/**********************************************************************************
*
* $Id: GradebookServiceTest.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.Iterator;
import java.util.List;
import java.util.Map;
import junit.framework.Assert;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.service.gradebook.shared.AssignmentHasIllegalPointsException;
import org.sakaiproject.service.gradebook.shared.ConflictingAssignmentNameException;
import org.sakaiproject.service.gradebook.shared.ConflictingExternalIdException;
import org.sakaiproject.tool.gradebook.Assignment;
import org.sakaiproject.tool.gradebook.AssignmentGradeRecord;
import org.sakaiproject.tool.gradebook.CourseGradeRecord;
import org.sakaiproject.tool.gradebook.Gradebook;
/**
* Uses spring's mock-objects to test the gradebook service without modifying the database
*
* @author <a href="mailto:jholtzman@berkeley.edu">Josh Holtzman</a>
*/
public class GradebookServiceTest extends GradebookTestBase {
private static final Log log = LogFactory.getLog(GradebookServiceTest.class);
private static final String GRADEBOOK_UID = "gradebookServiceTest";
private static final String ASN_1 = "Assignment #1";
private static final String EXT_ID_1 = "External #1";
private static final String EXT_TITLE_1 = "External Title #1";
private Long asn_1Id;
/**
* @see org.springframework.test.AbstractTransactionalSpringContextTests#onSetUpInTransaction()
*/
protected void onSetUpInTransaction() throws Exception {
super.onSetUpInTransaction();
gradebookFrameworkService.addGradebook(GRADEBOOK_UID, GRADEBOOK_UID);
Gradebook gradebook = gradebookManager.getGradebook(GRADEBOOK_UID);
// Set up a holder for enrollments, teaching assignments, and sections.
integrationSupport.createCourse(GRADEBOOK_UID, GRADEBOOK_UID, false, false, false);
List studentUidsList = Arrays.asList(new String[] {
"student1",
"student2",
"student3",
});
addUsersEnrollments(gradebook, studentUidsList);
// Add an internal assignment
Long gbId = gradebook.getId();
asn_1Id = gradebookManager.createAssignment(gbId, ASN_1, new Double(10), null, Boolean.FALSE,Boolean.FALSE,Boolean.FALSE);
// Add a score for the internal assignment
List assignments = gradebookManager.getAssignments(gbId);
Assignment asn = null;
for(Iterator iter = assignments.iterator(); iter.hasNext();) {
Assignment tmp = (Assignment)iter.next();
if(tmp.getName().equals(ASN_1)) {
asn = tmp;
break;
}
}
List gradeRecords = new ArrayList();
gradeRecords.add(new AssignmentGradeRecord(asn, "student1", new Double(10)));
gradebookManager.updateAssignmentGradeRecords(asn, gradeRecords);
}
/**
* Tests the gradebook service.
*
* @throws Exception
*/
public void testCreateExternalAssessment() throws Exception {
Assert.assertTrue(gradebookFrameworkService.isGradebookDefined(GRADEBOOK_UID));
// Make sure the service knows that the external id has not been defined
Assert.assertFalse(gradebookExternalAssessmentService.isExternalAssignmentDefined(GRADEBOOK_UID, EXT_ID_1));
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, EXT_ID_1, null, EXT_TITLE_1, new Double(10), new Date(), "Samigo", new Boolean(false));
// Make sure the service knows that the external id has been defined
Assert.assertTrue(gradebookExternalAssessmentService.isExternalAssignmentDefined(GRADEBOOK_UID, EXT_ID_1));
// Make sure that internal name conflicts are detected
try {
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, "A unique external id", null, ASN_1, new Double(10), new Date(), "Samigo", new Boolean(false));
fail();
} catch (ConflictingAssignmentNameException e) {}
// Make sure that external name conflicts are detected
try {
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, "Another unique external id", null, EXT_TITLE_1, new Double(10), new Date(), "Samigo", new Boolean(false));
fail();
} catch (ConflictingAssignmentNameException e) {}
// Make sure that external id conflicts are detected
try {
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, EXT_ID_1, null, "A unique title", new Double(10), new Date(), "Samigo", new Boolean(false));
fail();
} catch (ConflictingExternalIdException e) {}
// Test a floating value.
double floatingPoints = 10.66666;
String floatingExtId = "Just another external ID";
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, floatingExtId, null, "AFractionalAssessment", new Double(floatingPoints), new Date(), "Samigo", new Boolean(false));
// Find the assessment and ensure that it has been updated
Long gbId = gradebookManager.getGradebook(GRADEBOOK_UID).getId();
Assignment asn = null;
List assignments = gradebookManager.getAssignments(gbId);
for(Iterator iter = assignments.iterator(); iter.hasNext();) {
Assignment tmp = (Assignment)iter.next();
if(tmp.getExternalId() != null && tmp.getExternalId().equals(floatingExtId)) {
asn = tmp;
break;
}
}
Assert.assertEquals(asn.getPointsPossible(), new Double(floatingPoints));
}
public void testCreateExternalAssessmentWithCategory() throws Exception {
String categoryName = "My favorite category";
Long gbId = gradebookManager.getGradebook(GRADEBOOK_UID).getId();
Long catId = gradebookManager.createCategory(gbId, categoryName, new Double(0), 0, 0, 0, false);
Assert.assertTrue(gradebookFrameworkService.isGradebookDefined(GRADEBOOK_UID));
// Make sure the service knows that the external id has not been defined
Assert.assertFalse(gradebookExternalAssessmentService.isExternalAssignmentDefined(GRADEBOOK_UID, EXT_ID_1));
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, EXT_ID_1, null, EXT_TITLE_1, new Double(10), new Date(), "Samigo", new Boolean(false), catId);
// Make sure the service knows that the external id has been defined
Assert.assertTrue(gradebookExternalAssessmentService.isExternalAssignmentDefined(GRADEBOOK_UID, EXT_ID_1));
// let's retrieve the assignment and double check the category setting
// due to security in GradebookService, we need to retrieve all assign and then iterate through to find this one
List<Assignment> allAssigns = gradebookManager.getAssignments(gbId);
boolean assignFound = false;
for (Assignment assign : allAssigns) {
if (assign.isExternallyMaintained() && EXT_ID_1.equals(assign.getExternalId())) {
assignFound = true;
// double check the category
if (assign.getCategory() == null || !catId.equals(assign.getCategory().getId())) {
fail("Category was not saved via addExternalAssessment");
}
}
}
if (!assignFound) {
fail("Could not retrieve newly added external assignment");
}
// double check that leaving category null leaves category unassigned
String externalId2 = "external ID 2";
String externalTitle = "Another externally maintained one";
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, externalId2, null, externalTitle, new Double(10), new Date(), "Samigo", new Boolean(false), null);
// Make sure the service knows that the external id has been defined
Assert.assertTrue(gradebookExternalAssessmentService.isExternalAssignmentDefined(GRADEBOOK_UID, externalId2));
// let's retrieve the assignment and double check the category setting
// due to security in GradebookService, we need to retrieve all assign and then iterate through to find this one
allAssigns = gradebookManager.getAssignments(gbId);
assignFound = false;
for (Assignment assign : allAssigns) {
if (assign.isExternallyMaintained() && externalId2.equals(assign.getExternalId())) {
assignFound = true;
// double check the category
if (assign.getCategory() != null) {
fail("Category should be null for external assignment added via addExternalAssessment");
}
}
}
if (!assignFound) {
fail("Could not retrieve newly added external assignment without a category");
}
// Make sure that internal name conflicts are detected
try {
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, "A unique external id", null, ASN_1, new Double(10), new Date(), "Samigo", new Boolean(false), catId);
fail();
} catch (ConflictingAssignmentNameException e) {}
// Make sure that external name conflicts are detected
try {
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, "Another unique external id", null, EXT_TITLE_1, new Double(10), new Date(), "Samigo", new Boolean(false), catId);
fail();
} catch (ConflictingAssignmentNameException e) {}
// Make sure that external id conflicts are detected
try {
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, EXT_ID_1, null, "A unique title", new Double(10), new Date(), "Samigo", new Boolean(false), catId);
fail();
} catch (ConflictingExternalIdException e) {}
// Test a floating value.
double floatingPoints = 10.66666;
String floatingExtId = "Just another external ID";
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, floatingExtId, null, "AFractionalAssessment", new Double(floatingPoints), new Date(), "Samigo", new Boolean(false), catId);
// Find the assessment and ensure that it has been updated
Assignment asn = null;
List assignments = gradebookManager.getAssignments(gbId);
for(Iterator iter = assignments.iterator(); iter.hasNext();) {
Assignment tmp = (Assignment)iter.next();
if(tmp.getExternalId() != null && tmp.getExternalId().equals(floatingExtId)) {
asn = tmp;
break;
}
}
Assert.assertEquals(asn.getPointsPossible(), new Double(floatingPoints));
}
public void testModifyExternalAssessment() throws Exception {
Assert.assertTrue(gradebookFrameworkService.isGradebookDefined(GRADEBOOK_UID));
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, EXT_ID_1, null, EXT_TITLE_1, new Double(10), new Date(), "Samigo", new Boolean(false));
gradebookExternalAssessmentService.updateExternalAssessment(GRADEBOOK_UID, EXT_ID_1, null, EXT_TITLE_1, new Double(20), null, new Boolean(false));
// Find the assessment and ensure that it has been updated
Long gbId = gradebookManager.getGradebook(GRADEBOOK_UID).getId();
Assignment asn = null;
List assignments = gradebookManager.getAssignments(gbId);
for(Iterator iter = assignments.iterator(); iter.hasNext();) {
Assignment tmp = (Assignment)iter.next();
if(tmp.getExternalId() != null && tmp.getExternalId().equals(EXT_ID_1)) {
asn = tmp;
break;
}
}
Assert.assertEquals(asn.getPointsPossible(), new Double(20));
// Ensure that the total points possible in the gradebook reflects the updated assessment's points
Assert.assertTrue(gradebookManager.getTotalPoints(gbId) == 30);
}
public void testCreateExternalGradeRecords() throws Exception {
// Add an external assessment
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, EXT_ID_1, null, EXT_TITLE_1, new Double(10), new Date(), "Samigo", new Boolean(false));
// Add the external assessment score
Gradebook gb = gradebookManager.getGradebook(GRADEBOOK_UID);
gradebookExternalAssessmentService.updateExternalAssessmentScore(gb.getUid(), EXT_ID_1, "student1", new String("5"));
// Ensure that the course grade record for student1 has been updated
CourseGradeRecord cgr = gradebookManager.getStudentCourseGradeRecord(gb, "student1");
Assert.assertTrue(cgr.getPointsEarned().equals(new Double(15))); // 10 points on internal, 5 points on external
}
public void testModifyExternalGradeRecords() throws Exception {
// Add an external assessment
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, EXT_ID_1, null, EXT_TITLE_1, new Double(10), new Date(), "Samigo", new Boolean(false));
// Add the external assessment score
Gradebook gb = gradebookManager.getGradebook(GRADEBOOK_UID);
gradebookExternalAssessmentService.updateExternalAssessmentScore(gb.getUid(), EXT_ID_1, "student1", new String("2"));
// Ensure that the course grade record for student1 has been updated
CourseGradeRecord cgr = gradebookManager.getStudentCourseGradeRecord(gb, "student1");
Assert.assertTrue(cgr.getPointsEarned().equals(new Double(12))); // 10 points on internal, 2 points on external
// Update the score with null points
gradebookExternalAssessmentService.updateExternalAssessmentScore(gb.getUid(), EXT_ID_1, "student1", null);
// Ensure that the course grade record for student1 has been updated
cgr = gradebookManager.getStudentCourseGradeRecord(gb, "student1");
Assert.assertEquals(new Double(10), cgr.getPointsEarned()); // 10 points on internal, 0 points on external
}
public void testUpdateMultipleScores() throws Exception {
// Add an external assessment
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, EXT_ID_1, null, EXT_TITLE_1, new Double(10), new Date(), "Samigo", new Boolean(false));
// Add the external assessment score
Gradebook gb = gradebookManager.getGradebook(GRADEBOOK_UID);
gradebookExternalAssessmentService.updateExternalAssessmentScore(gb.getUid(), EXT_ID_1, "student1", new String("2"));
// Ensure that the course grade record for student1 has been updated
CourseGradeRecord cgr = gradebookManager.getStudentCourseGradeRecord(gb, "student1");
Assert.assertTrue(cgr.getPointsEarned().equals(new Double(12))); // 10 points on internal, 2 points on external
// Update multiple scores at once.
Map studentUidsToScores = new HashMap();
studentUidsToScores.put("student1", null);
studentUidsToScores.put("student2", new Double(4).toString());
studentUidsToScores.put("student3", new Double(5).toString());
gradebookExternalAssessmentService.updateExternalAssessmentScoresString(gb.getUid(), EXT_ID_1, studentUidsToScores);
cgr = gradebookManager.getStudentCourseGradeRecord(gb, "student1");
Assert.assertTrue(cgr.getPointsEarned().equals(new Double(10)));
cgr = gradebookManager.getStudentCourseGradeRecord(gb, "student2");
Assert.assertTrue(cgr.getPointsEarned().equals(new Double(4)));
// Do a bogus update of a null collection of scores, a la Assignments.
gradebookExternalAssessmentService.updateExternalAssessmentScoresString(gb.getUid(), EXT_ID_1, new HashMap());
cgr = gradebookManager.getStudentCourseGradeRecord(gb, "student2");
Assert.assertTrue(cgr.getPointsEarned().equals(new Double(4)));
}
public void testRemoveExternalAssignment() throws Exception {
Gradebook gb = gradebookManager.getGradebook(GRADEBOOK_UID);
// Grade a second student on the internal assignment to test
// course grade calculations later.
Assignment asn = gradebookManager.getAssignmentWithStats(asn_1Id);
List gradeRecords = new ArrayList();
gradeRecords.add(new AssignmentGradeRecord(asn, "student2", new Double(10)));
gradebookManager.updateAssignmentGradeRecords(asn, gradeRecords);
// Add an external assessment
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, EXT_ID_1, null, EXT_TITLE_1, new Double(10), new Date(), "Samigo", new Boolean(false));
// Add the external assessment score
gradebookExternalAssessmentService.updateExternalAssessmentScore(GRADEBOOK_UID, EXT_ID_1, "student1", new String("5"));
CourseGradeRecord cgr = gradebookManager.getStudentCourseGradeRecord(gb, "student1");
Assert.assertTrue(cgr.getPointsEarned().equals(new Double(15)));// 10 points on internal, 10 points on external
// Check the display grade (which is what the students would see).
if (log.isDebugEnabled()) log.debug("student1 cgr displayGrade=" + cgr.getDisplayGrade());
Assert.assertTrue(cgr.getDisplayGrade().equals("C"));
cgr = gradebookManager.getStudentCourseGradeRecord(gb, "student2");
if (log.isDebugEnabled()) log.debug("student2 cgr displayGrade=" + cgr.getDisplayGrade());
//comment it out because of new calculation method
// Assert.assertTrue(cgr.getDisplayGrade().equals("F"));
// Remove the external assessment
gradebookExternalAssessmentService.removeExternalAssessment(GRADEBOOK_UID, EXT_ID_1);
// Ensure that the course grade record for student1 has been updated
cgr = gradebookManager.getStudentCourseGradeRecord(gb, "student1");
Assert.assertTrue(cgr.getPointsEarned().equals(new Double(10)));// 10 points on internal, 0 points on external
// Check the display grade (which is what the students would see).
if (log.isDebugEnabled()) log.debug("student1 cgr displayGrade=" + cgr.getDisplayGrade());
Assert.assertTrue(cgr.getDisplayGrade().equals("A+"));
cgr = gradebookManager.getStudentCourseGradeRecord(gb, "student2");
if (log.isDebugEnabled()) log.debug("student2 cgr displayGrade=" + cgr.getDisplayGrade());
Assert.assertTrue(cgr.getDisplayGrade().equals("A+"));
// Try to add another external assessment with the same external ID as the recently deleted external assessment
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, EXT_ID_1, null, "some other unique title", new Double(10), new Date(), "Samigo", new Boolean(false));
}
public void testDeleteGradebook() throws Exception {
gradebookFrameworkService.deleteGradebook(GRADEBOOK_UID);
Assert.assertFalse(gradebookFrameworkService.isGradebookDefined(GRADEBOOK_UID));
}
public void testIsAssignmentDefined() throws Exception {
String assignmentTitle = "Is Assignment Defined Quiz";
Assert.assertFalse(gradebookExternalAssessmentService.isAssignmentDefined(GRADEBOOK_UID, assignmentTitle));
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, "Is Assignment Defined ID", null, assignmentTitle, new Double(10), new Date(), "Assignments", new Boolean(false));
Assert.assertTrue(gradebookExternalAssessmentService.isAssignmentDefined(GRADEBOOK_UID, assignmentTitle));
// Now test conflicts with an internally defined assignment.
Assert.assertTrue(gradebookExternalAssessmentService.isAssignmentDefined(GRADEBOOK_UID, ASN_1));
gradebookManager.removeAssignment(asn_1Id);
Assert.assertFalse(gradebookExternalAssessmentService.isAssignmentDefined(GRADEBOOK_UID, ASN_1));
}
public void testExternalAssignmentWithZeroPoints() throws Exception {
//add assignment to grade book
try{
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, EXT_ID_1, null, EXT_TITLE_1, new Double(0), new Date(), "Samigo", new Boolean(false));
fail();
}catch(AssignmentHasIllegalPointsException e){}
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, EXT_ID_1, null, EXT_TITLE_1, new Double(10), new Date(), "Samigo", new Boolean(false));
try{
gradebookExternalAssessmentService.updateExternalAssessment(GRADEBOOK_UID, EXT_ID_1, null, EXT_TITLE_1, new Double(0), null, new Boolean(false));
fail();
} catch(AssignmentHasIllegalPointsException e) {}
}
public void testDuplicateExternalIds() throws Exception {
// Add an external assessment
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, EXT_ID_1, null, EXT_TITLE_1, new Double(10), new Date(), "Samigo", new Boolean(false));
// Try to add another external assessment with a duplicate external ID
try {
gradebookExternalAssessmentService.addExternalAssessment(GRADEBOOK_UID, EXT_ID_1, null, "some unique title", new Double(10), new Date(), "Samigo", new Boolean(false));
fail();
} catch (ConflictingExternalIdException e) {}
}
}