def test_scheme_extends_list(self): alpha, digit, max_len = ( AlphaValidator(), DigitValidator(), MaxLengthValidator(10), ) my_scheme = Scheme( validators=[alpha], correct_answers=["SchemeAnswer", "SchemeAnswer2"], commands=[Skip], ) empty_question = Question("What?", scheme=my_scheme) self.assertEqual([alpha], empty_question.validators) self.assertEqual([Skip], empty_question.commands) self.assertEqual( ["SchemeAnswer", "SchemeAnswer2"], empty_question.correct_answers ) question = Question( "What?", validators=[digit, max_len], correct_answers=["RealAnswer"], commands=[Skip], scheme=my_scheme, ) self.assertEqual([digit, max_len, alpha], question.validators) self.assertEqual([Skip, Skip], question.commands) self.assertEqual( ["RealAnswer", "SchemeAnswer", "SchemeAnswer2"], question.correct_answers, )
def test_done_ready_api(self): q1, q2, q3 = ( Question("What?"), Question("What?", required=False), Question("What?"), ) quiz = Quiz(questions=[q1, q2, q3]) self.assertFalse(quiz.is_ready) self.assertFalse(quiz.is_done) q1.answer = q3.answer = "A" self.assertFalse(quiz.is_ready) self.assertFalse(quiz.is_done) quiz.inquiries = 2 self.assertTrue(quiz.is_ready) self.assertFalse(quiz.is_done) q2.answer = "A" self.assertTrue(quiz.is_ready) self.assertTrue(quiz.is_done) q1.answer = None self.assertFalse(quiz.is_ready) self.assertFalse(quiz.is_done)
def test_finish_error_on_uncompleted(self, mock_stdout, *_): q1, q2, q3 = ( Question("Hello?"), Question("World?"), Question("Hey?", required=False), ) quiz = Quiz(questions=[q1, q2, q3]) quiz.start() mock_stdout.assert_has_calls( [ call( "There are still some required questions to answer: (1, 2)" ), ANY, ] ) self.assertEqual("Answer", q1.answer) self.assertEqual("Cat", q2.answer) self.assertIsNone(q3.answer) self.assertEqual(2, q1.attempt) self.assertEqual(1, q2.attempt) self.assertEqual(1, q3.attempt)
def test_answers(self, mock_stdout, *_): q1, q2, q3, q4 = ( Question("What?"), Question("How?"), Question("When?", required=False), MultipleChoiceQuestion("Which?", choices=["This"]), ) quiz = Quiz( questions=[q1, q2, q3, q4], scheme=Scheme(commands=[Answers, Finish]), ) quiz.start() mock_stdout.assert_has_calls( [ ANY, call( "\nCurrent answers:\n" "1. What? -> [Me]\n" "2. How? -> [Handsome]\n" "~3. When? -> [No answer]\n" "4. Which? -> [a) This]\n" ), ANY, ] )
def test_quit(self, *_): question = Question("What", commands=[Quit]) with self.assertRaises(SystemExit) as cm: question.ask() self.assertEqual(0, cm.exception.code)
def test_jump(self, mock_stdout, *_): q1, q2, q3, q4 = ( Question("What?"), MultipleChoiceQuestion("What?", choices=["a"], required=False), MultipleChoiceQuestion("What?", choices=["c"], required=False), Question("What?", required=False), ) quiz = Quiz( questions=[q1, q2, q3, q4], scheme=Scheme(commands=[Jump, Finish]) ) quiz.start() mock_stdout.assert_has_calls( [ call("Jumped to question 4."), call("Jumped to question 1."), call("Jumped to question 4."), call("Jumped to question 1."), ANY, ] ) self.assertEqual(3, q1.attempt) self.assertEqual(1, q2.attempt) self.assertEqual(2, q4.attempt) self.assertEqual(0, q3.attempt) self.assertEqual("Answer", q1.answer)
def test_command_strips(self, mock_stdout, *_): # Also tests: get_commands question = Question("What?", commands=[Help]) question.ask() mock_stdout.assert_called_with("Command not found: hello") self.assertEqual([Help], question.get_commands())
def test_quiz_inquiries_get_incremented(self, *_): questions = [Question("What?"), Question("Hello?")] quiz = Quiz(questions=questions) quiz.start() self.assertEqual(4, quiz.inquiries) self.assertEqual(sum(q.attempt for q in questions), quiz.inquiries)
def test_is_done(self, mock_stdout, *_): q1, q2, q3, q4 = ( Question("What?"), Question("What?"), Question("What?", required=False), Question("What?", required=False), ) q1.pre_ask = q2.pre_ask = ( lambda q: self.assertFalse(q.quiz.is_done) if q.attempt == 1 else self.assertTrue(q.quiz.is_done) ) q3.pre_ask = q4.pre_ask = lambda q: self.assertFalse(q.quiz.is_done) quiz = Quiz(questions=[q1, q2, q3, q4]) quiz.start() mock_stdout.assert_has_calls( [ call( "\nYou now have answered all the required questions on" " this test. You may finish, but There are still some" " optional questions left (3, 4).\n" ), call("\n[Ready, some optional questions left (4).]\n"), call( "\nYou now have answered all the questions on this test." " You may finish or revise your questions if you want.\n" ), call("\n[Completed, waiting for finish command.]\n"), ] )
def test_is_ready(self, mock_stdout, *_): q1, q2, q3, q4 = ( Question("What?"), Question("What?"), Question("What?", required=False), Question("What?", required=False), ) q1.pre_ask = lambda q: self.assertFalse(q.quiz.is_ready) q2.pre_ask = lambda q: self.assertFalse(q.quiz.is_ready) q3.pre_ask = lambda q: self.assertTrue(q.quiz.is_ready) q4.pre_ask = lambda q: self.assertTrue(q.quiz.is_ready) quiz = Quiz(questions=[q1, q2, q3, q4]) quiz.start() mock_stdout.assert_has_calls( [ call( "\nYou now have answered all the required questions on" " this test. You may finish, but There are still some" " optional questions left (3, 4).\n" ), call("\n[Ready, some optional questions left (4).]\n"), ] )
def test_command_no_context(self, mock_stdout, *_): question = Question("What?", required=False) question.ask() mock_stdout.assert_called_with( "Commands are disabled for this question." ) self.assertEqual("Answer", question.answer)
def test_help_no_command_list(self, mock_stdout, *_): question = Question( "What?", commands=[Help(message="Howdy?", with_command_list=False)] ) question.ask() mock_stdout.assert_called_with("Howdy?") self.assertEqual("Answer", question.answer)
def test_help_base(self, mock_stdout, *_): question = Question("What?", commands=[Help], required=False) question.ask() mock_stdout.assert_called_with( "\nAvailable commands are:\n!help: Shows the help message.\n" ) self.assertEqual("Answer", question.answer)
def test_skip(self, mock_stdout, *_): question = Question("Hello?", commands=[Skip], required=False) question.answer = "World" question.ask() mock_stdout.assert_called_with("You decided to skip this question.") self.assertIsNone(question.answer) self.assertEqual(1, question.attempt)
def test_required_retries(self, mock_stdout, *_): question = Question("What?") self.assertTrue(question.get_required()) question.ask() mock_stdout.assert_called_with("This question is required.") self.assertEqual("OK", question.answer) self.assertEqual(2, question.attempt)
def test_quiz_index_corresponds_question_sequence(self, *_): question = Question("What?") question1 = Question("Hello?") question.pre_ask = question1.pre_ask = lambda q: self.assertEqual( q.sequence, q.quiz.index ) quiz = Quiz(questions=[question, question1]) quiz.start()
def test_start(self, *_): q = Question("Hello?", required=False) q1 = Question("Hello?", required=False) quiz = Quiz(questions=[q, q1]) quiz.start() self.assertEqual(1, quiz.inquiries) self.assertEqual(1, q.attempt) self.assertEqual(0, q1.attempt)
def test_update_scheme_force(self): my_scheme = Scheme(commands=[Skip]) a, b = Question("a"), Question("b", scheme=my_scheme) quiz = Quiz(questions=[a], scheme=my_scheme) quiz.questions.append(b) quiz.update(force_scheme=True) self.assertEqual([my_scheme, my_scheme], b.mounted_schemes)
def test_update_scheme_force(self): my_scheme = Scheme(commands=[Jump]) question = Question("What?", scheme=my_scheme) self.assertEqual([my_scheme], question.mounted_schemes) question.update_scheme(my_scheme, force=True) self.assertEqual([my_scheme, my_scheme], question.mounted_schemes) self.assertEqual([Jump, Jump], question.commands)
def test_required_questions_and_min_inquiries(self): q = Question("Hello?") q1 = Question("Hello?", required=False) q2 = Question("Hello?") q3 = Question("Hello?") q4 = Question("Hello?", required=False) quiz = Quiz(questions=[q, q1, q2, q3, q4]) self.assertEqual([q, q2, q3], quiz.required_questions) self.assertEqual(3, quiz.min_inquiries)
def test_update_scheme_do_not_force(self): # Same scheme is not applied twice if force_scheme=False my_scheme = Scheme(commands=[Skip]) a, b = Question("a"), Question("b", scheme=my_scheme) quiz = Quiz(questions=[a], scheme=my_scheme) quiz.questions.append(b) quiz.update() self.assertEqual([my_scheme], b.mounted_schemes)
def test_strip(self, *_): question = Question("What?") self.assertTrue(question.get_strip()) question_no_strip = Question("What? 2", strip=False) self.assertFalse(question_no_strip.get_strip()) question.ask() question_no_strip.ask() self.assertEqual("spaced", question.answer) self.assertEqual(" spaced ", question_no_strip.answer)
def test_command_not_found(self, mock_stdout, *_): # Also tests: command delimiter & first word counts as expression question = Question("What?", command_delimiter="/", commands=[Help]) question.ask() mock_stdout.assert_has_calls( [ call("Command not found: hello"), call("Command not found: search"), ] ) self.assertEqual("Answer", question.answer)
def test_empty_scheme_has_no_effect(self): from quizz import _field_names # noqa empty = Scheme() question = Question("What?", scheme=empty) question_no_scheme = Question("What?") for name in _field_names: if hasattr(question_no_scheme, name): self.assertEqual( getattr(question_no_scheme, name), getattr(question, name) )
def test_scheme_extends_dict(self): my_scheme = Scheme(extra={"foo": "bar", "baz": "qux"}) question = Question("What?", scheme=my_scheme) question_with_extra = Question( "What?", extra={"hello": 5}, scheme=my_scheme ) self.assertEqual({"foo": "bar", "baz": "qux"}, question.extra) self.assertEqual( {"hello": 5, "foo": "bar", "baz": "qux"}, question_with_extra.extra, )
def test_skip_inoperative_for_required(self, mock_stdout, *_): question = Question("Hello?", commands=[Skip]) question.ask() mock_stdout.assert_has_calls( [ call("You decided to skip this question."), call("This question is required."), ] ) self.assertEqual("Answer", question.answer) self.assertEqual(2, question.attempt)
def test_command_opcode_break(self, *_): # Required question is break-able class Break(Command): expression = "break" def execute(self, question, *args): return opcodes.BREAK question_ = Question("What?", commands=[Break]) question_.ask() self.assertIsNone(question_.answer) self.assertEqual(1, question_.attempt)
def test_command_with_args(self, *_): class SetExtra(Command): expression = "set_extra" def execute(self, question, *args): question.extra[args[0]] = args[1] return opcodes.CONTINUE question_ = Question("What?", commands=[SetExtra]) question_.ask() self.assertEqual("meow", question_.extra["cat"]) self.assertEqual("Answer", question_.answer) self.assertEqual(2, question_.attempt)
def test_unimplemented_command(self, *_): class MyCommand(Command): # noqa expression = "test" pass self.assertEqual("No description provided.", MyCommand.description) question = Question("What?", commands=[MyCommand]) with self.assertRaisesRegex( NotImplementedError, "Define a behaviour for this command using execute method.", ): question.ask()
def test_update_manually(self): a, b = Question("A"), Question("B") quiz = Quiz(questions=[a]) quiz.questions.append(b) self.assertIsNone(b.quiz) self.assertEqual([a, b], quiz.required_questions) self.assertEqual(0, b.sequence) b.quiz = quiz # Manual assignment, instead of quiz.update() self.assertEqual(quiz, b.quiz) self.assertEqual(1, b.sequence) self.assertEqual([], b.mounted_schemes)