def test_run_dialog(self): """Test run_dialog properly handle order states""" states = 'idle', 'size_picked', 'payment_picked' handler_names = 'handle_idle', 'handle_size_pick', 'handle_payment_pick' matrix = [ (1, 0, 0), (1, 1, 0), (1, 1, 1), ] self.bot.get_value = M() self.bot.start_dialog(self.dialog) order, machine = self.bot.dialogs[self.dialog] # Patch handlers mocks = [] for handler_name in handler_names: m = M() mocks.append(m) setattr(self.bot, handler_name, m) # Do Checks for each of them for method, state, calls in zip(mocks, states, matrix): self.bot.get_value.return_value = value = object() order.state = state self.bot.run_dialog(self.dialog) self.assertEqual(method.call_args_list, [call(self.dialog, order, value)]) self.assertEqual(calls, tuple(m.call_count for m in mocks))
def test_get_value(self): self.bot.variants = { 'state_1': { 'kkz': 'l', 'mfp': 'n' }, 'state_2': { 'aek': 'b', 'chv': 'd' } } dialog = self.dialog order = M() order.state = 'state_1' self.bot.dialogs[dialog] = order, M() ''' None input - returns None Invalid(at all) input - returns INVALID Invalid(depending on state) input - returns INVALID Valid input - returns matching variant Valid(wrong case) input - returns matching variant ''' asserts = { None: None, 'dfkFFhk': self.bot.INVALID, 'aek': self.bot.INVALID, 'kkz': 'l', 'MFP': 'n', } for inp, out in asserts.items(): with self.subTest('Test get_value for input {}'.format(inp)): dialog.get_input.return_value = inp rv = self.bot.get_value(dialog) self.assertEqual(order.state, 'state_1') self.assertEqual(out, rv)
def test_handle_size_pick(self): ''' invalid - send_message, send_variants valid - set_payment, send_message ''' dialog = self.dialog positive_input = 3463 self.bot.send_variants = send_variants = M() order = M() order.size_description = 'kkkk' order.payment_description = 'fffffff' args = dict(pizza_size=order.size_description, payment_type=order.payment_description) mocks = dialog.send_message, send_variants, order.set_payment asserts = { self.bot.INVALID: [[call(self.bot.messages.get('pick_payment'))], [call(dialog)], []], positive_input: [[call(self.bot.messages.get('confirm_pick').format(**args))], [], [call(positive_input)]], } for chat_input, expected in asserts.items(): for mock in mocks: mock.reset_mock() with self.subTest( 'Test handle_size_pick against {}'.format(chat_input)): self.bot.handle_size_pick(dialog, order, chat_input) for mock, value in zip(mocks, expected): self.assertEqual(mock.call_args_list, value)
def test_handle_idle(self): order = M() self.bot.send_variants = send_variants = M() dialog = self.dialog positive_input = 12345 mocks = dialog.send_message, send_variants, order.set_size ignore = object() pick_size_call = call(self.bot.messages.get('pick_size')) pick_payment_call = call(self.bot.messages.get('pick_payment')) asserts = { # dialog.send_message, send_variants, order.set_size None: [[pick_size_call], [], []], self.bot.INVALID: [[pick_size_call], [call(self.dialog)], []], positive_input: [[pick_payment_call], [], [call.set_size(positive_input)]], } for chat_input, expected in asserts.items(): for mock in mocks: mock.reset_mock() with self.subTest( 'Test handle_idle against {}'.format(chat_input)): self.bot.handle_idle(dialog, order, chat_input) for mock, value in zip(mocks, expected): self.assertEqual(mock.call_args_list, value)
def test_handle_payment_pick(self): ''' invalid - send_message,send_variants valid - confirm, start_dialog, send_message valid(is_confirmed) - confirm, send_message, create_order, start_dialog, send_message ''' dialog = self.dialog positive_input = 3463 positive_input_2 = 5683 self.bot.send_variants = send_variants = M() self.bot.start_dialog = start_dialog = M() order = M() order.size_description = 'afks' order.payment_description = 'fjdrt5' args = dict(pizza_size=order.size_description, payment_type=order.payment_description) mocks = dialog.send_message, send_variants, order.confirm,\ self.bot_manager.create_order, start_dialog # TODO: Complete test case asserts = { self.bot.INVALID: [ [call(self.bot.messages.get('confirm_pick').format(**args))], [call(dialog)], [], [], [], ], positive_input: [ [call(self.bot.messages.get('pick_size'))], [], [call(positive_input)], [], [call(dialog)], ], positive_input_2: [ [ call(self.bot.messages.get('success')), call(self.bot.messages.get('pick_size')) ], [], [call(positive_input_2)], [call(dialog, order)], [call(dialog)], ], } for chat_input, expected in asserts.items(): for mock in mocks: mock.reset_mock() with self.subTest( 'Test handle_payment_pick against {}'.format(chat_input)): order.is_confirmed = chat_input == positive_input_2 self.bot.handle_payment_pick(dialog, order, chat_input) for mock, value in zip(mocks, expected): self.assertEqual(mock.call_args_list, value)
def test_process_update(self): mocker = M() update = mocker.update chat = object() message = object() mocker.time.return_value = time_value = object() time_patch = patch('pizza_bot.telegram_chat.time.time', new=mocker.time) time_patch.start() asserts = { 'fails on wrong message': { 'message': None, 'chat': None, 'exc': TypeError('Update with empty message') }, 'fails on wrong chat': { 'message': M(text=object(), chat_id=chat), 'chat': object(), 'exc': TypeError('Chat integrity error') }, 'succeeds with chat assigned': { 'message': M(text=message, chat_id=chat), 'chat': None, 'exc': None }, 'succeeds without chat assigned': { 'message': M(text=message, chat_id=chat), 'chat': chat, 'exc': None }, } for title, case in asserts.items(): with self.subTest('Test process_update {}'.format(title)): mocker.reset_mock() update.message = case['message'] self.dialog.chat = case['chat'] self.dialog.message = None self.dialog.last_received = None if case['exc']: with self.assertRaises(TypeError) as cm: self.dialog.process_update(update) self.assertEqual(cm.exception.args, case['exc'].args) else: self.dialog.process_update(update) self.assertEqual(chat, self.dialog.chat) self.assertEqual(message, self.dialog.message) self.assertEqual(time_value, self.dialog.last_received) if case['chat'] is None: self.assertIs(chat, self.dialog.chat) time_patch.stop()
def test_create_order(self): dialog = M() order = M() order.pizza_size = 'hsdfh' order.payment_method = 'fdgjjfg' order.is_confirmed = 'serhs' expected_output = ('Order created:\n' '\tPizza size: {}\n' '\tPayment type: {}\n' '\tOrder confirmed: {}\n' '\n').format(order.pizza_size, order.payment_method, order.is_confirmed) with patch('sys.stdout', new_callable=io.StringIO) as cm: self.manager.create_order(dialog, order) output = cm.getvalue() self.assertEqual(output, expected_output)
def test_send_variants(self): self.bot.variants = { 's': { 'k': 'l', 'm': 'n' }, 'p': { 'a': 'b', 'c': 'd' } } order, machine = M(), M() order.state = 's' self.bot.messages = {'please_repeat': 'hhh{variants}ooo'} self.bot.dialogs[self.dialog] = order, machine self.bot.send_variants(self.dialog) assert self.dialog.send_message.call_args_list == [call('hhhk, mooo')]
def test_on_chat_start(self): mock = M() self.bot.start_dialog = mock.start_dialog self.bot.run_dialog = mock.run_dialog self.bot.on_chat_start(self.dialog) assert mock.method_calls == [ call.start_dialog(self.dialog), call.run_dialog(self.dialog), ]
def test_on_chat_exit(self): self.bot.log = log = M() self.bot.delete_dialog = delete_dialog = M() with self.subTest('Test on_chat_exit fails'): self.bot.on_chat_exit(self.dialog) # Assert assert log.call_args_list == [ call('Exit received from wrong dialog: {}'.format(self.dialog)) ] assert delete_dialog.call_count == 0 # Reset log.reset_mock(), delete_dialog.reset_mock() self.bot.dialogs[self.dialog] = M(), M() with self.subTest('Test on_chat_exit passes'): self.bot.on_chat_exit(self.dialog) # Assert assert log.call_count == 0 assert delete_dialog.call_args_list == [call(self.dialog)]
def test_on_chat_input(self): self.bot.log = log = M() self.bot.run_dialog = run_dialog = M() with self.subTest('Test on_chat_input fails'): self.bot.on_chat_input(self.dialog) # Assert assert log.call_args_list == [ call('Input received from wrong dialog: {}'.format( self.dialog)) ] assert run_dialog.call_count == 0 # Reset log.reset_mock(), run_dialog.reset_mock() self.bot.dialogs[self.dialog] = M(), M() with self.subTest('Test on_chat_input passes'): self.bot.on_chat_input(self.dialog) # Assert assert log.call_count == 0 assert run_dialog.call_args_list == [call(self.dialog)]
def test_run_chat(self): ''' fails on on_chat_start with exception logged, and on_chat_exit passes with: run_chat_cycle called in loop and on_chat_exit called after ''' type_err = TypeError() mocker = M() self.bot.on_chat_start = mocker.on_chat_start self.bot.on_chat_exit = mocker.on_chat_exit self.dialog.run_chat_cycle = mocker.run_chat_cycle mocker.run_chat_cycle.side_effect = [True, True, False] asserts = { 'fail on on_chat_start': { 'fails': True, 'calls': [ call.on_chat_start(self.dialog), call.logging.exception(type_err), call.on_chat_exit(self.dialog), ] }, 'succeeds': { 'fails': False, 'calls': [ call.on_chat_start(self.dialog), call.run_chat_cycle(), call.run_chat_cycle(), call.run_chat_cycle(), call.on_chat_exit(self.dialog), ] }, } with patch('pizza_bot.console_chat.logging', new=mocker.logging): for title, case in asserts.items(): mocker.reset_mock() with self.subTest('Test run_chat {}'.format(title)): mocker.on_chat_start.side_effect = type_err if case[ 'fails'] else None self.dialog.run_chat() self.assertListEqual(mocker.method_calls, case['calls'])
def test_process_messages(self): mocker = M() self.dialog.reinit_chat = mocker.reinit_chat messages = 'abc def ghi'.split() last_message = messages[-1] output = '\n{}\n'.format('\n'.join(messages[:-1])) asserts = { 'process_messages with reinit': { 'no_messages': True, 'calls': [ call.logging.error('No messages for sending!!!'), call.reinit_chat(), ] }, 'regular process_messages': { 'no_messages': False, 'calls': [] } } extend = lambda: self.dialog.messages.extend(messages) with patch('pizza_bot.console_chat.logging', new=mocker.logging): for title, case in asserts.items(): mocker.reset_mock() self.dialog.messages = [] if case['no_messages']: mocker.reinit_chat.side_effect = extend else: extend() with self.subTest('Test {} call'.format(title)),\ patch('sys.stdout', new_callable=io.StringIO) as cm: rv = self.dialog.process_messages() self.assertEqual(rv, messages[-1]) self.assertListEqual(mocker.method_calls, case['calls']) self.assertListEqual(self.dialog.messages, []) self.assertEqual(cm.getvalue(), output)
def test_run_chat_cycle(self): input_value = object() mocker = M() self.dialog.process_messages = mocker.process_messages self.dialog.reinit_chat = mocker.reinit_chat self.bot.on_chat_input = mocker.on_chat_input mocker.process_messages.return_value = last_message = 'sjstrjstj' type_err = TypeError() asserts = { 'fails': { 'return_value': False, 'input': False, 'on_chat_input': False, 'calls': [ call.process_messages(), call.input('{}:\n'.format(last_message)), ], }, 'succeeds with chat reinit': { 'return_value': True, 'input': True, 'on_chat_input': True, 'calls': [ call.process_messages(), call.input('{}:\n'.format(last_message)), call.on_chat_input(self.dialog), call.logging.exception(type_err), call.reinit_chat(), ], }, 'succeeds': { 'return_value': True, 'input': True, 'on_chat_input': False, 'calls': [ call.process_messages(), call.input('{}:\n'.format(last_message)), call.on_chat_input(self.dialog), ], }, } with patch('pizza_bot.console_chat.logging', new=mocker.logging),\ patch('builtins.input', new=mocker.input): for title, case in asserts.items(): mocker.reset_mock() with self.subTest('Test run_chat_cycle {}'.format(title)): mocker.on_chat_input.side_effect = type_err if case[ 'on_chat_input'] else None mocker.input.return_value = input_value if case[ 'input'] else None mocker.input.side_effect = None if case[ 'input'] else KeyboardInterrupt with patch('builtins.input', new=mocker.input): rv = self.dialog.run_chat_cycle() self.assertListEqual(mocker.method_calls, case['calls']) self.assertEqual(case['return_value'], rv)
def setUp(self): self.bot = M() self.maxDiff = None self.dialog = ConsoleDialog(self.bot)
def test_delete_dialog(self): it = M() self.bot.dialogs[it] = it self.bot.delete_dialog(it) assert it not in self.bot.dialogs
def setUp(self): self.bot = M() self.dialog = TelegramDialog(self.bot)
def setUp(self): self.bot_manager = M() self.dialog = M() self.bot = PizzaBot(self.bot_manager)