modify AssignmentFormatGrader to act like a SingleSectionGrader on single sections
This commit is contained in:
@@ -45,8 +45,9 @@ def invalid_args(func, argdict):
|
||||
Given a function and a dictionary of arguments, returns a set of arguments
|
||||
from argdict that aren't accepted by func
|
||||
"""
|
||||
args, varargs, keywords, defaults = inspect.getargspec(func)
|
||||
if keywords: return set() # All accepted
|
||||
args, _, keywords, _ = inspect.getargspec(func)
|
||||
if keywords:
|
||||
return set() # All accepted
|
||||
return set(argdict) - set(args)
|
||||
|
||||
|
||||
@@ -119,7 +120,7 @@ class CourseGrader(object):
|
||||
that has the matching section format.
|
||||
|
||||
The grader outputs a dictionary with the following keys:
|
||||
- percent: Contaisn a float value, which is the final percentage score for the student.
|
||||
- percent: Contains a float value, which is the final percentage score for the student.
|
||||
- section_breakdown: This is a list of dictionaries which provide details on sections
|
||||
that were graded. These are used for display in a graph or chart. The format for a
|
||||
section_breakdown dictionary is explained below.
|
||||
@@ -150,6 +151,7 @@ class CourseGrader(object):
|
||||
|
||||
@abc.abstractmethod
|
||||
def grade(self, grade_sheet, generate_random_scores=False):
|
||||
'''Given a grade sheet, return a dict containing grading information'''
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@@ -158,7 +160,10 @@ class WeightedSubsectionsGrader(CourseGrader):
|
||||
This grader takes a list of tuples containing (grader, category_name, weight) and computes
|
||||
a final grade by totalling the contribution of each sub grader and multiplying it by the
|
||||
given weight. For example, the sections may be
|
||||
[ (homeworkGrader, "Homework", 0.15), (labGrader, "Labs", 0.15), (midtermGrader, "Midterm", 0.30), (finalGrader, "Final", 0.40) ]
|
||||
|
||||
[ (homeworkGrader, "Homework", 0.15), (labGrader, "Labs", 0.15), (midtermGrader, "Midterm", 0.30),
|
||||
(finalGrader, "Final", 0.40) ]
|
||||
|
||||
All items in section_breakdown for each subgrader will be combined. A grade_breakdown will be
|
||||
composed using the score from each grader.
|
||||
|
||||
@@ -177,12 +182,12 @@ class WeightedSubsectionsGrader(CourseGrader):
|
||||
for subgrader, category, weight in self.sections:
|
||||
subgrade_result = subgrader.grade(grade_sheet, generate_random_scores)
|
||||
|
||||
weightedPercent = subgrade_result['percent'] * weight
|
||||
section_detail = "{0} = {1:.1%} of a possible {2:.0%}".format(category, weightedPercent, weight)
|
||||
weighted_percent = subgrade_result['percent'] * weight
|
||||
section_detail = "{0} = {1:.1%} of a possible {2:.0%}".format(category, weighted_percent, weight)
|
||||
|
||||
total_percent += weightedPercent
|
||||
total_percent += weighted_percent
|
||||
section_breakdown += subgrade_result['section_breakdown']
|
||||
grade_breakdown.append({'percent': weightedPercent, 'detail': section_detail, 'category': category})
|
||||
grade_breakdown.append({'percent': weighted_percent, 'detail': section_detail, 'category': category})
|
||||
|
||||
return {'percent': total_percent,
|
||||
'section_breakdown': section_breakdown,
|
||||
@@ -203,32 +208,33 @@ class SingleSectionGrader(CourseGrader):
|
||||
self.category = category or name
|
||||
|
||||
def grade(self, grade_sheet, generate_random_scores=False):
|
||||
foundScore = None
|
||||
found_score = None
|
||||
if self.type in grade_sheet:
|
||||
for score in grade_sheet[self.type]:
|
||||
if score.section == self.name:
|
||||
foundScore = score
|
||||
found_score = score
|
||||
break
|
||||
|
||||
if foundScore or generate_random_scores:
|
||||
if found_score or generate_random_scores:
|
||||
if generate_random_scores: # for debugging!
|
||||
earned = random.randint(2, 15)
|
||||
possible = random.randint(earned, 15)
|
||||
else: # We found the score
|
||||
earned = foundScore.earned
|
||||
possible = foundScore.possible
|
||||
earned = found_score.earned
|
||||
possible = found_score.possible
|
||||
|
||||
percent = earned / float(possible)
|
||||
detail = "{name} - {percent:.0%} ({earned:.3n}/{possible:.3n})".format(name=self.name,
|
||||
percent=percent,
|
||||
earned=float(earned),
|
||||
possible=float(possible))
|
||||
percent=percent,
|
||||
earned=float(earned),
|
||||
possible=float(possible))
|
||||
|
||||
else:
|
||||
percent = 0.0
|
||||
detail = "{name} - 0% (?/?)".format(name=self.name)
|
||||
|
||||
breakdown = [{'percent': percent, 'label': self.short_label, 'detail': detail, 'category': self.category, 'prominent': True}]
|
||||
breakdown = [{'percent': percent, 'label': self.short_label,
|
||||
'detail': detail, 'category': self.category, 'prominent': True}]
|
||||
|
||||
return {'percent': percent,
|
||||
'section_breakdown': breakdown,
|
||||
@@ -250,6 +256,13 @@ class AssignmentFormatGrader(CourseGrader):
|
||||
show_only_average is to suppress the display of each assignment in this grader and instead
|
||||
only show the total score of this grader in the breakdown.
|
||||
|
||||
hide_average is to suppress the display of the total score in this grader and instead
|
||||
only show each assignment in this grader in the breakdown.
|
||||
|
||||
If there is only a single assignment in this grader, then it acts like a SingleSectionGrader
|
||||
and returns only one entry for the grader. Since the assignment and the total are the same,
|
||||
the total is returned but is not labeled as an average.
|
||||
|
||||
category should be presentable to the user, but may not appear. When the grade breakdown is
|
||||
displayed, scores from the same category will be similar (for example, by color).
|
||||
|
||||
@@ -263,7 +276,8 @@ class AssignmentFormatGrader(CourseGrader):
|
||||
min_count = 2 would produce the labels "Assignment 3", "Assignment 4"
|
||||
|
||||
"""
|
||||
def __init__(self, type, min_count, drop_count, category=None, section_type=None, short_label=None, show_only_average=False, hide_average=False, starting_index=1):
|
||||
def __init__(self, type, min_count, drop_count, category=None, section_type=None, short_label=None,
|
||||
show_only_average=False, hide_average=False, starting_index=1):
|
||||
self.type = type
|
||||
self.min_count = min_count
|
||||
self.drop_count = drop_count
|
||||
@@ -275,7 +289,8 @@ class AssignmentFormatGrader(CourseGrader):
|
||||
self.hide_average = hide_average
|
||||
|
||||
def grade(self, grade_sheet, generate_random_scores=False):
|
||||
def totalWithDrops(breakdown, drop_count):
|
||||
def total_with_drops(breakdown, drop_count):
|
||||
'''calculates total score for a section while dropping lowest scores'''
|
||||
#create an array of tuples with (index, mark), sorted by mark['percent'] descending
|
||||
sorted_breakdown = sorted(enumerate(breakdown), key=lambda x: -x[1]['percent'])
|
||||
# A list of the indices of the dropped scores
|
||||
@@ -308,33 +323,50 @@ class AssignmentFormatGrader(CourseGrader):
|
||||
section_name = scores[i].section
|
||||
|
||||
percentage = earned / float(possible)
|
||||
summary = "{section_type} {index} - {name} - {percent:.0%} ({earned:.3n}/{possible:.3n})".format(index=i + self.starting_index,
|
||||
section_type=self.section_type,
|
||||
name=section_name,
|
||||
percent=percentage,
|
||||
earned=float(earned),
|
||||
possible=float(possible))
|
||||
summary_format = "{section_type} {index} - {name} - {percent:.0%} ({earned:.3n}/{possible:.3n})"
|
||||
summary = summary_format.format(index=i + self.starting_index,
|
||||
section_type=self.section_type,
|
||||
name=section_name,
|
||||
percent=percentage,
|
||||
earned=float(earned),
|
||||
possible=float(possible))
|
||||
else:
|
||||
percentage = 0
|
||||
summary = "{section_type} {index} Unreleased - 0% (?/?)".format(index=i + self.starting_index, section_type=self.section_type)
|
||||
summary = "{section_type} {index} Unreleased - 0% (?/?)".format(index=i + self.starting_index,
|
||||
section_type=self.section_type)
|
||||
|
||||
short_label = "{short_label} {index:02d}".format(index=i + self.starting_index, short_label=self.short_label)
|
||||
short_label = "{short_label} {index:02d}".format(index=i + self.starting_index,
|
||||
short_label=self.short_label)
|
||||
|
||||
breakdown.append({'percent': percentage, 'label': short_label, 'detail': summary, 'category': self.category})
|
||||
breakdown.append({'percent': percentage, 'label': short_label,
|
||||
'detail': summary, 'category': self.category})
|
||||
|
||||
total_percent, dropped_indices = totalWithDrops(breakdown, self.drop_count)
|
||||
total_percent, dropped_indices = total_with_drops(breakdown, self.drop_count)
|
||||
|
||||
for dropped_index in dropped_indices:
|
||||
breakdown[dropped_index]['mark'] = {'detail': "The lowest {drop_count} {section_type} scores are dropped.".format(drop_count=self.drop_count, section_type=self.section_type)}
|
||||
breakdown[dropped_index]['mark'] = {'detail': "The lowest {drop_count} {section_type} scores are dropped."
|
||||
.format(drop_count=self.drop_count, section_type=self.section_type)}
|
||||
|
||||
total_detail = "{section_type} Average = {percent:.0%}".format(percent=total_percent, section_type=self.section_type)
|
||||
total_label = "{short_label} Avg".format(short_label=self.short_label)
|
||||
if len(breakdown) == 1:
|
||||
# if there is only one entry in a section, suppress the existing individual entry and the average,
|
||||
# and just display a single entry for the section. That way it acts automatically like a
|
||||
# SingleSectionGrader.
|
||||
total_detail = "{section_type} = {percent:.0%}".format(percent=total_percent,
|
||||
section_type=self.section_type)
|
||||
total_label = "{short_label}".format(short_label=self.short_label)
|
||||
breakdown = [{'percent': total_percent, 'label': total_label,
|
||||
'detail': total_detail, 'category': self.category, 'prominent': True}, ]
|
||||
else:
|
||||
total_detail = "{section_type} Average = {percent:.0%}".format(percent=total_percent,
|
||||
section_type=self.section_type)
|
||||
total_label = "{short_label} Avg".format(short_label=self.short_label)
|
||||
|
||||
if self.show_only_average:
|
||||
breakdown = []
|
||||
if self.show_only_average:
|
||||
breakdown = []
|
||||
|
||||
if not self.hide_average:
|
||||
breakdown.append({'percent': total_percent, 'label': total_label, 'detail': total_detail, 'category': self.category, 'prominent': True})
|
||||
if not self.hide_average:
|
||||
breakdown.append({'percent': total_percent, 'label': total_label,
|
||||
'detail': total_detail, 'category': self.category, 'prominent': True})
|
||||
|
||||
return {'percent': total_percent,
|
||||
'section_breakdown': breakdown,
|
||||
|
||||
@@ -6,32 +6,34 @@ from xmodule.graders import Score, aggregate_scores
|
||||
|
||||
|
||||
class GradesheetTest(unittest.TestCase):
|
||||
'''Tests the aggregate_scores method'''
|
||||
|
||||
def test_weighted_grading(self):
|
||||
scores = []
|
||||
Score.__sub__ = lambda me, other: (me.earned - other.earned) + (me.possible - other.possible)
|
||||
|
||||
all, graded = aggregate_scores(scores)
|
||||
self.assertEqual(all, Score(earned=0, possible=0, graded=False, section="summary"))
|
||||
self.assertEqual(graded, Score(earned=0, possible=0, graded=True, section="summary"))
|
||||
all_total, graded_total = aggregate_scores(scores)
|
||||
self.assertEqual(all_total, Score(earned=0, possible=0, graded=False, section="summary"))
|
||||
self.assertEqual(graded_total, Score(earned=0, possible=0, graded=True, section="summary"))
|
||||
|
||||
scores.append(Score(earned=0, possible=5, graded=False, section="summary"))
|
||||
all, graded = aggregate_scores(scores)
|
||||
self.assertEqual(all, Score(earned=0, possible=5, graded=False, section="summary"))
|
||||
self.assertEqual(graded, Score(earned=0, possible=0, graded=True, section="summary"))
|
||||
all_total, graded_total = aggregate_scores(scores)
|
||||
self.assertEqual(all_total, Score(earned=0, possible=5, graded=False, section="summary"))
|
||||
self.assertEqual(graded_total, Score(earned=0, possible=0, graded=True, section="summary"))
|
||||
|
||||
scores.append(Score(earned=3, possible=5, graded=True, section="summary"))
|
||||
all, graded = aggregate_scores(scores)
|
||||
self.assertAlmostEqual(all, Score(earned=3, possible=10, graded=False, section="summary"))
|
||||
self.assertAlmostEqual(graded, Score(earned=3, possible=5, graded=True, section="summary"))
|
||||
all_total, graded_total = aggregate_scores(scores)
|
||||
self.assertAlmostEqual(all_total, Score(earned=3, possible=10, graded=False, section="summary"))
|
||||
self.assertAlmostEqual(graded_total, Score(earned=3, possible=5, graded=True, section="summary"))
|
||||
|
||||
scores.append(Score(earned=2, possible=5, graded=True, section="summary"))
|
||||
all, graded = aggregate_scores(scores)
|
||||
self.assertAlmostEqual(all, Score(earned=5, possible=15, graded=False, section="summary"))
|
||||
self.assertAlmostEqual(graded, Score(earned=5, possible=10, graded=True, section="summary"))
|
||||
all_total, graded_total = aggregate_scores(scores)
|
||||
self.assertAlmostEqual(all_total, Score(earned=5, possible=15, graded=False, section="summary"))
|
||||
self.assertAlmostEqual(graded_total, Score(earned=5, possible=10, graded=True, section="summary"))
|
||||
|
||||
|
||||
class GraderTest(unittest.TestCase):
|
||||
'''Tests grader implementations'''
|
||||
|
||||
empty_gradesheet = {
|
||||
}
|
||||
@@ -44,136 +46,152 @@ class GraderTest(unittest.TestCase):
|
||||
|
||||
test_gradesheet = {
|
||||
'Homework': [Score(earned=2, possible=20.0, graded=True, section='hw1'),
|
||||
Score(earned=16, possible=16.0, graded=True, section='hw2')],
|
||||
#The dropped scores should be from the assignments that don't exist yet
|
||||
Score(earned=16, possible=16.0, graded=True, section='hw2')],
|
||||
# The dropped scores should be from the assignments that don't exist yet
|
||||
|
||||
'Lab': [Score(earned=1, possible=2.0, graded=True, section='lab1'), # Dropped
|
||||
Score(earned=1, possible=1.0, graded=True, section='lab2'),
|
||||
Score(earned=1, possible=1.0, graded=True, section='lab3'),
|
||||
Score(earned=5, possible=25.0, graded=True, section='lab4'), # Dropped
|
||||
Score(earned=3, possible=4.0, graded=True, section='lab5'), # Dropped
|
||||
Score(earned=6, possible=7.0, graded=True, section='lab6'),
|
||||
Score(earned=5, possible=6.0, graded=True, section='lab7')],
|
||||
Score(earned=1, possible=1.0, graded=True, section='lab2'),
|
||||
Score(earned=1, possible=1.0, graded=True, section='lab3'),
|
||||
Score(earned=5, possible=25.0, graded=True, section='lab4'), # Dropped
|
||||
Score(earned=3, possible=4.0, graded=True, section='lab5'), # Dropped
|
||||
Score(earned=6, possible=7.0, graded=True, section='lab6'),
|
||||
Score(earned=5, possible=6.0, graded=True, section='lab7')],
|
||||
|
||||
'Midterm': [Score(earned=50.5, possible=100, graded=True, section="Midterm Exam"), ],
|
||||
}
|
||||
|
||||
def test_SingleSectionGrader(self):
|
||||
midtermGrader = graders.SingleSectionGrader("Midterm", "Midterm Exam")
|
||||
lab4Grader = graders.SingleSectionGrader("Lab", "lab4")
|
||||
badLabGrader = graders.SingleSectionGrader("Lab", "lab42")
|
||||
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 [midtermGrader.grade(self.empty_gradesheet),
|
||||
midtermGrader.grade(self.incomplete_gradesheet),
|
||||
badLabGrader.grade(self.test_gradesheet)]:
|
||||
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 = midtermGrader.grade(self.test_gradesheet)
|
||||
graded = midterm_grader.grade(self.test_gradesheet)
|
||||
self.assertAlmostEqual(graded['percent'], 0.505)
|
||||
self.assertEqual(len(graded['section_breakdown']), 1)
|
||||
|
||||
graded = lab4Grader.grade(self.test_gradesheet)
|
||||
graded = lab4_grader.grade(self.test_gradesheet)
|
||||
self.assertAlmostEqual(graded['percent'], 0.2)
|
||||
self.assertEqual(len(graded['section_breakdown']), 1)
|
||||
|
||||
def test_AssignmentFormatGrader(self):
|
||||
homeworkGrader = graders.AssignmentFormatGrader("Homework", 12, 2)
|
||||
noDropGrader = graders.AssignmentFormatGrader("Homework", 12, 0)
|
||||
#Even though the minimum number is 3, this should grade correctly when 7 assignments are found
|
||||
overflowGrader = graders.AssignmentFormatGrader("Lab", 3, 2)
|
||||
labGrader = graders.AssignmentFormatGrader("Lab", 7, 3)
|
||||
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 [homeworkGrader.grade(self.empty_gradesheet),
|
||||
noDropGrader.grade(self.empty_gradesheet),
|
||||
homeworkGrader.grade(self.incomplete_gradesheet),
|
||||
noDropGrader.grade(self.incomplete_gradesheet)]:
|
||||
# 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
|
||||
# Make sure the breakdown includes 12 sections, plus one summary
|
||||
self.assertEqual(len(graded['section_breakdown']), 12 + 1)
|
||||
|
||||
graded = homeworkGrader.grade(self.test_gradesheet)
|
||||
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 = noDropGrader.grade(self.test_gradesheet)
|
||||
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 = overflowGrader.grade(self.test_gradesheet)
|
||||
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 = labGrader.grade(self.test_gradesheet)
|
||||
graded = lab_grader.grade(self.test_gradesheet)
|
||||
self.assertAlmostEqual(graded['percent'], 0.9226190476190477)
|
||||
self.assertEqual(len(graded['section_breakdown']), 7 + 1)
|
||||
|
||||
def test_WeightedSubsectionsGrader(self):
|
||||
#First, a few sub graders
|
||||
homeworkGrader = graders.AssignmentFormatGrader("Homework", 12, 2)
|
||||
labGrader = graders.AssignmentFormatGrader("Lab", 7, 3)
|
||||
midtermGrader = graders.SingleSectionGrader("Midterm", "Midterm Exam")
|
||||
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')
|
||||
|
||||
weightedGrader = graders.WeightedSubsectionsGrader([(homeworkGrader, homeworkGrader.category, 0.25),
|
||||
(labGrader, labGrader.category, 0.25),
|
||||
(midtermGrader, midtermGrader.category, 0.5)])
|
||||
graded = midterm_grader.grade(self.test_gradesheet)
|
||||
self.assertAlmostEqual(graded['percent'], 0.505)
|
||||
self.assertEqual(len(graded['section_breakdown']), 0 + 1)
|
||||
|
||||
overOneWeightsGrader = graders.WeightedSubsectionsGrader([(homeworkGrader, homeworkGrader.category, 0.5),
|
||||
(labGrader, labGrader.category, 0.5),
|
||||
(midtermGrader, midtermGrader.category, 0.5)])
|
||||
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)
|
||||
|
||||
#The midterm should have all weight on this one
|
||||
zeroWeightsGrader = graders.WeightedSubsectionsGrader([(homeworkGrader, homeworkGrader.category, 0.0),
|
||||
(labGrader, labGrader.category, 0.0),
|
||||
(midtermGrader, midtermGrader.category, 0.5)])
|
||||
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)])
|
||||
|
||||
#This should always have a final percent of zero
|
||||
allZeroWeightsGrader = graders.WeightedSubsectionsGrader([(homeworkGrader, homeworkGrader.category, 0.0),
|
||||
(labGrader, labGrader.category, 0.0),
|
||||
(midtermGrader, midtermGrader.category, 0.0)])
|
||||
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)])
|
||||
|
||||
emptyGrader = graders.WeightedSubsectionsGrader([])
|
||||
# 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)])
|
||||
|
||||
graded = weightedGrader.grade(self.test_gradesheet)
|
||||
# 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 = overOneWeightsGrader.grade(self.test_gradesheet)
|
||||
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 = zeroWeightsGrader.grade(self.test_gradesheet)
|
||||
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 = allZeroWeightsGrader.grade(self.test_gradesheet)
|
||||
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 [weightedGrader.grade(self.empty_gradesheet),
|
||||
weightedGrader.grade(self.incomplete_gradesheet),
|
||||
zeroWeightsGrader.grade(self.empty_gradesheet),
|
||||
allZeroWeightsGrader.grade(self.empty_gradesheet)]:
|
||||
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 = emptyGrader.grade(self.test_gradesheet)
|
||||
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_graderFromConf(self):
|
||||
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.
|
||||
# Confs always produce a graders.WeightedSubsectionsGrader, so we test this by repeating the test
|
||||
# in test_graders.WeightedSubsectionsGrader, but generate the graders with confs.
|
||||
|
||||
weightedGrader = graders.grader_from_conf([
|
||||
weighted_grader = graders.grader_from_conf([
|
||||
{
|
||||
'type': "Homework",
|
||||
'min_count': 12,
|
||||
@@ -196,25 +214,25 @@ class GraderTest(unittest.TestCase):
|
||||
},
|
||||
])
|
||||
|
||||
emptyGrader = graders.grader_from_conf([])
|
||||
empty_grader = graders.grader_from_conf([])
|
||||
|
||||
graded = weightedGrader.grade(self.test_gradesheet)
|
||||
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 = emptyGrader.grade(self.test_gradesheet)
|
||||
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
|
||||
homeworkGrader = graders.AssignmentFormatGrader("Homework", 12, 2)
|
||||
homeworkGrader2 = graders.grader_from_conf(homeworkGrader)
|
||||
# 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 = homeworkGrader2.grade(self.test_gradesheet)
|
||||
graded = homework_grader2.grade(self.test_gradesheet)
|
||||
self.assertAlmostEqual(graded['percent'], 0.11)
|
||||
self.assertEqual(len(graded['section_breakdown']), 12 + 1)
|
||||
|
||||
#TODO: How do we test failure cases? The parser only logs an error when
|
||||
#it can't parse something. Maybe it should throw exceptions?
|
||||
# TODO: How do we test failure cases? The parser only logs an error when
|
||||
# it can't parse something. Maybe it should throw exceptions?
|
||||
|
||||
Reference in New Issue
Block a user