|
from itertools import cycle
from unittest import TestCase, mock
import game
INPUT = mock.Mock()
@mock.patch('builtins.input', INPUT)
class GameTest(TestCase):
def setUp(self):
INPUT.reset_mock()
def test_join(self):
"""Players may join a game of Pig"""
pig = game.Pig('PlayerA', 'PlayerB', 'PlayerC')
self.assertEqual(pig.get_players(), ('PlayerA', 'PlayerB', 'PlayerC'))
def test_roll(self):
"""A roll of the die results in an integer between 1 and 6"""
pig = game.Pig('PlayerA', 'PlayerB')
for i in range(500):
r = pig.roll()
self.assertIsInstance(r, int)
self.assertTrue(1 <= r <= 6)
def test_scores(self):
"""Player scores can be retrieved"""
pig = game.Pig('PlayerA', 'PlayerB', 'PlayerC')
self.assertEqual(
pig.get_score(),
{
'PlayerA': 0,
'PlayerB': 0,
'PlayerC': 0
}
)
def test_get_player_names(self):
"""Players can enter their names"""
INPUT.side_effect = ['A', 'M', 'Z', '']
names = game.get_player_names()
self.assertEqual(names, ['A', 'M', 'Z'])
def test_get_player_names_stdout(self):
"""Check the prompts for player names"""
INPUT.side_effect = ['A', 'B', '']
game.get_player_names()
INPUT.assert_has_calls([
mock.call("Player 1's name: "),
mock.call("Player 2's name: "),
mock.call("Player 3's name: ")
])
def test_roll_or_hold(self):
"""Player can choose to roll or hold"""
INPUT.side_effect = ['R', 'H', 'h', 'z', '12345', 'r']
pig = game.Pig('PlayerA', 'PlayerB')
self.assertEqual(pig.roll_or_hold(), 'roll')
self.assertEqual(pig.roll_or_hold(), 'hold')
self.assertEqual(pig.roll_or_hold(), 'hold')
self.assertEqual(pig.roll_or_hold(), 'roll')
@mock.patch('builtins.print', mock.Mock())
def test_gameplay(self):
"""Users may play a game of Pig"""
INPUT.side_effect = [
# player names
'George',
'Bob',
'',
# roll or hold
'r', 'r', # George
'r', 'r', 'r', 'h', # Bob
'r', 'r', 'r', 'h', # George
]
pig = game.Pig(*game.get_player_names())
pig.roll = mock.Mock(side_effect=[
6, 6, 1, # George
6, 6, 6, 6, # Bob
5, 4, 3, 2, # George
])
self.assertRaises(StopIteration, pig.play)
self.assertEqual(
pig.get_score(),
{
'George': 14,
'Bob': 24
}
)
@mock.patch('builtins.print')
def test_winning(self, fake_print):
"""A player wins when they earn 100 points"""
INPUT.side_effect = [
# player names
'George',
'Bob',
'',
# roll or hold
'r', 'r', # George
]
pig = game.Pig(*game.get_player_names())
pig.roll = mock.Mock(side_effect=[2, 2])
pig.scores['George'] = 97
pig.scores['Bob'] = 96
pig.play()
self.assertEqual(
pig.get_score(),
{
'George': 101,
'Bob': 96
}
)
fake_print.assert_called_with('George won the game with 101 points!')
def test_command_line(self):
"""The game can be invoked from the command line"""
INPUT.side_effect = [
# player names
'George',
'Bob',
'',
# roll or hold
'r', 'r', 'h', # George
# Bob immediately rolls a 1
'r', 'h', # George
'r', 'r', 'h' # Bob
]
with mock.patch('builtins.print') as fake_print, \
mock.patch.object(game.Pig, 'roll') as die:
die.side_effect = cycle([6, 2, 5, 1, 4, 3])
self.assertRaises(StopIteration, game.main)
# check output
fake_print.assert_has_calls([
mock.call('Now rolling: George'),
mock.call('George rolled a 6 and now has 6 points for this turn'),
mock.call('George rolled a 2 and now has 8 points for this turn'),
mock.call('George rolled a 5 and now has 13 points for this turn'),
mock.call('Now rolling: Bob'),
mock.call('Bob rolled a 1 and lost 0 points'),
mock.call('Now rolling: George'),
mock.call('George rolled a 4 and now has 4 points for this turn'),
mock.call('George rolled a 3 and now has 7 points for this turn'),
mock.call('Now rolling: Bob'),
mock.call('Bob rolled a 6 and now has 6 points for this turn'),
mock.call('Bob rolled a 2 and now has 8 points for this turn'),
mock.call('Bob rolled a 5 and now has 13 points for this turn')
])
|