Commit 8e93e077 by Victor Shnayder

Merge pull request #1509 from MITx/feature/victor/capa-finished

Add showanswer="finished" option and tests
parents ff35d3e6 a4ee057d
...@@ -429,6 +429,11 @@ class CapaModule(XModule): ...@@ -429,6 +429,11 @@ class CapaModule(XModule):
# used by conditional module # used by conditional module
return self.attempts > 0 return self.attempts > 0
def is_correct(self):
"""True if full points"""
d = self.get_score()
return d['score'] == d['total']
def answer_available(self): def answer_available(self):
''' '''
Is the user allowed to see an answer? Is the user allowed to see an answer?
...@@ -449,6 +454,9 @@ class CapaModule(XModule): ...@@ -449,6 +454,9 @@ class CapaModule(XModule):
return self.lcp.done return self.lcp.done
elif self.show_answer == 'closed': elif self.show_answer == 'closed':
return self.closed() return self.closed()
elif self.show_answer == 'finished':
return self.closed() or self.is_correct()
elif self.show_answer == 'past_due': elif self.show_answer == 'past_due':
return self.is_past_due() return self.is_past_due()
elif self.show_answer == 'always': elif self.show_answer == 'always':
......
...@@ -42,6 +42,7 @@ class CapaFactory(object): ...@@ -42,6 +42,7 @@ class CapaFactory(object):
force_save_button=None, force_save_button=None,
attempts=None, attempts=None,
problem_state=None, problem_state=None,
correct=False
): ):
""" """
All parameters are optional, and are added to the created problem if specified. All parameters are optional, and are added to the created problem if specified.
...@@ -58,6 +59,7 @@ class CapaFactory(object): ...@@ -58,6 +59,7 @@ class CapaFactory(object):
module. module.
attempts: also added to instance state. Will be converted to an int. attempts: also added to instance state. Will be converted to an int.
correct: if True, the problem will be initialized to be answered correctly.
""" """
definition = {'data': CapaFactory.sample_problem_xml, } definition = {'data': CapaFactory.sample_problem_xml, }
location = Location(["i4x", "edX", "capa_test", "problem", location = Location(["i4x", "edX", "capa_test", "problem",
...@@ -81,10 +83,19 @@ class CapaFactory(object): ...@@ -81,10 +83,19 @@ class CapaFactory(object):
instance_state_dict = {} instance_state_dict = {}
if problem_state is not None: if problem_state is not None:
instance_state_dict = problem_state instance_state_dict = problem_state
if attempts is not None: if attempts is not None:
# converting to int here because I keep putting "0" and "1" in the tests # converting to int here because I keep putting "0" and "1" in the tests
# since everything else is a string. # since everything else is a string.
instance_state_dict['attempts'] = int(attempts) instance_state_dict['attempts'] = int(attempts)
if correct:
# TODO: make this actually set an answer of 3.14, and mark it correct
#instance_state_dict['student_answers'] = {}
#instance_state_dict['correct_map'] = {}
pass
if len(instance_state_dict) > 0: if len(instance_state_dict) > 0:
instance_state = json.dumps(instance_state_dict) instance_state = json.dumps(instance_state_dict)
else: else:
...@@ -94,13 +105,16 @@ class CapaFactory(object): ...@@ -94,13 +105,16 @@ class CapaFactory(object):
definition, descriptor, definition, descriptor,
instance_state, None, metadata=metadata) instance_state, None, metadata=metadata)
if correct:
# TODO: probably better to actually set the internal state properly, but...
module.get_score = lambda: {'score': 1, 'total': 1}
return module return module
class CapaModuleTest(unittest.TestCase): class CapaModuleTest(unittest.TestCase):
def setUp(self): def setUp(self):
now = datetime.datetime.now() now = datetime.datetime.now()
day_delta = datetime.timedelta(days=1) day_delta = datetime.timedelta(days=1)
...@@ -120,6 +134,18 @@ class CapaModuleTest(unittest.TestCase): ...@@ -120,6 +134,18 @@ class CapaModuleTest(unittest.TestCase):
self.assertNotEqual(module.url_name, other_module.url_name, self.assertNotEqual(module.url_name, other_module.url_name,
"Factory should be creating unique names for each problem") "Factory should be creating unique names for each problem")
def test_correct(self):
"""
Check that the factory creates correct and incorrect problems properly.
"""
module = CapaFactory.create()
self.assertEqual(module.get_score()['score'], 0)
other_module = CapaFactory.create(correct=True)
self.assertEqual(other_module.get_score()['score'], 1)
def test_showanswer_default(self): def test_showanswer_default(self):
""" """
Make sure the show answer logic does the right thing. Make sure the show answer logic does the right thing.
...@@ -178,7 +204,7 @@ class CapaModuleTest(unittest.TestCase): ...@@ -178,7 +204,7 @@ class CapaModuleTest(unittest.TestCase):
for everyone--e.g. after due date + grace period. for everyone--e.g. after due date + grace period.
""" """
# can see after attempts used up, even with due date in the future # can't see after attempts used up, even with due date in the future
used_all_attempts = CapaFactory.create(showanswer='past_due', used_all_attempts = CapaFactory.create(showanswer='past_due',
max_attempts="1", max_attempts="1",
attempts="1", attempts="1",
...@@ -209,3 +235,50 @@ class CapaModuleTest(unittest.TestCase): ...@@ -209,3 +235,50 @@ class CapaModuleTest(unittest.TestCase):
due=self.yesterday_str, due=self.yesterday_str,
graceperiod=self.two_day_delta_str) graceperiod=self.two_day_delta_str)
self.assertFalse(still_in_grace.answer_available()) self.assertFalse(still_in_grace.answer_available())
def test_showanswer_finished(self):
"""
With showanswer="finished" should show answer after the problem is closed,
or after the answer is correct.
"""
# can see after attempts used up, even with due date in the future
used_all_attempts = CapaFactory.create(showanswer='finished',
max_attempts="1",
attempts="1",
due=self.tomorrow_str)
self.assertTrue(used_all_attempts.answer_available())
# can see after due date
past_due_date = CapaFactory.create(showanswer='finished',
max_attempts="1",
attempts="0",
due=self.yesterday_str)
self.assertTrue(past_due_date.answer_available())
# can't see because attempts left and wrong
attempts_left_open = CapaFactory.create(showanswer='finished',
max_attempts="1",
attempts="0",
due=self.tomorrow_str)
self.assertFalse(attempts_left_open.answer_available())
# _can_ see because attempts left and right
correct_ans = CapaFactory.create(showanswer='finished',
max_attempts="1",
attempts="0",
due=self.tomorrow_str,
correct=True)
self.assertTrue(correct_ans.answer_available())
# Can see even though grace period hasn't expired, because have no more
# attempts.
still_in_grace = CapaFactory.create(showanswer='finished',
max_attempts="1",
attempts="1",
due=self.yesterday_str,
graceperiod=self.two_day_delta_str)
self.assertTrue(still_in_grace.answer_available())
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment