/**********************************************************************************
*
* $Id: GradeManagerTest.java 105079 2012-02-24 23:08:11Z ottenhoff@longsight.com $
*
***********************************************************************************
*
* Copyright (c) 2005, 2006, 2007, 2008 The Sakai Foundation, The MIT Corporation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**********************************************************************************/
package org.sakaiproject.tool.gradebook.test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import junit.framework.Assert;
import org.sakaiproject.tool.gradebook.Assignment;
import org.sakaiproject.tool.gradebook.AssignmentGradeRecord;
import org.sakaiproject.tool.gradebook.CourseGrade;
import org.sakaiproject.tool.gradebook.CourseGradeRecord;
import org.sakaiproject.tool.gradebook.GradeMapping;
import org.sakaiproject.tool.gradebook.Gradebook;
import org.sakaiproject.tool.gradebook.GradingEvents;
/**
* Tests the grade manager.
*
*/
public class GradeManagerTest extends GradebookTestBase {
protected Gradebook gradebook;
protected void onSetUpInTransaction() throws Exception {
super.onSetUpInTransaction();
String gradebookName = this.getClass().getName();
gradebookFrameworkService.addGradebook(gradebookName, gradebookName);
// Set up a holder for enrollments, teaching assignments, and sections.
integrationSupport.createCourse(gradebookName, gradebookName, false, false, false);
// Grab the gradebook for use in the tests
gradebook = gradebookManager.getGradebook(gradebookName);
}
public void testGradeManager() throws Exception {
List studentUidsList = Arrays.asList(new String[] {
"testStudentUserUid1",
"testStudentUserUid2",
"testStudentUserUid3",
});
addUsersEnrollments(gradebook, studentUidsList);
gradebookManager.createAssignment(gradebook.getId(), "Assignment #1", new Double(20), new Date(), Boolean.FALSE,Boolean.FALSE, Boolean.FALSE);
Assignment persistentAssignment = (Assignment)gradebookManager.
getAssignmentsWithStats(gradebook.getId(), Assignment.DEFAULT_SORT, true).get(0);
Map studentAssignmentScoreMap = new HashMap();
studentAssignmentScoreMap.put(studentUidsList.get(0), new Double(18));
studentAssignmentScoreMap.put(studentUidsList.get(1), new Double(19));
studentAssignmentScoreMap.put(studentUidsList.get(2), new Double(20));
Map gradeRecordMap = new HashMap();
gradeRecordMap.put(studentUidsList.get(0), new AssignmentGradeRecord(persistentAssignment, (String)studentUidsList.get(0), (Double)studentAssignmentScoreMap.get(studentUidsList.get(0))));
gradeRecordMap.put(studentUidsList.get(1), new AssignmentGradeRecord(persistentAssignment, (String)studentUidsList.get(1), (Double)studentAssignmentScoreMap.get(studentUidsList.get(1))));
gradeRecordMap.put(studentUidsList.get(2), new AssignmentGradeRecord(persistentAssignment, (String)studentUidsList.get(2), (Double)studentAssignmentScoreMap.get(studentUidsList.get(2))));
gradebookManager.updateAssignmentGradeRecords(persistentAssignment, gradeRecordMap.values());
// Fetch the grade records
List records = gradebookManager.getAssignmentGradeRecords(persistentAssignment, studentUidsList);
// Ensure that each of the students in the map have a grade record, and
// that their grade is correct
Set students = new HashSet(studentUidsList);
for(Iterator iter = records.iterator(); iter.hasNext();) {
AssignmentGradeRecord agr = (AssignmentGradeRecord)iter.next();
double tmpScore = ((AssignmentGradeRecord)gradeRecordMap.get(agr.getStudentId())).getPointsEarned().doubleValue();
double persistentScore = agr.getPointsEarned().doubleValue();
Assert.assertTrue(tmpScore == persistentScore);
}
// Add overrides to the course grades
CourseGrade courseGrade = gradebookManager.getCourseGrade(gradebook.getId());
records = gradebookManager.getPointsEarnedCourseGradeRecords(courseGrade, students);
gradeRecordMap = new HashMap();
for(Iterator iter = records.iterator(); iter.hasNext();) {
CourseGradeRecord record = (CourseGradeRecord)iter.next();
if(record.getStudentId().equals(studentUidsList.get(0))) {
record.setEnteredGrade("C-");
} else if(record.getStudentId().equals(studentUidsList.get(1))) {
record.setEnteredGrade("D+");
} else if(record.getStudentId().equals(studentUidsList.get(2))) {
record.setEnteredGrade("F");
}
gradeRecordMap.put(record.getStudentId(), record);
}
gradebookManager.updateCourseGradeRecords(courseGrade, gradeRecordMap.values());
GradeMapping gradeMapping = gradebook.getSelectedGradeMapping();
// Ensure that the sort grades have been updated to reflect the overridden grades
List courseGradeRecords = gradebookManager.getPointsEarnedCourseGradeRecords(courseGrade, studentUidsList);
for(Iterator iter = courseGradeRecords.iterator(); iter.hasNext();) {
CourseGradeRecord cgr = (CourseGradeRecord)iter.next();
Double sortGrade = cgr.getGradeAsPercentage();
String studentId = cgr.getStudentId();
String tmpGrade = ((CourseGradeRecord)gradeRecordMap.get(studentId)).getEnteredGrade();
if (logger.isDebugEnabled()) logger.debug("sortGrade=" + sortGrade + ", gradeMapping=" + gradeMapping + ", tmpGrade=" + tmpGrade);
Assert.assertTrue(sortGrade.equals(gradeMapping.getValue(tmpGrade)));
Assert.assertTrue(gradeMapping.getGrade(cgr.getGradeAsPercentage()).equals(tmpGrade));
}
// Remove the overrides
gradeRecordMap = new HashMap();
for(Iterator iter = records.iterator(); iter.hasNext();) {
CourseGradeRecord record = (CourseGradeRecord)iter.next();
record.setEnteredGrade(null);
gradeRecordMap.put(record.getStudentId(), record);
}
gradebookManager.updateCourseGradeRecords(courseGrade, gradeRecordMap.values());
// Ensure that the sort grades have been updated
courseGradeRecords = gradebookManager.getPointsEarnedCourseGradeRecords(courseGrade, studentUidsList);
double totalPoints = gradebookManager.getTotalPoints(gradebook.getId());
for(Iterator iter = courseGradeRecords.iterator(); iter.hasNext();) {
CourseGradeRecord cgr = (CourseGradeRecord)iter.next();
double percent = ((Double)studentAssignmentScoreMap.get(cgr.getStudentId())).doubleValue() / totalPoints * 100.0;
Double sortGrade = cgr.getGradeAsPercentage();
Assert.assertTrue(sortGrade.doubleValue() - percent < .001);
}
}
public void testNewExcessiveScores() throws Exception {
List studentUidsList = Arrays.asList(new String[] {
"normalStudent",
"goodStudent",
"excessiveStudent",
});
addUsersEnrollments(gradebook, studentUidsList);
gradebookManager.createAssignment(gradebook.getId(), "Excessive Test", new Double(10), new Date(), Boolean.FALSE,Boolean.FALSE,Boolean.FALSE);
Assignment asn = (Assignment)gradebookManager.getAssignmentsWithStats(gradebook.getId(), Assignment.DEFAULT_SORT, true).get(0);
// Create a grade record set
List gradeRecords = new ArrayList();
gradeRecords.add(new AssignmentGradeRecord(asn, "normalStudent", new Double(9)));
gradeRecords.add(new AssignmentGradeRecord(asn, "goodStudent", new Double(10)));
gradeRecords.add(new AssignmentGradeRecord(asn, "excessiveStudent", new Double(11)));
Set excessives = gradebookManager.updateAssignmentGradeRecords(asn, gradeRecords);
Assert.assertTrue(excessives.size() == 1);
Assert.assertTrue(excessives.contains("excessiveStudent"));
}
public void testAssignmentScoresEntered() throws Exception {
Set students = new HashSet();
students.add("entered1");
Long asgId = gradebookManager.createAssignment(gradebook.getId(), "Scores Entered Test", new Double(10), new Date(), Boolean.FALSE,Boolean.FALSE,Boolean.FALSE
);
Assignment asn = (Assignment)gradebookManager.getAssignmentsWithStats(gradebook.getId(), Assignment.DEFAULT_SORT, true).get(0);
Assert.assertTrue(!gradebookManager.isEnteredAssignmentScores(asgId));
List gradeRecords = new ArrayList();
gradeRecords.add(new AssignmentGradeRecord(asn, "entered1", new Double(9)));
gradebookManager.updateAssignmentGradeRecords(asn, gradeRecords);
Assert.assertTrue(gradebookManager.isEnteredAssignmentScores(asgId));
List persistentGradeRecords = gradebookManager.getAssignmentGradeRecords(asn, students);
gradeRecords = new ArrayList();
AssignmentGradeRecord gradeRecord = (AssignmentGradeRecord)persistentGradeRecords.get(0);
gradeRecord.setPointsEarned(null);
gradeRecords.add(gradeRecord);
gradebookManager.updateAssignmentGradeRecords(asn, gradeRecords);
Assert.assertTrue(!gradebookManager.isEnteredAssignmentScores(asgId));
}
public void testGradeEvents() throws Exception {
String studentId = "student1";
List studentUidsList = Arrays.asList(new String[] {
studentId,
});
gradebookManager.createAssignment(gradebook.getId(), "GradingEvent Test", new Double(10), new Date(), Boolean.FALSE,Boolean.FALSE,Boolean.FALSE);
Assignment assignment = (Assignment)gradebookManager.getAssignments(gradebook.getId()).get(0);
// Create a map of studentUserUids to grades
List gradeRecords = new ArrayList();
gradeRecords.add(new AssignmentGradeRecord(assignment, studentId, new Double(9)));
// Save the grades
gradebookManager.updateAssignmentGradeRecords(assignment, gradeRecords);
// Update the grades (make sure we grab them from the db, first)
Set students = new HashSet();
students.add(studentId);
List persistentGradeRecords = gradebookManager.getAssignmentGradeRecords(assignment, students);
gradeRecords = new ArrayList();
AssignmentGradeRecord gradeRecord = (AssignmentGradeRecord)persistentGradeRecords.get(0);
gradeRecord.setPointsEarned(new Double(10));
gradeRecords.add(gradeRecord);
gradebookManager.updateAssignmentGradeRecords(assignment, gradeRecords);
// Ensure that there are two grading events for this student
GradingEvents events = gradebookManager.getGradingEvents(assignment, studentUidsList);
Assert.assertEquals(events.getEvents(studentId).size(), 2);
}
public void testDroppedStudents() throws Exception {
Gradebook gradebook = gradebookManager.getGradebook(this.getClass().getName());
Long asgId = gradebookManager.createAssignment(gradebook.getId(), "Dropped Students Test", new Double(10), new Date(), Boolean.FALSE,Boolean.FALSE,Boolean.FALSE);
Assignment asn = gradebookManager.getAssignment(asgId);
// We need to operate on whatever grade records already exist in the db
List studentUidsList = Arrays.asList(new String[] {
"realStudent1",
"realStudent2",
});
addUsersEnrollments(gradebook, studentUidsList);
// Create a grade record set
List gradeRecords = new ArrayList();
gradeRecords.add(new AssignmentGradeRecord(asn, "realStudent1", new Double(10)));
gradeRecords.add(new AssignmentGradeRecord(asn, "realStudent2", new Double(10)));
gradeRecords.add(new AssignmentGradeRecord(asn, "droppedStudent", new Double(1)));
gradebookManager.updateAssignmentGradeRecords(asn, gradeRecords);
asn = gradebookManager.getAssignmentWithStats(asgId);
// Make sure the dropped student wasn't included in the average.
Assert.assertTrue(asn.getMean().doubleValue() == 100.0);
// Now add the dropped student.
studentUidsList = Arrays.asList(new String[] {
"droppedStudent",
});
addUsersEnrollments(gradebook, studentUidsList);
asn = gradebookManager.getAssignmentWithStats(asgId);
Assert.assertTrue(asn.getMean().doubleValue() < 100.0);
// Make sure that dropped students can't prevent changing final grade types.
CourseGrade courseGrade = getCourseGradeWithStats(gradebook.getId());
gradeRecords = new ArrayList();
CourseGradeRecord courseGradeRecord = new CourseGradeRecord(courseGrade, "noSuchStudent");
courseGradeRecord.setEnteredGrade("C-");
gradeRecords.add(courseGradeRecord);
gradebookManager.updateCourseGradeRecords(courseGrade, gradeRecords);
Assert.assertFalse(gradebookManager.isExplicitlyEnteredCourseGradeRecords(gradebook.getId()));
}
public void testNotCountedAssignments() throws Exception {
List studentUidsList = Arrays.asList(new String[] {
"testStudentUserUid1",
});
addUsersEnrollments(gradebook, studentUidsList);
Long id1 = gradebookManager.createAssignment(gradebook.getId(), "asn1", new Double(10), null, Boolean.FALSE,Boolean.TRUE,Boolean.FALSE);
Long id2 = gradebookManager.createAssignment(gradebook.getId(), "asn2", new Double(20), new Date(10), Boolean.FALSE,Boolean.TRUE,Boolean.FALSE);
Assignment asn1 = gradebookManager.getAssignmentWithStats(id1);
Assignment asn2 = gradebookManager.getAssignmentWithStats(id2);
// Add some scores to the assignments.
List gradeRecords = new ArrayList();
gradeRecords.add(new AssignmentGradeRecord(asn1, (String)studentUidsList.get(0), new Double(8)));
gradebookManager.updateAssignmentGradeRecords(asn1, gradeRecords);
gradeRecords = new ArrayList();
gradeRecords.add(new AssignmentGradeRecord(asn2, (String)studentUidsList.get(0), new Double(18)));
gradebookManager.updateAssignmentGradeRecords(asn2, gradeRecords);
// Make sure that the Course Grade total points includes both.
CourseGrade courseGrade = getCourseGradeWithStats(gradebook.getId());
List courseGradeRecords = gradebookManager.getPointsEarnedCourseGradeRecords(courseGrade, studentUidsList);
CourseGradeRecord cgr = (CourseGradeRecord)courseGradeRecords.get(0);
Assert.assertTrue(cgr.getPointsEarned().doubleValue() == 26.0);
// Don't count one assignment.
asn2.setNotCounted(true);
gradebookManager.updateAssignment(asn2);
// Get what the student will see.
CourseGradeRecord scgr = gradebookManager.getStudentCourseGradeRecord(gradebook, (String)studentUidsList.get(0));
// Make sure it's not counted.
courseGrade = getCourseGradeWithStats(gradebook.getId());
courseGradeRecords = gradebookManager.getPointsEarnedCourseGradeRecords(courseGrade, studentUidsList);
cgr = (CourseGradeRecord)courseGradeRecords.get(0);
// Assert.assertTrue(cgr.getPointsEarned().doubleValue() == 8.0);
// Make sure there's no disconnect between what the instructor
// will see and what the student will see.
Assert.assertTrue(cgr.getNonNullAutoCalculatedGrade().equals(scgr.getGradeAsPercentage()));
// Test what is now (unfortunately) a different code path.
List persistentGradeRecords = gradebookManager.getAssignmentGradeRecords(asn1, studentUidsList);
AssignmentGradeRecord gradeRecord = (AssignmentGradeRecord)persistentGradeRecords.get(0);
gradeRecord.setPointsEarned(new Double(7));
gradeRecords = new ArrayList();
gradeRecords.add(gradeRecord);
gradebookManager.updateAssignmentGradeRecords(asn1, gradeRecords);
courseGradeRecords = gradebookManager.getPointsEarnedCourseGradeRecords(courseGrade, studentUidsList);
cgr = (CourseGradeRecord)courseGradeRecords.get(0);
// Assert.assertTrue(cgr.getPointsEarned().doubleValue() == 7.0);
}
/**
* This tests an edge case responsible for an earlier bug: If an unscored assignment
* changes whether it's counted towards the course grade, all course grades need
* to be recalculated because the total points possible have changed.
*/
public void testNotCountedUnscoredAssignments() throws Exception {
List studentUidsList = Arrays.asList(new String[] {
"testStudentUserUid1",
});
addUsersEnrollments(gradebook, studentUidsList);
Long id1 = gradebookManager.createAssignment(gradebook.getId(), "asn1", new Double(10), null, Boolean.FALSE,Boolean.FALSE,Boolean.FALSE);
Long id2 = gradebookManager.createAssignment(gradebook.getId(), "asn2", new Double(20), new Date(10), Boolean.FALSE,Boolean.FALSE,Boolean.FALSE);
Assignment asn1 = gradebookManager.getAssignmentWithStats(id1);
Assignment asn2 = gradebookManager.getAssignmentWithStats(id2);
// Only score the first assignment.
List gradeRecords = new ArrayList();
gradeRecords.add(new AssignmentGradeRecord(asn1, (String)studentUidsList.get(0), new Double(8)));
gradebookManager.updateAssignmentGradeRecords(asn1, gradeRecords);
// Don't count the unscored assignment.
asn2.setNotCounted(true);
gradebookManager.updateAssignment(asn2);
// Get what the student will see.
CourseGradeRecord scgr = gradebookManager.getStudentCourseGradeRecord(gradebook, (String)studentUidsList.get(0));
// Make sure it's not counted.
CourseGrade courseGrade = getCourseGradeWithStats(gradebook.getId());
List courseGradeRecords = gradebookManager.getPointsEarnedCourseGradeRecords(courseGrade, studentUidsList);
CourseGradeRecord cgr = (CourseGradeRecord)courseGradeRecords.get(0);
Assert.assertTrue(cgr.getPointsEarned().doubleValue() == 8.0);
// Make sure there's no disconnect between what the instructor
// will see and what the student will see.
Assert.assertTrue(cgr.getNonNullAutoCalculatedGrade().equals(scgr.getGradeAsPercentage()));
}
}