diff --git a/mathstack/models.py b/mathstack/models.py index 359e421..e70014d 100644 --- a/mathstack/models.py +++ b/mathstack/models.py @@ -2,7 +2,6 @@ from api import models as api_models from django.contrib.auth.signals import user_logged_in -from django.core.exceptions import ObjectDoesNotExist from django.db import models from django.dispatch import receiver @@ -10,6 +9,10 @@ class BooleanQuestion(models.Model): """ A model for storing YES/NO math questions """ + DIVISORS = [2, 3, 4, 5, 6, 9] + LOWER = 10 + UPPER = 5000 + MODULUS = "MODULUS" OP_CHOICES = [(MODULUS, "%")] operand1 = models.IntegerField() @@ -18,7 +21,7 @@ class BooleanQuestion(models.Model): correct_answer = models.BooleanField() def __str__(self): - return "{} {} {} == 0".format(self.operand1, self.operator, self.operand2) + return "{} {} {} == 0".format(self.operand1, self.get_operator_display(), self.operand2) def save(self, *args, **kwargs): self.correct_answer = self.compute_answer() @@ -37,17 +40,14 @@ def compute_answer(self): @staticmethod def get_divisor(): - DIVISORS = [2, 3, 4, 5, 6, 9] - return random.choice(DIVISORS) + return random.choice(BooleanQuestion.DIVISORS) @staticmethod def generate_question(): """ Method to generate a random math question and update the ActiveQuestion accordingly. Presently generates divisibility questions only. """ - LOWER = 10 - UPPER = 5000 - op1 = random.randint(LOWER, UPPER) + op1 = random.randint(BooleanQuestion.LOWER, BooleanQuestion.UPPER) op2 = BooleanQuestion.get_divisor() q = BooleanQuestion.objects.create(operand1=op1, operand2=op2, operator=BooleanQuestion.MODULUS) return q @@ -106,10 +106,9 @@ def __str__(self): @receiver(user_logged_in) def populate_active_question(sender, user, request, **kwargs): - pass - # if hasattr(user, 'student'): - # # check for an existing `ActiveQuestion` - # q = ActiveQuestion.objects.filter(student=user.student).first() - # if not q: - # ActiveQuestion.objects.create( - # student=user.student, question=BooleanQuestion.generate_question()) + if hasattr(user, 'student'): + # check for an existing `ActiveQuestion` + q = ActiveQuestion.objects.filter(student=user.student).first() + if not q: + ActiveQuestion.objects.create( + student=user.student, question=BooleanQuestion.generate_question()) diff --git a/mathstack/tests/test_helpers.py b/mathstack/tests/test_helpers.py index 04bc991..205f93b 100644 --- a/mathstack/tests/test_helpers.py +++ b/mathstack/tests/test_helpers.py @@ -18,6 +18,6 @@ class LoggedInStudentTestCase(TestCase): # the base class -- contains no tests def setUp(self): self.user = UserFactory() - self.teacher = StudentFactory(user=self.user) + self.student = StudentFactory(user=self.user) self.client = Client() self.client.login(username=self.user.username, password=PASSWORD) diff --git a/mathstack/tests/test_models.py b/mathstack/tests/test_models.py new file mode 100644 index 0000000..c5c6282 --- /dev/null +++ b/mathstack/tests/test_models.py @@ -0,0 +1,46 @@ +""" test_models.py for the MATHSTACK app + + To run these tests, from an activated virtualenv run this command: + + python manage.py test --keepdb +""" + +from django.test import TestCase + +from mathstack import models as mathstack_models +import mathstack.tests.factories as mathstack_factories + + +class TestBooleanQuestion(TestCase): + + def setUp(self): + super(TestBooleanQuestion, self).setUp() + self.question = mathstack_factories.BooleanQuestionFactory() + + def test_str(self): + self.assertEqual('1000 % 5 == 0', str(self.question)) + + def test_compute_answer(self): + answer = self.question.compute_answer() + self.assertTrue(answer, '{} should be True'.format(self.question)) + + def test_compute_answer_invalid_operator(self): + question = mathstack_factories.BooleanQuestionFactory() + question.operator = '/' + + try: + question.compute_answer() + self.fail('Should not be able to compute answer for invalid operator') + except RuntimeError as e: + self.assertEqual("Unknown question operator '/'.", str(e)) + + def test_get_divisor(self): + divisor = mathstack_models.BooleanQuestion.get_divisor() + self.assertIn(divisor, mathstack_models.BooleanQuestion.DIVISORS) + + def test_generate_question(self): + question = mathstack_models.BooleanQuestion.generate_question() + self.assertGreaterEqual(question.operand1, mathstack_models.BooleanQuestion.LOWER) + self.assertLess(question.operand1, mathstack_models.BooleanQuestion.UPPER) + self.assertEqual(question.operator, mathstack_models.BooleanQuestion.MODULUS) + self.assertIn(question.operand2, mathstack_models.BooleanQuestion.DIVISORS) diff --git a/mathstack/tests/test_views.py b/mathstack/tests/test_views.py index 58bab05..4fa193c 100644 --- a/mathstack/tests/test_views.py +++ b/mathstack/tests/test_views.py @@ -6,6 +6,7 @@ """ from django.shortcuts import reverse +from api.tests import factories as api_factories import mathstack.tests.factories as mathstack_factories from mathstack.tests.test_helpers import LoggedInStudentTestCase @@ -17,9 +18,40 @@ def setUp(self): self.url = reverse("bool_answer_create") self.active_q = mathstack_factories.ActiveQuestionFactory() + def test_bool_answer_create_get_not_student(self): + user = api_factories.UserFactory() + self.client.login(username=user.username, password=api_factories.PASSWORD) + + response = self.client.get(self.url) + + self.assertEqual(404, response.status_code) + def test_bool_answer_create_get(self): response = self.client.get(self.url) self.assertContains( response, "

Math Practice Page

") + + def test_bool_answer_create_post(self): + data = { + } + + original_active_question_id = self.student.activequestion_set.first().id + num_answers_before = self.student.booleananswer_set.count() + + response = self.client.post(self.url, data=data, follow=True) + + self.assertEqual(200, response.status_code) + self.assertEqual([('/math/div/', 302)], response.redirect_chain) + + updated_active_question = self.student.activequestion_set.first() + num_answers_after = self.student.booleananswer_set.count() + self.assertEqual(num_answers_after, num_answers_before + 1) + self.assertNotEqual(original_active_question_id, + updated_active_question.question.id, + "Question should be updated when answer is submitted") + + self.assertContains( + response, + "

Math Practice Page

") diff --git a/mathstack/views.py b/mathstack/views.py index 606b0c6..2f8e69e 100644 --- a/mathstack/views.py +++ b/mathstack/views.py @@ -10,8 +10,8 @@ class StudentOnlyMixin(LoginRequiredMixin): def get_context_data(self, **kwargs): context = super(StudentOnlyMixin, self).get_context_data(**kwargs) - #if not hasattr(self.request.user, "student") or self.request.user.student is None: - # raise Http404() + if not hasattr(self.request.user, "student") or self.request.user.student is None: + raise Http404() return context