Commit 488923fd by Ned Batchelder

Add a test for Django-based file uploads to problems.

parent 0684f6a4
...@@ -314,24 +314,43 @@ class CodeResponseXMLFactory(ResponseXMLFactory): ...@@ -314,24 +314,43 @@ class CodeResponseXMLFactory(ResponseXMLFactory):
return super(CodeResponseXMLFactory, self).build_xml(**kwargs) return super(CodeResponseXMLFactory, self).build_xml(**kwargs)
def create_response_element(self, **kwargs): def create_response_element(self, **kwargs):
""" Create a <coderesponse> XML element: """
Create a <coderesponse> XML element.
Uses **kwargs: Uses **kwargs:
*initial_display*: The code that initially appears in the textbox
[DEFAULT: "Enter code here"]
*answer_display*: The answer to display to the student
[DEFAULT: "This is the correct answer!"]
*grader_payload*: A JSON-encoded string sent to the grader
[DEFAULT: empty dict string]
*allowed_files*: A space-separated string of file names.
[DEFAULT: None]
*required_files*: A space-separated string of file names.
[DEFAULT: None]
*initial_display*: The code that initially appears in the textbox
[DEFAULT: "Enter code here"]
*answer_display*: The answer to display to the student
[DEFAULT: "This is the correct answer!"]
*grader_payload*: A JSON-encoded string sent to the grader
[DEFAULT: empty dict string]
""" """
# Get **kwargs # Get **kwargs
initial_display = kwargs.get("initial_display", "Enter code here") initial_display = kwargs.get("initial_display", "Enter code here")
answer_display = kwargs.get("answer_display", "This is the correct answer!") answer_display = kwargs.get("answer_display", "This is the correct answer!")
grader_payload = kwargs.get("grader_payload", '{}') grader_payload = kwargs.get("grader_payload", '{}')
allowed_files = kwargs.get("allowed_files", None)
required_files = kwargs.get("required_files", None)
# Create the <coderesponse> element # Create the <coderesponse> element
response_element = etree.Element("coderesponse") response_element = etree.Element("coderesponse")
# If files are involved, create the <filesubmission> element.
has_files = allowed_files or required_files
if has_files:
filesubmission_element = etree.SubElement(response_element, "filesubmission")
if allowed_files:
filesubmission_element.set("allowed_files", allowed_files)
if required_files:
filesubmission_element.set("required_files", required_files)
# Create the <codeparam> element.
codeparam_element = etree.SubElement(response_element, "codeparam") codeparam_element = etree.SubElement(response_element, "codeparam")
# Set the initial display text # Set the initial display text
...@@ -347,8 +366,9 @@ class CodeResponseXMLFactory(ResponseXMLFactory): ...@@ -347,8 +366,9 @@ class CodeResponseXMLFactory(ResponseXMLFactory):
grader_element.text = str(grader_payload) grader_element.text = str(grader_payload)
# Create the input within the response # Create the input within the response
input_element = etree.SubElement(response_element, "textbox") if not has_files:
input_element.set("mode", "python") input_element = etree.SubElement(response_element, "textbox")
input_element.set("mode", "python")
return response_element return response_element
......
...@@ -2,8 +2,12 @@ ...@@ -2,8 +2,12 @@
# text processing dependancies # text processing dependancies
import json import json
import os
from textwrap import dedent from textwrap import dedent
from mock import patch
from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.test.client import RequestFactory from django.test.client import RequestFactory
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
...@@ -18,7 +22,10 @@ from xmodule.modulestore.django import modulestore, editable_modulestore ...@@ -18,7 +22,10 @@ from xmodule.modulestore.django import modulestore, editable_modulestore
#import factories and parent testcase modules #import factories and parent testcase modules
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from capa.tests.response_xml_factory import OptionResponseXMLFactory, CustomResponseXMLFactory, SchematicResponseXMLFactory from capa.tests.response_xml_factory import (
OptionResponseXMLFactory, CustomResponseXMLFactory, SchematicResponseXMLFactory,
CodeResponseXMLFactory,
)
from courseware.tests.helpers import LoginEnrollmentTestCase from courseware.tests.helpers import LoginEnrollmentTestCase
from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE from courseware.tests.modulestore_config import TEST_DATA_MIXED_MODULESTORE
from lms.lib.xblock.runtime import quote_slashes from lms.lib.xblock.runtime import quote_slashes
...@@ -547,6 +554,58 @@ class TestCourseGrader(TestSubmittingProblems): ...@@ -547,6 +554,58 @@ class TestCourseGrader(TestSubmittingProblems):
self.assertEqual(self.score_for_hw('homework3'), [1.0, 1.0]) self.assertEqual(self.score_for_hw('homework3'), [1.0, 1.0])
class ProblemWithUploadedFilesTest(TestSubmittingProblems):
"""Tests of problems with uploaded files."""
def setUp(self):
super(ProblemWithUploadedFilesTest, self).setUp()
self.section = self.add_graded_section_to_course('section')
def problem_setup(self, name, files):
"""
Create a CodeResponse problem with files to upload.
"""
xmldata = CodeResponseXMLFactory().build_xml(
allowed_files=files, required_files=files,
)
ItemFactory.create(
parent_location=self.section.location,
category='problem',
display_name=name,
data=xmldata
)
# re-fetch the course from the database so the object is up to date
self.refresh_course()
def test_three_files(self):
# Open the test files, and arrange to close them later.
filenames = "prog1.py prog2.py prog3.py"
fileobjs = [
open(os.path.join(settings.COMMON_TEST_DATA_ROOT, "capa", filename))
for filename in filenames.split()
]
for fileobj in fileobjs:
self.addCleanup(fileobj.close)
self.problem_setup("the_problem", filenames)
with patch('courseware.module_render.xqueue_interface.session') as mock_session:
resp = self.submit_question_answer("the_problem", {'2_1': fileobjs})
self.assertEqual(resp.status_code, 200)
json_resp = json.loads(resp.content)
self.assertEqual(json_resp['success'], "incorrect")
# See how post got called.
name, args, kwargs = mock_session.mock_calls[0]
self.assertEqual(name, "post")
self.assertEqual(len(args), 1)
self.assertTrue(args[0].endswith("/submit/"))
self.assertItemsEqual(kwargs.keys(), ["files", "data"])
self.assertItemsEqual(kwargs['files'].keys(), filenames.split())
class TestPythonGradedResponse(TestSubmittingProblems): class TestPythonGradedResponse(TestSubmittingProblems):
""" """
Check that we can submit a schematic and custom response, and it answers properly. Check that we can submit a schematic and custom response, and it answers properly.
......
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