Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
688 changes: 688 additions & 0 deletions cms/djangoapps/content_testing/models.py

Large diffs are not rendered by default.

Empty file.
869 changes: 869 additions & 0 deletions cms/djangoapps/content_testing/tests/test_model.py

Large diffs are not rendered by default.

302 changes: 302 additions & 0 deletions cms/djangoapps/content_testing/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,302 @@
"""
Tests for the views involved in content testing.
"""

from contentstore.tests.test_course_settings import CourseTestCase
from xmodule.modulestore.tests.factories import ItemFactory
from capa.tests.response_xml_factory import CustomResponseXMLFactory
from content_testing.models import ContentTest
from content_testing.views import getprompt, add_contenttest_to_descriptor, delete_contenttest
from xmodule.modulestore.django import modulestore
from textwrap import dedent
from lxml import etree
from django.http import Http404


# disable sillly pylint violations
# pylint: disable=W0212
# pylint: disable=W0201
class ContentTestViewTestCase (CourseTestCase):
"""
Tests for the views involved in the automated content testing
"""

SCRIPT = dedent("""
def is_prime (n):
primality = True
for i in range(2,int(math.sqrt(n))+1):
if n%i == 0:
primality = False
break
return primality

def test_prime(expect,ans):
a1=int(ans)
return is_prime(a1)""").strip()

def setUp(self):
"""
override parent setUp to put a problem in that course
"""

super(ContentTestViewTestCase, self).setUp()

#change the script if 1
problem_xml = CustomResponseXMLFactory().build_xml(
script=self.SCRIPT,
cfn='test_prime')

self.problem = ItemFactory.create(
parent_location=self.course.location,
data=problem_xml,
category='problem')

# format as if it came from the form generated by the capa_problem
# sigh
self.input_id_base = self.problem.id.replace('://', '-').replace('/', '-')

self.url = "/test_problem/"
self.loc = self.problem.location.url()

# add a @draft thing, so it doesn't change to that half way through
modulestore().update_metadata(self.loc, {'tests': []})

def create_model(self):
"""
helper method to add a content test to the database
"""

# saved responses for making tests
self.response_dict_correct = {
self.input_id_base + '-draft_2_1': '174440041'
}

self.response_dict_incorrect = {
self.input_id_base + '-draft_2_1': '6'
}

self.pass_correct = ContentTest(
location=self.loc,
should_be='correct',
response_dict=self.response_dict_correct
)

# save the test
modulestore().update_metadata(self.loc, {'tests': [self.pass_correct.todict()]})

# update self.problem to reflect the change
self.problem = modulestore().get_item(self.problem.location)

def check_no_contenttests(self):
"""
check that there are no tests in this summary
"""

descriptor = modulestore().get_item(self.problem.location)
self.assertEqual(len(descriptor.tests), 0)

def check_exist_contenttest(self):
"""
check that there are tests in the summary view
"""

descriptor = modulestore().get_item(self.problem.location)
self.assertEqual(len(descriptor.tests), 1)

# also, chack that it was saved "fully", with all the data that gets
# calculated on instantiation (necessary for future rematching)
for test in descriptor.tests:
assert 'responses' in test



class ContentTestDispatchTestCase(ContentTestViewTestCase):

def test_no_tests(self):
"""
test that initially there are no tests for the problem
"""

response = self.client.get(self.url, {'location': self.loc})
self.check_no_contenttests()
self.assertEqual(response.status_code, 200)

def test_create(self):
"""
test that saving a new test works
"""

# format the response that the capa problem generates
input_id = 'input_' + self.input_id_base + '_2_1'
post_data = {
'location': self.loc,
'should_be': 'correct',
input_id: '5'
}

response = self.client.post(self.url, post_data, follow=True)

# ceck that there is now one test.
self.check_exist_contenttest()
self.assertEqual(response.status_code, 200)

def test_delete(self):
"""
test that the delete works
"""

self.create_model()
model_id = self.problem.tests[0]['id']

req_data = {
'id_to_delete': model_id,
'location': self.loc
}

response = self.client.delete(self.url, req_data)

self.check_no_contenttests()
self.assertEqual(response.status_code, 200)

def test_summary(self):
"""
Test that the main render is done properly
"""

self.create_model()

response = self.client.get(self.url, {'location': self.loc})

assert ContentTest.NONE.lower() in response.content.lower()

def test_run(self):
"""
Test running tests
"""

self.create_model()

# run the test, and see that result is persistant
response1 = self.client.post(self.url, {'location': self.loc, 'run': 'yup'})
response2 = self.client.get(self.url, {'location': self.loc})

assert ContentTest.PASS.lower() in response2.content.lower()
self.assertEqual(response1.status_code, 200)

def test_404_without_location(self):
"""
Test raises 404 when not passed location
"""

response = self.client.post(self.url)
self.assertEqual(response.status_code, 404)


class HelpFuncTestCase(ContentTestViewTestCase):

def test_getprompt_parent(self):

xml_string = dedent("""
<root>
<intro/>
<child>
<blob/>
</child>
</root>
""")

xml = etree.XML(xml_string)
intro = xml[0]
blob = xml[1][0]

self.assertEqual(getprompt(blob), intro)

def test_getprompt_sib(self):

xml_string = dedent("""
<root>
<intro/>
<child>
<blob/>
</child>
</root>
""")

xml = etree.XML(xml_string)
intro = xml[0]
child = xml[1]

self.assertEqual(getprompt(child), intro)

def test_getprompt_none(self):

xml_string = dedent("""
<root>
<child>
<blob/>
</child>
</root>
""")

xml = etree.XML(xml_string)
blob = xml[0][0]

self.assertEqual(getprompt(blob), None)

def test_add_to_descriptor(self):
"""
Test the function for incrementing id's.
"""
self.create_model()

# add a few tests
num_tests = 5
for i in range(num_tests-1):
add_contenttest_to_descriptor(self.problem, self.pass_correct.todict())

# refetch problem form database to see changes
problem = modulestore().get_item(self.problem.location)

test_ids = [test['id'] for test in problem.tests]

# asserts that there are `num_tests`, and each has different ids
self.assertEqual(len(problem.tests), num_tests)
assert len(test_ids) == len(set(test_ids))

def test_delete_contenttest(self):
"""
Test deleteing tests by id works
"""
self.create_model()

# add a few tests
num_tests = 5
for i in range(num_tests-1):
add_contenttest_to_descriptor(self.problem, self.pass_correct.todict())

# delete the test
delete_contenttest(self.problem, self.problem.tests[0]['id'])

# re-fetch descriptor
self.problem = modulestore().get_item(self.problem.location)

self.assertEqual(len(self.problem.tests), num_tests-1)

def test_delete_404_no_tests(self):
"""
Test that delete complains when deleting tests when there are no tests
"""

# delete the test
self.assertRaises(Http404, delete_contenttest, self.problem, 0)

def test_delete_404_exist_tests(self):
"""
Test that when there are tests, deleting a test that doesn't exits
cuases error
"""

self.create_model()

# delete the test
self.assertRaises(Http404, delete_contenttest, self.problem, 3)
Loading