def define_randomized_custom_response_problem(self, problem_url_name, redefine=False):
        """
        Defines a custom response problem that uses a random value to determine correctness.

        Generated answer is also returned as the `msg`, so that the value can be used as a
        correct answer by a test.

        If the `redefine` flag is set, then change the definition of correctness (from equals
        to not-equals).
        """
        factory = CustomResponseXMLFactory()
        script = textwrap.dedent(
            """
                def check_func(expect, answer_given):
                    expected = str(random.randint(0, 100))
                    return {'ok': answer_given %s expected, 'msg': expected}
            """
            % ("!=" if redefine else "==")
        )
        problem_xml = factory.build_xml(script=script, cfn="check_func", expect="42", num_responses=1)
        if redefine:
            self.module_store.update_item(InstructorTaskModuleTestCase.problem_location(problem_url_name), problem_xml)
        else:
            # Use "per-student" rerandomization so that check-problem can be called more than once.
            # Using "always" means we cannot check a problem twice, but we want to call once to get the
            # correct answer, and call a second time with that answer to confirm it's graded as correct.
            # Per-student rerandomization will at least generate different seeds for different users, so
            # we get a little more test coverage.
            ItemFactory.create(
                parent_location=self.problem_section.location,
                category="problem",
                display_name=str(problem_url_name),
                data=problem_xml,
                metadata={"rerandomize": "per_student"},
            )
Example #2
0
    def singleton(cls):
        """ Return the singleton, creating one if it does not already exist."""

        # If we haven't created the singleton yet, create it now
        if cls.SINGLETON is None:

            # Create a mock ModuleSystem, installing our cache
            system = mock.MagicMock(ModuleSystem)
            system.render_template = lambda template, context: "<div>%s</div>" % template
            system.cache = cache
            system.filestore = mock.MagicMock(fs.osfs.OSFS)
            system.filestore.root_path = ""
            system.DEBUG = True

            # Create a custom response problem
            xml_factory = CustomResponseXMLFactory()
            xml = xml_factory.build_xml(script=TEST_SCRIPT, cfn="check_func", expect="42")

            # Create and store the context
            cls.SINGLETON = cls(system, xml)

        else:
            pass

        # Return the singleton
        return cls.SINGLETON
Example #3
0
    def singleton(cls):
        """ Return the singleton, creating one if it does not already exist."""

        # If we haven't created the singleton yet, create it now
        if cls.SINGLETON is None:

            # Create a mock ModuleSystem, installing our cache
            system = mock.MagicMock(ModuleSystem)
            system.STATIC_URL = '/dummy-static/'
            system.render_template = lambda template, context: "<div>%s</div>" % template
            system.cache = cache
            system.filestore = mock.MagicMock(fs.osfs.OSFS)
            system.filestore.root_path = ""
            system.DEBUG = True

            # Create a custom response problem
            xml_factory = CustomResponseXMLFactory()
            xml = xml_factory.build_xml(script=TEST_SCRIPT,
                                        cfn="check_func",
                                        expect="42")

            # Create and store the context
            cls.SINGLETON = cls(system, xml)

        else:
            pass

        # Return the singleton
        return cls.SINGLETON
Example #4
0
    def define_randomized_custom_response_problem(self, problem_url_name, redefine=False):
        """
        Defines a custom response problem that uses a random value to determine correctness.

        Generated answer is also returned as the `msg`, so that the value can be used as a
        correct answer by a test.

        If the `redefine` flag is set, then change the definition of correctness (from equals
        to not-equals).
        """
        factory = CustomResponseXMLFactory()
        script = textwrap.dedent("""
                def check_func(expect, answer_given):
                    expected = str(random.randint(0, 100))
                    return {'ok': answer_given %s expected, 'msg': expected}
            """ % ('!=' if redefine else '=='))
        problem_xml = factory.build_xml(script=script, cfn="check_func", expect="42", num_responses=1)
        if redefine:
            self.module_store.update_item(InstructorTaskModuleTestCase.problem_location(problem_url_name), problem_xml)
        else:
            # Use "per-student" rerandomization so that check-problem can be called more than once.
            # Using "always" means we cannot check a problem twice, but we want to call once to get the
            # correct answer, and call a second time with that answer to confirm it's graded as correct.
            # Per-student rerandomization will at least generate different seeds for different users, so
            # we get a little more test coverage.
            ItemFactory.create(parent_location=self.problem_section.location,
                               template="i4x://edx/templates/problem/Blank_Common_Problem",
                               display_name=str(problem_url_name),
                               data=problem_xml,
                               metadata={"rerandomize": "per_student"})
class ScriptProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin):
    """
    TestCase Class for Script Problem Type
    """
    problem_name = 'SCRIPT TEST PROBLEM'
    problem_type = 'script'
    partially_correct = False

    factory = CustomResponseXMLFactory()

    factory_kwargs = {
        'cfn':
        'test_add_to_ten',
        'expect':
        '10',
        'num_inputs':
        2,
        'question_text':
        'Enter two integers that sum to 10.',
        'input_element_label':
        'Enter an integer',
        'script':
        textwrap.dedent("""
            def test_add_to_ten(expect,ans):
                try:
                    a1=int(ans[0])
                    a2=int(ans[1])
                except ValueError:
                    a1=0
                    a2=0
                return (a1+a2)==int(expect)
        """),
    }
    status_indicators = {
        'correct': ['div.correct'],
        'incorrect': ['div.incorrect'],
        'unanswered': ['div.unanswered', 'div.unsubmitted'],
    }

    def setUp(self, *args, **kwargs):
        """
        Additional setup for ScriptProblemTypeTest
        """
        super(ScriptProblemTypeTest, self).setUp(*args, **kwargs)

    def answer_problem(self, correctness):
        """
        Answer script problem.
        """
        # Correct answer is any two integers that sum to 10
        first_addend = random.randint(-100, 100)
        second_addend = 10 - first_addend

        # If we want an incorrect answer, then change
        # the second addend so they no longer sum to 10
        if not correctness == 'correct':
            second_addend += random.randint(1, 10)

        self.problem_page.fill_answer(first_addend, input_num=0)
        self.problem_page.fill_answer(second_addend, input_num=1)
    def computed_answer_setup(self, name):
        """
        set up an example problem using an answer script'''
        """

        script = self.COMPUTED_ANSWER_SCRIPT

        computed_xml = CustomResponseXMLFactory().build_xml(answer=script)

        ItemFactory.create(parent_location=self.section.location,
                           category='problem',
                           boilerplate='customgrader.yaml',
                           data=computed_xml,
                           display_name=name)

        # define the correct and incorrect responses to this problem
        self.correct_responses[name] = self.COMPUTED_ANSWER_CORRECT
        self.incorrect_responses[name] = self.COMPUTED_ANSWER_INCORRECT

        # re-fetch the course from the database so the object is up to date
        self.refresh_course()
    def computed_answer_setup(self, name):
        """
        set up an example problem using an answer script'''
        """

        script = self.COMPUTED_ANSWER_SCRIPT

        custom_template = "i4x://edx/templates/problem/Custom_Python-Evaluated_Input"

        computed_xml = CustomResponseXMLFactory().build_xml(answer=script)

        ItemFactory.create(parent_location=self.section.location,
                           template=custom_template,
                           data=computed_xml,
                           display_name=name)

        # define the correct and incorrect responses to this problem
        self.correct_responses[name] = self.COMPUTED_ANSWER_CORRECT
        self.incorrect_responses[name] = self.COMPUTED_ANSWER_INCORRECT

        # re-fetch the course from the database so the object is up to date
        self.refresh_course()
Example #8
0
    def custom_response_setup(self, name):
        """
        set up an example custom response problem using a check function
        """

        test_csv = self.CUSTOM_RESPONSE_SCRIPT
        expect = self.CUSTOM_RESPONSE_CORRECT
        cfn_problem_xml = CustomResponseXMLFactory().build_xml(script=test_csv, cfn='test_csv', expect=expect)

        ItemFactory.create(
            parent_location=self.section.location,
            category='problem',
            boilerplate='customgrader.yaml',
            data=cfn_problem_xml,
            display_name=name
        )

        # define the correct and incorrect responses to this problem
        self.correct_responses[name] = expect
        self.incorrect_responses[name] = self.CUSTOM_RESPONSE_INCORRECT

        # re-fetch the course from the database so the object is up to date
        self.refresh_course()
    def custom_response_setup(self, name):
        """
        set up an example custom response problem using a check function
        """

        custom_template = "i4x://edx/templates/problem/Custom_Python-Evaluated_Input"
        test_csv = self.CUSTOM_RESPONSE_SCRIPT
        expect = self.CUSTOM_RESPONSE_CORRECT
        cfn_problem_xml = CustomResponseXMLFactory().build_xml(script=test_csv,
                                                               cfn='test_csv',
                                                               expect=expect)

        ItemFactory.create(parent_location=self.section.location,
                           template=custom_template,
                           data=cfn_problem_xml,
                           display_name=name)

        # define the correct and incorrect responses to this problem
        self.correct_responses[name] = expect
        self.incorrect_responses[name] = self.CUSTOM_RESPONSE_INCORRECT

        # re-fetch the course from the database so the object is up to date
        self.refresh_course()
         'question_text': 'The solution is [mathjax]x^2+2x+y[/mathjax]',
         'sample_dict': {
             'x': (-100, 100),
             'y': (-100, 100)
         },
         'num_samples': 10,
         'tolerance': 0.00001,
         'math_display': True,
         'answer': 'x^2+2*x+y'
     },
     'correct': ['div.correct'],
     'incorrect': ['div.incorrect'],
     'unanswered': ['div.unanswered']
 },
 'script': {
     'factory': CustomResponseXMLFactory(),
     'kwargs': {
         'question_text':
         'Enter two integers that sum to 10.',
         'cfn':
         'test_add_to_ten',
         'expect':
         '10',
         'num_inputs':
         2,
         'script':
         textwrap.dedent("""
             def test_add_to_ten(expect,ans):
                 try:
                     a1=int(ans[0])
                     a2=int(ans[1])
class ScriptProblemTypeBase(ProblemTypeTestBase):
    """
    ProblemTypeTestBase specialization for Script Problem Type
    """
    problem_name = 'SCRIPT TEST PROBLEM'
    problem_type = 'script'
    problem_points = 2
    partially_correct = False

    factory = CustomResponseXMLFactory()

    factory_kwargs = {
        'cfn':
        'test_add_to_ten',
        'expect':
        '10',
        'num_inputs':
        2,
        'question_text':
        'Enter two integers that sum to 10.',
        'input_element_label':
        'Enter an integer',
        'script':
        textwrap.dedent("""
            def test_add_to_ten(expect,ans):
                try:
                    a1=int(ans[0])
                    a2=int(ans[1])
                except ValueError:
                    a1=0
                    a2=0
                return (a1+a2)==int(expect)
        """),
    }
    status_indicators = {
        'correct': ['div.correct'],
        'incorrect': ['div.incorrect'],
        'unanswered': ['div.unanswered', 'div.unsubmitted'],
        'submitted': ['div.submitted'],
    }

    def problem_status(self, status):
        """
        Returns the status of problem
        Args:
            status(string): status of the problem which is to be checked

        Returns:
            True: If provided status is present on the page
        """
        selector = ', '.join(self.status_indicators[status])
        try:
            self.problem_page.wait_for_element_visibility(selector,
                                                          'Status is present',
                                                          timeout=10)
            return True
        except BrokenPromise:
            return False

    def answer_problem(self, correctness):
        """
        Answer script problem.
        """
        # Correct answer is any two integers that sum to 10
        first_addend = random.randint(-100, 100)
        second_addend = 10 - first_addend

        # If we want an incorrect answer, then change
        # the second addend so they no longer sum to 10
        if not correctness == 'correct':
            second_addend += random.randint(1, 10)

        self.problem_page.fill_answer(first_addend, input_num=0)  # lint-amnesty, pylint: disable=no-member
        self.problem_page.fill_answer(second_addend, input_num=1)  # lint-amnesty, pylint: disable=no-member