示例#1
0
    def setUp(self):
        super(MultipleChoiceTagTests, self).setUp()

        self.base = '/' + COURSE_NAME
        self.app_context = actions.simple_add_course(COURSE_NAME, ADMIN_EMAIL,
                                                     'Assessment Tags')
        self.namespace = 'ns_%s' % COURSE_NAME

        with utils.Namespace(self.namespace):
            dto = models.QuestionDTO(None, transforms.loads(self.MC_1_JSON))
            self.mc_1_id = models.QuestionDAO.save(dto)
            dto = models.QuestionDTO(None, transforms.loads(self.MC_2_JSON))
            self.mc_2_id = models.QuestionDAO.save(dto)
            dto = models.QuestionGroupDTO(
                None,
                transforms.loads(self.QG_1_JSON_TEMPLATE %
                                 (self.mc_1_id, self.mc_2_id)))
            self.qg_1_id = models.QuestionGroupDAO.save(dto)

        self.course = courses.Course(None, self.app_context)
        self.assessment = self.course.add_assessment()
        self.assessment.availability = courses.AVAILABILITY_AVAILABLE
        self.assessment.html_content = (
            '<question quid="%s" weight="1" instanceid="q1"></question>'
            '<question-group qgid="%s" instanceid="qg1"></question-group' %
            (self.mc_1_id, self.qg_1_id))
        self.course.save()
示例#2
0
    def setUp(self):
        """Sets up datastore contents."""
        super(QuestionDAOTestCase, self).setUp()
        self.used_twice_question_id = 1
        self.used_twice_question_dto = models.QuestionDTO(
            self.used_twice_question_id, {})

        self.used_once_question_id = 2
        self.used_once_question_dto = models.QuestionDTO(
            self.used_once_question_id, {})

        self.unused_question_id = 3
        self.unused_question_dto = models.QuestionDTO(self.unused_question_id,
                                                      {})
        models.QuestionDAO.save_all([
            self.used_twice_question_dto, self.used_once_question_dto,
            self.unused_question_dto
        ])

        # Handcoding the dicts. This is dangerous because they're handcoded
        # elsewhere, the implementations could fall out of sync, and these tests
        # may then pass erroneously.
        self.first_question_group_description = 'first_question_group'
        self.first_question_group_id = 4
        self.first_question_group_dto = models.QuestionGroupDTO(
            self.first_question_group_id, {
                'description': self.first_question_group_description,
                'items': [{
                    'question': str(self.used_once_question_id)
                }]
            })

        self.second_question_group_description = 'second_question_group'
        self.second_question_group_id = 5
        self.second_question_group_dto = models.QuestionGroupDTO(
            self.second_question_group_id, {
                'description': self.second_question_group_description,
                'items': [{
                    'question': str(self.used_twice_question_id)
                }]
            })

        self.third_question_group_description = 'third_question_group'
        self.third_question_group_id = 6
        self.third_question_group_dto = models.QuestionGroupDTO(
            self.third_question_group_id, {
                'description': self.third_question_group_description,
                'items': [{
                    'question': str(self.used_twice_question_id)
                }]
            })

        models.QuestionGroupDAO.save_all([
            self.first_question_group_dto, self.second_question_group_dto,
            self.third_question_group_dto
        ])
示例#3
0
    def test_add_to_question_group(self):
        # Create a question
        question_description = 'Question'
        question_dto = models.QuestionDTO(None, {
            'description': question_description,
            'type': 0  # MC
        })
        question_id = models.QuestionDAO.save(question_dto)

        add_to_group_selector = '.add-question-to-group'

        # No groups are present so no add_to_group icon should be present
        self.assertEqual([], self._soup_table().select(add_to_group_selector))

        # Create a group
        qg_description = 'Question Group'
        qg_dto = models.QuestionGroupDTO(None, {
            'description': qg_description,
            'items': []
        })
        qg_id = models.QuestionGroupDAO.save(qg_dto)

        # Since we now have a group, the add_to_group icon should be visible
        self.assertIsNotNone(
            self._soup_table().select(add_to_group_selector))

        # Add Question to Question Group via post_add_to_question_group
        questions_table = self._soup_table()
        xsrf_token = questions_table.get('data-qg-xsrf-token', '')
        response = self._call_add_to_question_group(
            question_id, qg_id, 1, xsrf_token)

        # Check if operation was successful
        self.assertEquals(response.status_int, 200)
        questions_table = self._soup_table()
        self.assertEquals(
            questions_table.select('.groups-cell li')[0].text.strip(),
            qg_description
        )

        # Check a bunch of calls that should fail
        response = self._call_add_to_question_group(question_id, qg_id, 1, 'a')
        self.assertEquals(response.status_int, 403)

        response = transforms.loads(self._call_add_to_question_group(
            -1, qg_id, 1, xsrf_token).body)
        self.assertEquals(response['status'], 500)

        response = transforms.loads(self._call_add_to_question_group(
            question_id, -1, 1, xsrf_token).body)
        self.assertEquals(response['status'], 500)

        response = transforms.loads(self._call_add_to_question_group(
            'a', qg_id, 1, xsrf_token).body)
        self.assertEquals(response['status'], 500)

        response = transforms.loads(self._call_add_to_question_group(
            question_id, qg_id, 'a', xsrf_token).body)
        self.assertEquals(response['status'], 500)
    def test_no_question_groups(self):
        description = 'Question description'
        models.QuestionDAO.save(
            models.QuestionDTO(None, {'description': description}))

        table = self._soup_table()
        self.assertEquals(description,
                          table.select('.description-cell a')[0].text.strip())
示例#5
0
 def test_no_question_groups(self):
     description = 'Question description'
     models.QuestionDAO.save(
         models.QuestionDTO(None, {'description': description}))
     asset_tables = self._load_tables()
     self.assertEquals(asset_tables[0].findall('./tbody/tr/td/a')[1].tail,
                       description)
     self.assertEquals(asset_tables[1].find('./tfoot/tr/td').text,
                       'No question groups available')
    def test_last_modified_timestamp(self):
        begin_time = time.time()
        question_dto = models.QuestionDTO(None, {})
        models.QuestionDAO.save(question_dto)
        self.assertTrue((begin_time <= question_dto.last_modified)
                        and (question_dto.last_modified <= time.time()))

        questions_table = self._soup_table()
        self.assertEquals(
            questions_table.select('[data-timestamp]')[0].get(
                'data-timestamp', ''), str(question_dto.last_modified))
示例#7
0
 def convert_to_dtos(self, questions):
     dtos = []
     for question in questions:
         question['version'] = models.QuestionDAO.VERSION
         dto = models.QuestionDTO(None, question)
         if dto.type == 'multi_choice':
             dto.type = models.QuestionDTO.MULTIPLE_CHOICE
         else:
             dto.type = models.QuestionDTO.SHORT_ANSWER
         dtos.append(dto)
     return dtos
    def test_table_entries(self):
        # Create a question
        mc_question_description = 'Test MC Question'
        mc_question_dto = models.QuestionDTO(
            None,
            {
                'description': mc_question_description,
                'type': 0  # MC
            })
        mc_question_id = models.QuestionDAO.save(mc_question_dto)

        # Create a question group and add the question
        qg_description = 'Question Group'
        qg_dto = models.QuestionGroupDTO(
            None, {
                'description': qg_description,
                'items': [{
                    'question': str(mc_question_id)
                }]
            })
        qg_id = models.QuestionGroupDAO.save(qg_dto)

        # Create a second assessment and add the question group to the content
        assessment_two = self.course.add_assessment()
        assessment_two.title = 'Test Assessment'
        assessment_two.html_content = """
            <question-group qgid="%s" instanceid="QG"></question-group>
        """ % qg_id

        self.course.save()

        # Check Question Group table
        question_groups_table = self._soup_table()
        row = question_groups_table.select('tbody tr')[0]
        # Check edit link and description
        edit_link = row.select('.description-cell a')[0]
        self.assertEquals(edit_link.text.strip(), qg_description)
        self.assertEquals(
            edit_link.get('href'),
            'dashboard?action=edit_question_group&key={}'.format(qg_id))

        # The question that is part of this group, should be listed
        self.assertEquals(
            row.select('.questions-cell li')[0].text.strip(),
            mc_question_description)

        # Assessment where this Question Group is located, should be linked
        location_link = row.select('.locations-cell a')[0]
        self.assertEquals(location_link.get('href'),
                          'assessment?name={}'.format(assessment_two.unit_id))
        self.assertEquals(assessment_two.title, location_link.text.strip())
    def test_unused_question(self):
        # Create an unused question
        unused_question_dto = models.QuestionDTO(None, {
            'description': 'unused',
            'type': 0
        })
        unused_question_id = models.QuestionDAO.save(unused_question_dto)
        self.course.save()

        dom = self.parse_html_string(self.get(self.URL).body)
        question_row = dom.find(
            './/tr[@data-quid=\'{}\']'.format(unused_question_id))
        filter_data = json.loads(question_row.get('data-filter'))
        self.assertEqual(filter_data['unused'], 1)
    def test_question_clone(self):
        # Add a question by just nailing it in to the datastore.
        mc_question_description = 'Test MC Question'
        mc_question_dto = models.QuestionDTO(
            None,
            {
                'description': mc_question_description,
                'type': 0  # MC
            })
        models.QuestionDAO.save(mc_question_dto)

        # On the assets -> questions page, clone the question.
        response = self.get(self.URL)
        dom = self.parse_html_string(self.get(self.URL).body)
        clone_link = dom.find('.//a[@class="icon icon-clone"]')
        response = self.get(clone_link.get('href'), response).follow()
        self.assertIn(mc_question_description + ' (clone)', response.body)
示例#11
0
    def test_last_modified_timestamp(self):
        begin_time = time.time()
        question_dto = models.QuestionDTO(None, {})
        models.QuestionDAO.save(question_dto)
        self.assertTrue((begin_time <= question_dto.last_modified)
                        and (question_dto.last_modified <= time.time()))

        qg_dto = models.QuestionGroupDTO(None, {})
        models.QuestionGroupDAO.save(qg_dto)
        self.assertTrue((begin_time <= qg_dto.last_modified)
                        and (question_dto.last_modified <= time.time()))

        asset_tables = self._load_tables()
        self.assertEquals(
            asset_tables[0].find('./tbody/tr/td[@data-timestamp]').get(
                'data-timestamp', ''), str(question_dto.last_modified))
        self.assertEquals(
            asset_tables[1].find('./tbody/tr/td[@data-timestamp]').get(
                'data-timestamp', ''), str(qg_dto.last_modified))
    def test_question_clone(self):
        # Add a question by just nailing it in to the datastore.
        mc_question_description = 'Test MC Question'
        mc_question_dto = models.QuestionDTO(
            None,
            {
                'description': mc_question_description,
                'type': 0  # MC
            })
        models.QuestionDAO.save(mc_question_dto)

        # On the assets -> questions page, clone the question.
        response = self.get(self.URL)
        soup = self.parse_html_string_to_soup(self.get(self.URL).body)
        clone_link = soup.select('.clone-question')[0]
        question_key = clone_link.get('data-key')
        xsrf_token = soup.select('#question-table')[0].get(
            'data-clone-question-token')
        self.post('dashboard?action=clone_question', {
            'key': question_key,
            'xsrf_token': xsrf_token
        })
        response = self.get(self.URL)
        self.assertIn(mc_question_description + ' (clone)', response.body)
示例#13
0
    def test_question_clone(self):
        # Add a question by just nailing it in to the datastore.
        mc_question_description = 'Test MC Question'
        mc_question_dto = models.QuestionDTO(None, {
            'description': mc_question_description,
            'type': 0  # MC
        })
        models.QuestionDAO.save(mc_question_dto)

        # On the assets -> questions page, clone the question.
        response = self.get(self.URL)
        dom = self.parse_html_string(self.get(self.URL).body)
        clone_link = dom.find('.//a[@class="icon icon-clone"]')
        question_key = clone_link.get('data-key')
        xsrf_token = dom.find('.//table[@id="question-table"]'
                              ).get('data-clone-question-token')
        self.post(
            'dashboard?action=clone_question',
            {
                'key': question_key,
                'xsrf_token': xsrf_token
            })
        response = self.get(self.URL)
        self.assertIn(mc_question_description + ' (clone)', response.body)
示例#14
0
    def test_table_entries(self):
        # Create a question
        mc_question_description = 'Test MC Question'
        mc_question_dto = models.QuestionDTO(None, {
            'description': mc_question_description,
            'type': 0  # MC
        })
        mc_question_id = models.QuestionDAO.save(mc_question_dto)

        # Create an assessment and add the question to the content
        assessment_one = self.course.add_assessment()
        assessment_one.title = 'Test Assessment One'
        assessment_one.html_content = """
            <question quid="%s" weight="1" instanceid="1"></question>
        """ % mc_question_id

        # Create a second question
        sa_question_description = 'Test SA Question'
        sa_question_dto = models.QuestionDTO(None, {
            'description': sa_question_description,
            'type': 1  # SA
        })
        sa_question_id = models.QuestionDAO.save(sa_question_dto)

        # Create a question group and add the second question
        qg_description = 'Question Group'
        qg_dto = models.QuestionGroupDTO(None, {
              'description': qg_description,
             'items': [{'question': str(sa_question_id)}]
        })
        qg_id = models.QuestionGroupDAO.save(qg_dto)

        # Create a second assessment and add the question group to the content
        assessment_two = self.course.add_assessment()
        assessment_two.title = 'Test Assessment'
        assessment_two.html_content = """
            <question-group qgid="%s" instanceid="QG"></question-group>
        """ % qg_id

        self.course.save()

        # Get the Assets > Question tab
        dom = self.parse_html_string(self.get(self.URL).body)
        asset_tables = dom.findall('.//table[@class="assets-table"]')
        self.assertEquals(len(asset_tables), 2)

        # First check Question Bank table
        questions_table = asset_tables[0]
        question_rows = questions_table.findall('./tbody/tr[@data-filter]')
        self.assertEquals(len(question_rows), 2)

        # Check edit link and description of the first question
        first_row = list(question_rows[0])
        first_cell = first_row[0]
        self.assertEquals(first_cell.findall('a')[1].tail,
                          mc_question_description)
        self.assertEquals(first_cell.find('a').get('href'), (
            'dashboard?action=edit_question&key=%s' % mc_question_id))
        # Check if the assessment is listed
        location_link = first_row[2].find('ul/li/a')
        self.assertEquals(location_link.get('href'), (
            'assessment?name=%s' % assessment_one.unit_id))
        self.assertEquals(location_link.text, assessment_one.title)

        # Check second question (=row)
        second_row = list(question_rows[1])
        self.assertEquals(
            second_row[0].findall('a')[1].tail, sa_question_description)
        # Check whether the containing Question Group is listed
        self.assertEquals(second_row[1].find('ul/li').text, qg_description)

        # Now check Question Group table
        question_groups_table = asset_tables[1]
        row = question_groups_table.find('./tbody/tr')
        # Check edit link and description
        edit_link = row[0].find('a')
        self.assertEquals(edit_link.tail, qg_description)
        self.assertEquals(edit_link.get('href'), (
            'dashboard?action=edit_question_group&key=%s' % qg_id))

        # The question that is part of this group, should be listed
        self.assertEquals(row[1].find('ul/li').text, sa_question_description)

        # Assessment where this Question Group is located, should be linked
        location_link = row[2].find('ul/li/a')
        self.assertEquals(location_link.get('href'), (
            'assessment?name=%s' % assessment_two.unit_id))
        self.assertEquals(location_link.text, assessment_two.title)
    def test_table_entries(self):
        # Create a question
        mc_question_description = 'Test MC Question'
        mc_question_dto = models.QuestionDTO(
            None,
            {
                'description': mc_question_description,
                'type': 0  # MC
            })
        mc_question_id = models.QuestionDAO.save(mc_question_dto)

        # Create an assessment and add the question to the content.
        # Also include a broken question ref to the assessment (and expect this
        # doesn't break anything).
        assessment_one = self.course.add_assessment()
        assessment_one.title = 'Test Assessment One'
        assessment_one.html_content = """
            <question quid="%s" weight="1" instanceid="1"></question>
            <question quid="broken" weight="1" instanceid="broken"></question>
        """ % mc_question_id

        # Create a second question
        sa_question_description = 'Test SA Question'
        sa_question_dto = models.QuestionDTO(
            None,
            {
                'description': sa_question_description,
                'type': 1  # SA
            })
        sa_question_id = models.QuestionDAO.save(sa_question_dto)

        # Create a question group and add the second question
        qg_description = 'Question Group'
        qg_dto = models.QuestionGroupDTO(
            None, {
                'description': qg_description,
                'items': [{
                    'question': str(sa_question_id)
                }]
            })
        qg_id = models.QuestionGroupDAO.save(qg_dto)

        # Create a second assessment and add the question group to the content
        assessment_two = self.course.add_assessment()
        assessment_two.title = 'Test Assessment'
        assessment_two.html_content = """
            <question-group qgid="%s" instanceid="QG"></question-group>
        """ % qg_id

        self.course.save()

        # First check Question Bank table
        questions_table = self._soup_table()
        question_rows = questions_table.select('tr[data-filter]')
        self.assertEquals(len(question_rows), 2)

        # Check edit link and description of the first question
        first_row = question_rows[0]
        description_link = first_row.select('.description-cell a')[0]
        self.assertEquals(description_link.text.strip(),
                          mc_question_description)
        self.assertEquals(
            description_link.get('href'),
            ('dashboard?action=edit_question&key={}'.format(mc_question_id)))

        # Check if the assessment is listed
        location_link = first_row.select('.locations-cell a')[0]
        self.assertEquals(location_link.get('href'),
                          'assessment?name={}'.format(assessment_one.unit_id))
        self.assertEquals(assessment_one.title, location_link.text.strip())

        # Check second question (=row)
        second_row = question_rows[1]
        self.assertEquals(
            second_row.select('.description-cell a')[0].text.strip(),
            sa_question_description)
        # Check whether the containing Question Group is listed
        self.assertEquals(
            second_row.select('.groups-cell li')[0].text.strip(),
            qg_description)
示例#16
0
    def _get_sample_v15_course(self):
        """Creates a course with different types of questions and returns it."""
        sites.setup_courses('course:/test::ns_test, course:/:/')
        course = courses.Course(None, app_context=sites.get_all_courses()[0])
        unit1 = course.add_unit()
        lesson1 = course.add_lesson(unit1)
        assessment_old = course.add_assessment()
        assessment_old.title = 'Old assessment'
        assessment_new = course.add_assessment()
        assessment_new.title = 'New assessment'
        assessment_peer = course.add_assessment()
        assessment_peer.title = 'Peer review assessment'

        # Create a multiple choice question.
        mcq_new_id = 1
        mcq_new_dict = {
            'description': 'mcq_new',
            'type': 0,  # Multiple choice question.
            'choices': [{
                'text': 'answer',
                'score': 1.0
            }],
            'version': '1.5'
        }
        mcq_new_dto = models.QuestionDTO(mcq_new_id, mcq_new_dict)

        # Create a short answer question.
        frq_new_id = 2
        frq_new_dict = {
            'defaultFeedback': '',
            'rows': 1,
            'description': 'short answer',
            'hint': '',
            'graders': [{
                'matcher': 'case_insensitive',
                'score': '1.0',
                'response': 'hi',
                'feedback': ''
            }],
            'question': 'short answer question',
            'version': '1.5',
            'type': 1,  # Short answer question.
            'columns': 100
        }
        frq_new_dto = models.QuestionDTO(frq_new_id, frq_new_dict)

        # Save these questions to datastore.
        models.QuestionDAO.save_all([mcq_new_dto, frq_new_dto])

        # Create a question group.
        question_group_id = 3
        question_group_dict = {
            'description': 'question_group',
            'items': [
                {'question': str(mcq_new_id)},
                {'question': str(frq_new_id)},
                {'question': str(mcq_new_id)}
            ],
            'version': '1.5',
            'introduction': ''
        }
        question_group_dto = models.QuestionGroupDTO(
            question_group_id, question_group_dict)

        # Save the question group to datastore.
        models.QuestionGroupDAO.save_all([question_group_dto])

        # Add a MC question and a question group to leesson1.
        lesson1.objectives = """
            <question quid="1" weight="1" instanceid="QN"></question>
            random_text
            <gcb-youtube videoid="Kdg2drcUjYI" instanceid="VD"></gcb-youtube>
            more_random_text
            <question-group qgid="3" instanceid="QG"></question-group>
        """

        # Add a MC question, a short answer question, and a question group to
        # new style assessment.
        assessment_new.html_content = """
            <question quid="1" weight="1" instanceid="QN2"></question>
            <question quid="2" weight="1" instanceid="FRQ2"></question>
            random_text
            <gcb-youtube videoid="Kdg2drcUjYI" instanceid="VD"></gcb-youtube>
            more_random_text
            <question-group qgid="3" instanceid="QG2"></question-group>
        """

        return course
示例#17
0
    def test_add_to_question_group(self):
        # Create a question
        question_description = 'Question'
        question_dto = models.QuestionDTO(None, {
            'description': question_description,
            'type': 0  # MC
        })
        question_id = models.QuestionDAO.save(question_dto)

        # No groups are present so no add_to_group icon should be present
        self.assertIsNone(self._load_tables()[0].find('./tbody/tr/td[ul]div'))

        # Create a group
        qg_description = 'Question Group'
        qg_dto = models.QuestionGroupDTO(None, {
            'description': qg_description,
            'items': []
        })
        qg_id = models.QuestionGroupDAO.save(qg_dto)

        # Since we now have a group, the add_to_group icon should be visible
        self.assertIsNotNone(
            self._load_tables()[0].find('./tbody/tr/td[ul]/div'))

        # Add Question to Question Group via post_add_to_question_group
        asset_tables = self._load_tables()
        xsrf_token = asset_tables[0].get('data-qg-xsrf-token', '')
        response = self._call_add_to_question_group(
            question_id, qg_id, 1, xsrf_token)

        # Check if operation was successful
        self.assertEquals(response.status_int, 200)
        asset_tables = self._load_tables()
        self.assertEquals(
            asset_tables[0].find('./tbody/tr/td/ul/li').text,
            qg_description
        )
        self.assertEquals(
            asset_tables[1].find('./tbody/tr/td/ul/li').text,
            question_description
        )

        # Check a bunch of calls that should fail
        response = self._call_add_to_question_group(question_id, qg_id, 1, 'a')
        self.assertEquals(response.status_int, 403)

        response = transforms.loads(self._call_add_to_question_group(
            -1, qg_id, 1, xsrf_token).body)
        self.assertEquals(response['status'], 500)

        response = transforms.loads(self._call_add_to_question_group(
            question_id, -1, 1, xsrf_token).body)
        self.assertEquals(response['status'], 500)

        response = transforms.loads(self._call_add_to_question_group(
            'a', qg_id, 1, xsrf_token).body)
        self.assertEquals(response['status'], 500)

        response = transforms.loads(self._call_add_to_question_group(
            question_id, qg_id, 'a', xsrf_token).body)
        self.assertEquals(response['status'], 500)