예제 #1
0
    def init_from_model(self, student, model, course_structure,
                        submissions_scores, csm_scores):
        """
        Load the subsection grade from the persisted model.
        """
        for block in model.visible_blocks.blocks:
            self._compute_block_score(block.locator, course_structure,
                                      submissions_scores, csm_scores, block)

        self.graded_total = AggregatedScore(
            tw_earned=model.earned_graded,
            tw_possible=model.possible_graded,
            graded=True,
            display_name=self.display_name,
            module_id=self.location,
        )
        self.all_total = AggregatedScore(
            tw_earned=model.earned_all,
            tw_possible=model.possible_all,
            graded=False,
            display_name=self.display_name,
            module_id=self.location,
        )
        self._log_event(log.debug, u"init_from_model", student)
        return self
예제 #2
0
 def __init__(self, subsection, course_data):
     super(ZeroSubsectionGrade, self).__init__(subsection)
     self.graded_total = AggregatedScore(tw_earned=0,
                                         tw_possible=None,
                                         graded=False,
                                         first_attempted=None)
     self.all_total = AggregatedScore(tw_earned=0,
                                      tw_possible=None,
                                      graded=self.graded,
                                      first_attempted=None)
     self.course_data = course_data
예제 #3
0
    def _aggregated_score_from_model(grade_model, is_graded):
        """
        Helper method that returns `AggregatedScore` objects based on
        the values in the given `grade_model`.  If the given model
        has an associated override, the values from the override are
        used instead.
        """
        score_type = 'graded' if is_graded else 'all'
        earned_value = getattr(grade_model, 'earned_{}'.format(score_type))
        possible_value = getattr(grade_model, 'possible_{}'.format(score_type))
        if hasattr(grade_model, 'override'):
            score_type = 'graded_override' if is_graded else 'all_override'

            earned_override = getattr(grade_model.override,
                                      'earned_{}'.format(score_type))
            if earned_override is not None:
                earned_value = earned_override

            possible_override = getattr(grade_model.override,
                                        'possible_{}'.format(score_type))
            if possible_override is not None:
                possible_value = possible_override

        return AggregatedScore(
            tw_earned=earned_value,
            tw_possible=possible_value,
            graded=is_graded,
            first_attempted=grade_model.first_attempted,
        )
예제 #4
0
    def test_weighted_grading(self):
        scores = []
        agg_fields = dict(first_attempted=None)
        prob_fields = dict(raw_earned=0, raw_possible=0, weight=0, first_attempted=None)

        # No scores
        all_total, graded_total = aggregate_scores(scores)
        self.assertEqual(
            all_total,
            AggregatedScore(tw_earned=0, tw_possible=0, graded=False, **agg_fields),
        )
        self.assertEqual(
            graded_total,
            AggregatedScore(tw_earned=0, tw_possible=0, graded=True, **agg_fields),
        )

        # (0/5 non-graded)
        scores.append(ProblemScore(weighted_earned=0, weighted_possible=5, graded=False, **prob_fields))
        all_total, graded_total = aggregate_scores(scores)
        self.assertEqual(
            all_total,
            AggregatedScore(tw_earned=0, tw_possible=5, graded=False, **agg_fields),
        )
        self.assertEqual(
            graded_total,
            AggregatedScore(tw_earned=0, tw_possible=0, graded=True, **agg_fields),
        )

        # (0/5 non-graded) + (3/5 graded) = 3/10 total, 3/5 graded
        now = datetime.now()
        prob_fields['first_attempted'] = now
        agg_fields['first_attempted'] = now
        scores.append(ProblemScore(weighted_earned=3, weighted_possible=5, graded=True, **prob_fields))
        all_total, graded_total = aggregate_scores(scores)
        self.assertAlmostEqual(
            all_total,
            AggregatedScore(tw_earned=3, tw_possible=10, graded=False, **agg_fields),
        )
        self.assertAlmostEqual(
            graded_total,
            AggregatedScore(tw_earned=3, tw_possible=5, graded=True, **agg_fields),
        )

        # (0/5 non-graded) + (3/5 graded) + (2/5 graded) = 5/15 total, 5/10 graded
        scores.append(ProblemScore(weighted_earned=2, weighted_possible=5, graded=True, **prob_fields))
        all_total, graded_total = aggregate_scores(scores)
        self.assertAlmostEqual(
            all_total,
            AggregatedScore(tw_earned=5, tw_possible=15, graded=False, **agg_fields),
        )
        self.assertAlmostEqual(
            graded_total,
            AggregatedScore(tw_earned=5, tw_possible=10, graded=True, **agg_fields),
        )
예제 #5
0
    def __init__(self, subsection, model, factory):
        all_total = AggregatedScore(
            tw_earned=model.earned_all,
            tw_possible=model.possible_all,
            graded=False,
            first_attempted=model.first_attempted,
        )
        graded_total = AggregatedScore(
            tw_earned=model.earned_graded,
            tw_possible=model.possible_graded,
            graded=True,
            first_attempted=model.first_attempted,
        )
        override = model.override if hasattr(model, 'override') else None

        # save these for later since we compute problem_scores lazily
        self.model = model
        self.factory = factory

        super(ReadSubsectionGrade, self).__init__(subsection, all_total,
                                                  graded_total, override)
예제 #6
0
    def init_from_model(self, student, model, course_structure,
                        submissions_scores, csm_scores):
        """
        Load the subsection grade from the persisted model.
        """
        for block in model.visible_blocks.blocks:
            self._compute_block_score(block.locator, course_structure,
                                      submissions_scores, csm_scores, block)

        self.graded_total = AggregatedScore(
            tw_earned=model.earned_graded,
            tw_possible=model.possible_graded,
            graded=True,
            first_attempted=model.first_attempted,
        )
        self.all_total = AggregatedScore(
            tw_earned=model.earned_all,
            tw_possible=model.possible_all,
            graded=False,
            first_attempted=model.first_attempted,
        )
        self.override = model.override if hasattr(model, 'override') else None
        self._log_event(log.debug, u"init_from_model", student)
        return self
예제 #7
0
class GraderTest(unittest.TestCase):
    """
    Tests grader implementations
    """
    shard = 1

    empty_gradesheet = {}

    incomplete_gradesheet = {
        'Homework': {},
        'Lab': {},
        'Midterm': {},
    }

    class MockGrade(object):
        """
        Mock class for SubsectionGrade object.
        """
        def __init__(self, graded_total, display_name):
            self.graded_total = graded_total
            self.display_name = display_name

        @property
        def percent_graded(self):
            return compute_percent(self.graded_total.earned,
                                   self.graded_total.possible)

    common_fields = dict(graded=True, first_attempted=datetime.now())
    test_gradesheet = {
        'Homework': {
            'hw1':
            MockGrade(AggregatedScore(tw_earned=2,
                                      tw_possible=20.0,
                                      **common_fields),
                      display_name='hw1'),
            'hw2':
            MockGrade(AggregatedScore(tw_earned=16,
                                      tw_possible=16.0,
                                      **common_fields),
                      display_name='hw2'),
        },

        # The dropped scores should be from the assignments that don't exist yet
        'Lab': {
            # Dropped
            'lab1':
            MockGrade(AggregatedScore(tw_earned=1,
                                      tw_possible=2.0,
                                      **common_fields),
                      display_name='lab1'),
            'lab2':
            MockGrade(AggregatedScore(tw_earned=1,
                                      tw_possible=1.0,
                                      **common_fields),
                      display_name='lab2'),
            'lab3':
            MockGrade(AggregatedScore(tw_earned=1,
                                      tw_possible=1.0,
                                      **common_fields),
                      display_name='lab3'),
            # Dropped
            'lab4':
            MockGrade(AggregatedScore(tw_earned=5,
                                      tw_possible=25.0,
                                      **common_fields),
                      display_name='lab4'),
            # Dropped
            'lab5':
            MockGrade(AggregatedScore(tw_earned=3,
                                      tw_possible=4.0,
                                      **common_fields),
                      display_name='lab5'),
            'lab6':
            MockGrade(AggregatedScore(tw_earned=6,
                                      tw_possible=7.0,
                                      **common_fields),
                      display_name='lab6'),
            'lab7':
            MockGrade(AggregatedScore(tw_earned=5,
                                      tw_possible=6.0,
                                      **common_fields),
                      display_name='lab7'),
        },
        'Midterm': {
            'midterm':
            MockGrade(
                AggregatedScore(tw_earned=50.5,
                                tw_possible=100,
                                **common_fields),
                display_name="Midterm Exam",
            ),
        },
    }

    def test_assignment_format_grader(self):
        homework_grader = graders.AssignmentFormatGrader("Homework", 12, 2)
        no_drop_grader = graders.AssignmentFormatGrader("Homework", 12, 0)
        # Even though the minimum number is 3, this should grade correctly when 7 assignments are found
        overflow_grader = graders.AssignmentFormatGrader("Lab", 3, 2)
        lab_grader = graders.AssignmentFormatGrader("Lab", 7, 3)

        # Test the grading of an empty gradesheet
        for graded in [
                homework_grader.grade(self.empty_gradesheet),
                no_drop_grader.grade(self.empty_gradesheet),
                homework_grader.grade(self.incomplete_gradesheet),
                no_drop_grader.grade(self.incomplete_gradesheet),
        ]:
            self.assertAlmostEqual(graded['percent'], 0.0)
            # Make sure the breakdown includes 12 sections, plus one summary
            self.assertEqual(len(graded['section_breakdown']), 12 + 1)

        graded = homework_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'],
                               0.11)  # 100% + 10% / 10 assignments
        self.assertEqual(len(graded['section_breakdown']), 12 + 1)

        graded = no_drop_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(
            graded['percent'],
            0.0916666666666666)  # 100% + 10% / 12 assignments
        self.assertEqual(len(graded['section_breakdown']), 12 + 1)

        graded = overflow_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(
            graded['percent'],
            0.8879999999999999)  # 100% + 10% / 5 assignments
        self.assertEqual(len(graded['section_breakdown']), 7 + 1)

        graded = lab_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.92249999999999999)
        self.assertEqual(len(graded['section_breakdown']), 7 + 1)

    def test_assignment_format_grader_on_single_section_entry(self):
        midterm_grader = graders.AssignmentFormatGrader("Midterm", 1, 0)
        # Test the grading on a section with one item:
        for graded in [
                midterm_grader.grade(self.empty_gradesheet),
                midterm_grader.grade(self.incomplete_gradesheet),
        ]:
            self.assertAlmostEqual(graded['percent'], 0.0)
            # Make sure the breakdown includes just the one summary
            self.assertEqual(len(graded['section_breakdown']), 0 + 1)
            self.assertEqual(graded['section_breakdown'][0]['label'],
                             'Midterm')

        graded = midterm_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.50)
        self.assertEqual(len(graded['section_breakdown']), 0 + 1)

    def test_weighted_subsections_grader(self):
        # First, a few sub graders
        homework_grader = graders.AssignmentFormatGrader("Homework", 12, 2)
        lab_grader = graders.AssignmentFormatGrader("Lab", 7, 3)
        midterm_grader = graders.AssignmentFormatGrader("Midterm", 1, 0)

        weighted_grader = graders.WeightedSubsectionsGrader([
            (homework_grader, homework_grader.category, 0.25),
            (lab_grader, lab_grader.category, 0.25),
            (midterm_grader, midterm_grader.category, 0.5),
        ])

        over_one_weights_grader = graders.WeightedSubsectionsGrader([
            (homework_grader, homework_grader.category, 0.5),
            (lab_grader, lab_grader.category, 0.5),
            (midterm_grader, midterm_grader.category, 0.5),
        ])

        # The midterm should have all weight on this one
        zero_weights_grader = graders.WeightedSubsectionsGrader([
            (homework_grader, homework_grader.category, 0.0),
            (lab_grader, lab_grader.category, 0.0),
            (midterm_grader, midterm_grader.category, 0.5),
        ])

        # This should always have a final percent of zero
        all_zero_weights_grader = graders.WeightedSubsectionsGrader([
            (homework_grader, homework_grader.category, 0.0),
            (lab_grader, lab_grader.category, 0.0),
            (midterm_grader, midterm_grader.category, 0.0),
        ])

        empty_grader = graders.WeightedSubsectionsGrader([])

        graded = weighted_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.50812499999999994)
        self.assertEqual(len(graded['section_breakdown']),
                         (12 + 1) + (7 + 1) + 1)
        self.assertEqual(len(graded['grade_breakdown']), 3)

        graded = over_one_weights_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.76624999999999999)
        self.assertEqual(len(graded['section_breakdown']),
                         (12 + 1) + (7 + 1) + 1)
        self.assertEqual(len(graded['grade_breakdown']), 3)

        graded = zero_weights_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.25)
        self.assertEqual(len(graded['section_breakdown']),
                         (12 + 1) + (7 + 1) + 1)
        self.assertEqual(len(graded['grade_breakdown']), 3)

        graded = all_zero_weights_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.0)
        self.assertEqual(len(graded['section_breakdown']),
                         (12 + 1) + (7 + 1) + 1)
        self.assertEqual(len(graded['grade_breakdown']), 3)

        for graded in [
                weighted_grader.grade(self.empty_gradesheet),
                weighted_grader.grade(self.incomplete_gradesheet),
                zero_weights_grader.grade(self.empty_gradesheet),
                all_zero_weights_grader.grade(self.empty_gradesheet),
        ]:
            self.assertAlmostEqual(graded['percent'], 0.0)
            self.assertEqual(len(graded['section_breakdown']),
                             (12 + 1) + (7 + 1) + 1)
            self.assertEqual(len(graded['grade_breakdown']), 3)

        graded = empty_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.0)
        self.assertEqual(len(graded['section_breakdown']), 0)
        self.assertEqual(len(graded['grade_breakdown']), 0)

    def test_grader_from_conf(self):

        # Confs always produce a graders.WeightedSubsectionsGrader, so we test this by repeating the test
        # in test_graders.WeightedSubsectionsGrader, but generate the graders with confs.

        weighted_grader = graders.grader_from_conf([
            {
                'type': "Homework",
                'min_count': 12,
                'drop_count': 2,
                'short_label': "HW",
                'weight': 0.25,
            },
            {
                'type': "Lab",
                'min_count': 7,
                'drop_count': 3,
                'category': "Labs",
                'weight': 0.25
            },
            {
                'type': "Midterm",
                'min_count': 0,
                'drop_count': 0,
                'name': "Midterm Exam",
                'short_label': "Midterm",
                'weight': 0.5,
            },
        ])

        empty_grader = graders.grader_from_conf([])

        graded = weighted_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.50812499999999994)
        self.assertEqual(len(graded['section_breakdown']),
                         (12 + 1) + (7 + 1) + 1)
        self.assertEqual(len(graded['grade_breakdown']), 3)

        graded = empty_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.0)
        self.assertEqual(len(graded['section_breakdown']), 0)
        self.assertEqual(len(graded['grade_breakdown']), 0)

        # Test that graders can also be used instead of lists of dictionaries
        homework_grader = graders.AssignmentFormatGrader("Homework", 12, 2)
        homework_grader2 = graders.grader_from_conf(homework_grader)

        graded = homework_grader2.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.11)
        self.assertEqual(len(graded['section_breakdown']), 12 + 1)

    @ddt.data(
        (
            # empty
            {},
            u"Configuration has no appropriate grader class."),
        (
            # no min_count
            {
                'type': "Homework",
                'drop_count': 0
            },
            u"Configuration has no appropriate grader class."),
        (
            # no drop_count
            {
                'type': "Homework",
                'min_count': 0
            },
            u"__init__() takes at least 4 arguments (3 given)"),
    )
    @ddt.unpack
    def test_grader_with_invalid_conf(self, invalid_conf,
                                      expected_error_message):
        with self.assertRaises(ValueError) as error:
            graders.grader_from_conf([invalid_conf])
        self.assertIn(expected_error_message, text_type(error.exception))
예제 #8
0
    def test_weighted_grading(self):
        scores = []
        agg_fields = dict(display_name="aggregated_score", module_id=None)
        prob_fields = dict(display_name="problem_score",
                           module_id=None,
                           raw_earned=0,
                           raw_possible=0,
                           weight=0)

        all_total, graded_total = aggregate_scores(
            scores, display_name=agg_fields['display_name'])
        self.assertEqual(
            all_total,
            AggregatedScore(tw_earned=0,
                            tw_possible=0,
                            graded=False,
                            **agg_fields),
        )
        self.assertEqual(
            graded_total,
            AggregatedScore(tw_earned=0,
                            tw_possible=0,
                            graded=True,
                            **agg_fields),
        )

        scores.append(
            ProblemScore(weighted_earned=0,
                         weighted_possible=5,
                         graded=False,
                         **prob_fields))
        all_total, graded_total = aggregate_scores(
            scores, display_name=agg_fields['display_name'])
        self.assertEqual(
            all_total,
            AggregatedScore(tw_earned=0,
                            tw_possible=5,
                            graded=False,
                            **agg_fields),
        )
        self.assertEqual(
            graded_total,
            AggregatedScore(tw_earned=0,
                            tw_possible=0,
                            graded=True,
                            **agg_fields),
        )

        scores.append(
            ProblemScore(weighted_earned=3,
                         weighted_possible=5,
                         graded=True,
                         **prob_fields))
        all_total, graded_total = aggregate_scores(
            scores, display_name=agg_fields['display_name'])
        self.assertAlmostEqual(
            all_total,
            AggregatedScore(tw_earned=3,
                            tw_possible=10,
                            graded=False,
                            **agg_fields),
        )
        self.assertAlmostEqual(
            graded_total,
            AggregatedScore(tw_earned=3,
                            tw_possible=5,
                            graded=True,
                            **agg_fields),
        )

        scores.append(
            ProblemScore(weighted_earned=2,
                         weighted_possible=5,
                         graded=True,
                         **prob_fields))
        all_total, graded_total = aggregate_scores(
            scores, display_name=agg_fields['display_name'])
        self.assertAlmostEqual(
            all_total,
            AggregatedScore(tw_earned=5,
                            tw_possible=15,
                            graded=False,
                            **agg_fields),
        )
        self.assertAlmostEqual(
            graded_total,
            AggregatedScore(tw_earned=5,
                            tw_possible=10,
                            graded=True,
                            **agg_fields),
        )
예제 #9
0
class GraderTest(unittest.TestCase):
    """
    Tests grader implementations
    """

    empty_gradesheet = {}

    incomplete_gradesheet = {
        'Homework': [],
        'Lab': [],
        'Midterm': [],
    }

    test_gradesheet = {
        'Homework': [
            AggregatedScore(tw_earned=2,
                            tw_possible=20.0,
                            graded=True,
                            display_name='hw1',
                            module_id=None),
            AggregatedScore(tw_earned=16,
                            tw_possible=16.0,
                            graded=True,
                            display_name='hw2',
                            module_id=None)
        ],

        # The dropped scores should be from the assignments that don't exist yet
        'Lab': [
            AggregatedScore(tw_earned=1,
                            tw_possible=2.0,
                            graded=True,
                            display_name='lab1',
                            module_id=None),  # Dropped
            AggregatedScore(tw_earned=1,
                            tw_possible=1.0,
                            graded=True,
                            display_name='lab2',
                            module_id=None),
            AggregatedScore(tw_earned=1,
                            tw_possible=1.0,
                            graded=True,
                            display_name='lab3',
                            module_id=None),
            AggregatedScore(tw_earned=5,
                            tw_possible=25.0,
                            graded=True,
                            display_name='lab4',
                            module_id=None),  # Dropped
            AggregatedScore(tw_earned=3,
                            tw_possible=4.0,
                            graded=True,
                            display_name='lab5',
                            module_id=None),  # Dropped
            AggregatedScore(tw_earned=6,
                            tw_possible=7.0,
                            graded=True,
                            display_name='lab6',
                            module_id=None),
            AggregatedScore(tw_earned=5,
                            tw_possible=6.0,
                            graded=True,
                            display_name='lab7',
                            module_id=None),
        ],
        'Midterm': [
            AggregatedScore(tw_earned=50.5,
                            tw_possible=100,
                            graded=True,
                            display_name="Midterm Exam",
                            module_id=None),
        ],
    }

    def test_single_section_grader(self):
        midterm_grader = graders.SingleSectionGrader("Midterm", "Midterm Exam")
        lab4_grader = graders.SingleSectionGrader("Lab", "lab4")
        bad_lab_grader = graders.SingleSectionGrader("Lab", "lab42")

        for graded in [
                midterm_grader.grade(self.empty_gradesheet),
                midterm_grader.grade(self.incomplete_gradesheet),
                bad_lab_grader.grade(self.test_gradesheet),
        ]:
            self.assertEqual(len(graded['section_breakdown']), 1)
            self.assertEqual(graded['percent'], 0.0)

        graded = midterm_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.505)
        self.assertEqual(len(graded['section_breakdown']), 1)

        graded = lab4_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.2)
        self.assertEqual(len(graded['section_breakdown']), 1)

    def test_assignment_format_grader(self):
        homework_grader = graders.AssignmentFormatGrader("Homework", 12, 2)
        no_drop_grader = graders.AssignmentFormatGrader("Homework", 12, 0)
        # Even though the minimum number is 3, this should grade correctly when 7 assignments are found
        overflow_grader = graders.AssignmentFormatGrader("Lab", 3, 2)
        lab_grader = graders.AssignmentFormatGrader("Lab", 7, 3)

        # Test the grading of an empty gradesheet
        for graded in [
                homework_grader.grade(self.empty_gradesheet),
                no_drop_grader.grade(self.empty_gradesheet),
                homework_grader.grade(self.incomplete_gradesheet),
                no_drop_grader.grade(self.incomplete_gradesheet),
        ]:
            self.assertAlmostEqual(graded['percent'], 0.0)
            # Make sure the breakdown includes 12 sections, plus one summary
            self.assertEqual(len(graded['section_breakdown']), 12 + 1)

        graded = homework_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'],
                               0.11)  # 100% + 10% / 10 assignments
        self.assertEqual(len(graded['section_breakdown']), 12 + 1)

        graded = no_drop_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(
            graded['percent'],
            0.0916666666666666)  # 100% + 10% / 12 assignments
        self.assertEqual(len(graded['section_breakdown']), 12 + 1)

        graded = overflow_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(
            graded['percent'],
            0.8880952380952382)  # 100% + 10% / 5 assignments
        self.assertEqual(len(graded['section_breakdown']), 7 + 1)

        graded = lab_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.9226190476190477)
        self.assertEqual(len(graded['section_breakdown']), 7 + 1)

    def test_assignment_format_grader_on_single_section_entry(self):
        midterm_grader = graders.AssignmentFormatGrader("Midterm", 1, 0)
        # Test the grading on a section with one item:
        for graded in [
                midterm_grader.grade(self.empty_gradesheet),
                midterm_grader.grade(self.incomplete_gradesheet),
        ]:
            self.assertAlmostEqual(graded['percent'], 0.0)
            # Make sure the breakdown includes just the one summary
            self.assertEqual(len(graded['section_breakdown']), 0 + 1)
            self.assertEqual(graded['section_breakdown'][0]['label'],
                             'Midterm')

        graded = midterm_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.505)
        self.assertEqual(len(graded['section_breakdown']), 0 + 1)

    def test_weighted_subsections_grader(self):
        # First, a few sub graders
        homework_grader = graders.AssignmentFormatGrader("Homework", 12, 2)
        lab_grader = graders.AssignmentFormatGrader("Lab", 7, 3)
        # phasing out the use of SingleSectionGraders, and instead using AssignmentFormatGraders that
        # will act like SingleSectionGraders on single sections.
        midterm_grader = graders.AssignmentFormatGrader("Midterm", 1, 0)

        weighted_grader = graders.WeightedSubsectionsGrader([
            (homework_grader, homework_grader.category, 0.25),
            (lab_grader, lab_grader.category, 0.25),
            (midterm_grader, midterm_grader.category, 0.5),
        ])

        over_one_weights_grader = graders.WeightedSubsectionsGrader([
            (homework_grader, homework_grader.category, 0.5),
            (lab_grader, lab_grader.category, 0.5),
            (midterm_grader, midterm_grader.category, 0.5),
        ])

        # The midterm should have all weight on this one
        zero_weights_grader = graders.WeightedSubsectionsGrader([
            (homework_grader, homework_grader.category, 0.0),
            (lab_grader, lab_grader.category, 0.0),
            (midterm_grader, midterm_grader.category, 0.5),
        ])

        # This should always have a final percent of zero
        all_zero_weights_grader = graders.WeightedSubsectionsGrader([
            (homework_grader, homework_grader.category, 0.0),
            (lab_grader, lab_grader.category, 0.0),
            (midterm_grader, midterm_grader.category, 0.0),
        ])

        empty_grader = graders.WeightedSubsectionsGrader([])

        graded = weighted_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.5106547619047619)
        self.assertEqual(len(graded['section_breakdown']),
                         (12 + 1) + (7 + 1) + 1)
        self.assertEqual(len(graded['grade_breakdown']), 3)

        graded = over_one_weights_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.7688095238095238)
        self.assertEqual(len(graded['section_breakdown']),
                         (12 + 1) + (7 + 1) + 1)
        self.assertEqual(len(graded['grade_breakdown']), 3)

        graded = zero_weights_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.2525)
        self.assertEqual(len(graded['section_breakdown']),
                         (12 + 1) + (7 + 1) + 1)
        self.assertEqual(len(graded['grade_breakdown']), 3)

        graded = all_zero_weights_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.0)
        self.assertEqual(len(graded['section_breakdown']),
                         (12 + 1) + (7 + 1) + 1)
        self.assertEqual(len(graded['grade_breakdown']), 3)

        for graded in [
                weighted_grader.grade(self.empty_gradesheet),
                weighted_grader.grade(self.incomplete_gradesheet),
                zero_weights_grader.grade(self.empty_gradesheet),
                all_zero_weights_grader.grade(self.empty_gradesheet),
        ]:
            self.assertAlmostEqual(graded['percent'], 0.0)
            self.assertEqual(len(graded['section_breakdown']),
                             (12 + 1) + (7 + 1) + 1)
            self.assertEqual(len(graded['grade_breakdown']), 3)

        graded = empty_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.0)
        self.assertEqual(len(graded['section_breakdown']), 0)
        self.assertEqual(len(graded['grade_breakdown']), 0)

    def test_grader_from_conf(self):

        # Confs always produce a graders.WeightedSubsectionsGrader, so we test this by repeating the test
        # in test_graders.WeightedSubsectionsGrader, but generate the graders with confs.

        weighted_grader = graders.grader_from_conf([
            {
                'type': "Homework",
                'min_count': 12,
                'drop_count': 2,
                'short_label': "HW",
                'weight': 0.25,
            },
            {
                'type': "Lab",
                'min_count': 7,
                'drop_count': 3,
                'category': "Labs",
                'weight': 0.25
            },
            {
                'type': "Midterm",
                'name': "Midterm Exam",
                'short_label': "Midterm",
                'weight': 0.5,
            },
        ])

        empty_grader = graders.grader_from_conf([])

        graded = weighted_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.5106547619047619)
        self.assertEqual(len(graded['section_breakdown']),
                         (12 + 1) + (7 + 1) + 1)
        self.assertEqual(len(graded['grade_breakdown']), 3)

        graded = empty_grader.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.0)
        self.assertEqual(len(graded['section_breakdown']), 0)
        self.assertEqual(len(graded['grade_breakdown']), 0)

        # Test that graders can also be used instead of lists of dictionaries
        homework_grader = graders.AssignmentFormatGrader("Homework", 12, 2)
        homework_grader2 = graders.grader_from_conf(homework_grader)

        graded = homework_grader2.grade(self.test_gradesheet)
        self.assertAlmostEqual(graded['percent'], 0.11)
        self.assertEqual(len(graded['section_breakdown']), 12 + 1)
예제 #10
0
    def test_weighted_grading(self):
        scores = []
        agg_fields = dict(display_name="aggregated_score",
                          module_id=None,
                          attempted=False)
        prob_fields = dict(
            display_name="problem_score",
            module_id=None,
            raw_earned=0,
            raw_possible=0,
            weight=0,
            attempted=False,
        )

        # No scores
        all_total, graded_total = aggregate_scores(
            scores, display_name=agg_fields['display_name'])
        self.assertEqual(
            all_total,
            AggregatedScore(tw_earned=0,
                            tw_possible=0,
                            graded=False,
                            **agg_fields),
        )
        self.assertEqual(
            graded_total,
            AggregatedScore(tw_earned=0,
                            tw_possible=0,
                            graded=True,
                            **agg_fields),
        )

        # (0/5 non-graded)
        scores.append(
            ProblemScore(weighted_earned=0,
                         weighted_possible=5,
                         graded=False,
                         **prob_fields))
        all_total, graded_total = aggregate_scores(
            scores, display_name=agg_fields['display_name'])
        self.assertEqual(
            all_total,
            AggregatedScore(tw_earned=0,
                            tw_possible=5,
                            graded=False,
                            **agg_fields),
        )
        self.assertEqual(
            graded_total,
            AggregatedScore(tw_earned=0,
                            tw_possible=0,
                            graded=True,
                            **agg_fields),
        )

        # (0/5 non-graded) + (3/5 graded) = 3/10 total, 3/5 graded
        prob_fields['attempted'] = True
        agg_fields['attempted'] = True
        scores.append(
            ProblemScore(weighted_earned=3,
                         weighted_possible=5,
                         graded=True,
                         **prob_fields))
        all_total, graded_total = aggregate_scores(
            scores, display_name=agg_fields['display_name'])
        self.assertAlmostEqual(
            all_total,
            AggregatedScore(tw_earned=3,
                            tw_possible=10,
                            graded=False,
                            **agg_fields),
        )
        self.assertAlmostEqual(
            graded_total,
            AggregatedScore(tw_earned=3,
                            tw_possible=5,
                            graded=True,
                            **agg_fields),
        )

        # (0/5 non-graded) + (3/5 graded) + (2/5 graded) = 5/15 total, 5/10 graded
        scores.append(
            ProblemScore(weighted_earned=2,
                         weighted_possible=5,
                         graded=True,
                         **prob_fields))
        all_total, graded_total = aggregate_scores(
            scores, display_name=agg_fields['display_name'])
        self.assertAlmostEqual(
            all_total,
            AggregatedScore(tw_earned=5,
                            tw_possible=15,
                            graded=False,
                            **agg_fields),
        )
        self.assertAlmostEqual(
            graded_total,
            AggregatedScore(tw_earned=5,
                            tw_possible=10,
                            graded=True,
                            **agg_fields),
        )