001: /**********************************************************************************
002: *
003: * $Id: GradeMappingTest.java 22246 2007-03-06 23:27:56Z ray@media.berkeley.edu $
004: *
005: ***********************************************************************************
006: *
007: * Copyright (c) 2006 The Regents of the University of California
008: *
009: * Licensed under the Educational Community License Version 1.0 (the "License");
010: * By obtaining, using and/or copying this Original Work, you agree that you have read,
011: * understand, and will comply with the terms and conditions of the Educational Community License.
012: * You may obtain a copy of the License at:
013: *
014: * http://www.opensource.org/licenses/ecl1.php
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
017: * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
018: * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
019: * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
020: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
021: *
022: **********************************************************************************/package org.sakaiproject.tool.gradebook.test;
023:
024: import java.util.ArrayList;
025: import java.util.Arrays;
026: import java.util.Collection;
027: import java.util.Collections;
028: import java.util.Comparator;
029: import java.util.HashSet;
030: import java.util.Iterator;
031: import java.util.List;
032: import java.util.Map;
033: import java.util.Set;
034:
035: import junit.framework.Assert;
036:
037: import org.apache.commons.logging.Log;
038: import org.apache.commons.logging.LogFactory;
039: import org.sakaiproject.service.gradebook.shared.GradingScaleDefinition;
040: import org.sakaiproject.tool.gradebook.CourseGrade;
041: import org.sakaiproject.tool.gradebook.CourseGradeRecord;
042: import org.sakaiproject.tool.gradebook.GradeMapping;
043: import org.sakaiproject.tool.gradebook.Gradebook;
044: import org.sakaiproject.tool.gradebook.GradingScale;
045: import org.sakaiproject.tool.gradebook.LetterGradePlusMinusMapping;
046: import org.sakaiproject.tool.gradebook.test.support.BackwardCompatabilityBusiness;
047:
048: public class GradeMappingTest extends GradebookTestBase {
049: private static Log log = LogFactory.getLog(GradeMappingTest.class);
050:
051: private BackwardCompatabilityBusiness backwardCompatabilityBusiness;
052:
053: protected void onSetUpInTransaction() throws Exception {
054: super .onSetUpInTransaction();
055: backwardCompatabilityBusiness = (BackwardCompatabilityBusiness) applicationContext
056: .getBean("backwardCompatabilityBusiness");
057: }
058:
059: public void testSetGradeMappings() throws Exception {
060: GradeMapping gradeMapping;
061:
062: // By default, we get Letter Grades as a default mapping,
063: // and three possible mappings per gradebook.
064: String gradebook1Name = "SetGradeMappingsTest1";
065: gradebookFrameworkService.addGradebook(gradebook1Name,
066: gradebook1Name);
067: Gradebook gradebook1 = gradebookManager
068: .getGradebook(gradebook1Name);
069: gradeMapping = gradebook1.getSelectedGradeMapping();
070: GradeMapping oldStaticDefault = new LetterGradePlusMinusMapping();
071: Assert.assertTrue(gradeMapping.getName().equals(
072: oldStaticDefault.getName()));
073: Assert.assertTrue(gradebook1.getGradeMappings().size() == 3);
074:
075: // Now make LetterGradeMapping the default.
076: gradebookFrameworkService
077: .setDefaultGradingScale("LetterGradeMapping");
078: String gradebook2Name = "SetGradeMappingsTest2";
079: gradebookFrameworkService.addGradebook(gradebook2Name,
080: gradebook2Name);
081: Gradebook gradebook2 = gradebookManager
082: .getGradebook(gradebook2Name);
083: gradeMapping = gradebook2.getSelectedGradeMapping();
084: GradingScale letterGradingScale = gradeMapping
085: .getGradingScale();
086: Assert.assertTrue(gradeMapping.getName()
087: .equals("Letter Grades"));
088: Assert.assertTrue(gradeMapping.getValue("A").equals(
089: new Double(90)));
090:
091: // Now replace the LetterGradePlusMinusMapping with LoseWinScale...
092: ArrayList newMappings = new ArrayList();
093: GradingScaleDefinition def = new GradingScaleDefinition();
094: def.setUid("LoseWinScale");
095: def.setName("Win, Lose, or Draw");
096: def.setGrades(Arrays.asList(new String[] { "Win", "Draw",
097: "Lose" }));
098: def.setDefaultBottomPercents(Arrays.asList(new Object[] {
099: new Double(80), new Double(40), new Double(0) }));
100: newMappings.add(def);
101:
102: // ... and change the default values of LetterGradeMapping.
103: def = new GradingScaleDefinition();
104: def.setUid(letterGradingScale.getUid());
105: def.setName(letterGradingScale.getName());
106: List gradesList = letterGradingScale.getGrades();
107: def.setGrades(new ArrayList(gradesList));
108: Map bottomPercentsMap = letterGradingScale
109: .getDefaultBottomPercents();
110: List bottomPercentsList = new ArrayList();
111: for (int i = 0; i < gradesList.size(); i++) {
112: String grade = (String) gradesList.get(i);
113: Double bottomPercent = (Double) bottomPercentsMap
114: .get(grade);
115: if (i == 0) {
116: bottomPercent = new Double(89);
117: }
118: bottomPercentsList.add(bottomPercent);
119: }
120: def.setDefaultBottomPercents(bottomPercentsList);
121: newMappings.add(def);
122: gradebookFrameworkService
123: .setAvailableGradingScales(newMappings);
124:
125: // Make sure a new gradebook is as expected.
126: String gradebook3Name = "SetGradeMappingsTest3";
127: gradebookFrameworkService.addGradebook(gradebook3Name,
128: gradebook3Name);
129: Gradebook gradebook3 = gradebookManager
130: .getGradebook(gradebook3Name);
131: gradeMapping = gradebook3.getSelectedGradeMapping();
132: Assert.assertTrue(gradeMapping.getValue("A").equals(
133: new Double(89)));
134: Assert.assertTrue(gradebook3.getGradeMappings().size() == 2);
135: GradeMapping newGradeMapping = null;
136: for (Iterator iter = gradebook3.getGradeMappings().iterator(); iter
137: .hasNext()
138: && (newGradeMapping == null);) {
139: GradeMapping gm = (GradeMapping) iter.next();
140: if (!gm.getId().equals(gradeMapping.getId())) {
141: newGradeMapping = gm;
142: }
143: }
144: gradebook3.setSelectedGradeMapping(newGradeMapping);
145: gradebookManager.updateGradebook(gradebook3);
146: Assert.assertTrue(gradebook3.getSelectedGradeMapping()
147: .getName().equals("Win, Lose, or Draw"));
148:
149: // Make sure the old gradebook doesn't change until we tell it to.
150: gradebook2 = gradebookManager.getGradebook(gradebook2Name);
151: gradeMapping = gradebook2.getSelectedGradeMapping();
152: Assert.assertTrue(gradeMapping.getValue("A").equals(
153: new Double(90)));
154: gradeMapping.setDefaultValues();
155: Assert.assertTrue(gradeMapping.getValue("A").equals(
156: new Double(89)));
157: }
158:
159: public void testBackwardCompatability() throws Exception {
160: String gradebookName = "PreTemplateGB";
161: backwardCompatabilityBusiness.addGradebook(gradebookName,
162: gradebookName);
163: Gradebook gradebook = gradebookManager
164: .getGradebook(gradebookName);
165:
166: // Play the old songs.
167: GradeMapping gradeMapping = gradebook.getSelectedGradeMapping();
168: GradeMapping oldStaticDefault = new LetterGradePlusMinusMapping();
169: Assert.assertTrue(gradeMapping.getName().equals(
170: oldStaticDefault.getName()));
171: Assert.assertTrue(gradebook.getGradeMappings().size() == 3);
172: }
173:
174: public void testBadDefaultGradingScale() throws Exception {
175: List newMappings = new ArrayList();
176: GradingScaleDefinition def = new GradingScaleDefinition();
177: def.setUid("JustOneScale");
178: def.setName("Just One Grading Scale");
179: def.setGrades(Arrays.asList(new String[] { "Win", "Draw",
180: "Lose" }));
181: def.setDefaultBottomPercents(Arrays.asList(new Object[] {
182: new Double(80), new Double(40), new Double(0) }));
183: newMappings.add(def);
184: gradebookFrameworkService
185: .setAvailableGradingScales(newMappings);
186:
187: gradebookFrameworkService
188: .setDefaultGradingScale("NoSuchGradeMapping");
189:
190: String gradebook1Name = "SetGradeMappingsTest1";
191: if (log.isInfoEnabled())
192: log.info("Ignore the upcoming warning about no default...");
193: gradebookFrameworkService.addGradebook(gradebook1Name,
194: gradebook1Name);
195: Gradebook gradebook1 = gradebookManager
196: .getGradebook(gradebook1Name);
197: GradeMapping gradeMapping = gradebook1
198: .getSelectedGradeMapping();
199:
200: // The service should have defaulted the mapping to the only
201: // one available.
202: Assert.assertTrue(gradeMapping.getName().equals(def.getName()));
203: }
204:
205: public void testManualOnlyGrades() throws Exception {
206: String scaleUid = "TheNineties";
207: List<GradingScaleDefinition> newMappings = new ArrayList<GradingScaleDefinition>();
208: GradingScaleDefinition def = new GradingScaleDefinition();
209: def.setUid(scaleUid);
210: def.setName("Nineties Grading");
211: def.setGrades(Arrays.asList(new String[] { "Wicked", "Slacker",
212: "Whatever", "Whoa", "As If" }));
213: def.setDefaultBottomPercents(Arrays.asList(new Object[] {
214: new Double(100), new Double(0), null, "", null }));
215: newMappings.add(def);
216: gradebookFrameworkService
217: .setAvailableGradingScales(newMappings);
218: gradebookFrameworkService.setDefaultGradingScale(scaleUid);
219:
220: String gradebookUid = "ManualGB";
221: gradebookFrameworkService.addGradebook(gradebookUid,
222: gradebookUid);
223: integrationSupport.createCourse(gradebookUid, gradebookUid,
224: false, false, false);
225: Gradebook gradebook = gradebookManager
226: .getGradebook(gradebookUid);
227: GradeMapping gradeMapping = gradebook.getSelectedGradeMapping();
228: Assert.assertTrue(gradeMapping.getName().equals(def.getName()));
229:
230: // Make sure the ordering sticks.
231: Collection<String> grades = gradeMapping.getGrades();
232: int pos = 0;
233: for (String grade : grades) {
234: Assert.assertTrue(grade.equals(def.getGrades().get(pos++)));
235: }
236:
237: // Make sure we get the right bottom grade.
238: String grade = gradeMapping.getGrade(1.0);
239: Assert.assertTrue(grade.equals("Slacker"));
240: grade = gradeMapping.getGrade(0.0);
241: Assert.assertTrue(grade.equals("Slacker"));
242:
243: // To make testing dead-simple, we make student UIDs equal to
244: // the grades we intent to give them.
245: Set<String> students = new HashSet<String>(def.getGrades());
246: addUsersEnrollments(gradebook, students);
247:
248: CourseGrade courseGrade = gradebookManager
249: .getCourseGrade(gradebook.getId());
250: List<CourseGradeRecord> gradeRecords = new ArrayList<CourseGradeRecord>();
251: for (String studentAndGrade : students) {
252: CourseGradeRecord record = new CourseGradeRecord(
253: courseGrade, studentAndGrade);
254: record.setEnteredGrade(studentAndGrade);
255: gradeRecords.add(record);
256: }
257: gradebookManager.updateCourseGradeRecords(courseGrade,
258: gradeRecords);
259:
260: // Make sure we can assign a manual-only grade to a student.
261: CourseGradeRecord gradeRecord = gradebookManager
262: .getStudentCourseGradeRecord(gradebook, "Whoa");
263: Assert.assertTrue(gradeRecord.getDisplayGrade().equals("Whoa"));
264:
265: // Test the sorting of assigned grades. Need to make sure that the manual-only
266: // entered grades keep their positions relative to the bottom of the grading scale.
267: gradeRecords = gradebookManager
268: .getPointsEarnedCourseGradeRecordsWithStats(
269: courseGrade, students);
270:
271: // a) Shuffle the records by sorting them alphabetically.
272: Comparator<CourseGradeRecord> comparator = new Comparator<CourseGradeRecord>() {
273: public int compare(CourseGradeRecord cgr1,
274: CourseGradeRecord cgr2) {
275: return cgr1.getStudentId().compareTo(
276: cgr2.getStudentId());
277: }
278: };
279: Collections.sort(gradeRecords, comparator);
280: Assert.assertTrue(gradeRecords.get(0).getStudentId().equals(
281: "As If"));
282:
283: // b) Now try the "override grade" sort, which should be percentage based except
284: // for the manual-only grades.
285: Collections.sort(gradeRecords, CourseGradeRecord
286: .getOverrideComparator(gradeMapping));
287: Collections.reverse(gradeRecords); // Grading scale is highest to lowest.
288: pos = 0;
289: for (String gradeCode : grades) {
290: Assert.assertTrue(gradeCode.equals(gradeRecords.get(pos++)
291: .getDisplayGrade()));
292: }
293:
294: // Make sure we can't accidentally get a letter grade from a null input.
295: grade = gradeMapping.getGrade(null);
296: Assert.assertTrue(grade == null);
297:
298: // Make sure manual-only grades aren't included in calculating the average course grade,
299: // but that null (calculated) grades are.
300: List<CourseGradeRecord> newGradeRecords = new ArrayList<CourseGradeRecord>();
301: gradeRecord = gradeRecords.remove(0);
302: gradeRecord.setEnteredGrade("Wicked"); // Worth 100%
303: newGradeRecords.add(gradeRecord);
304: gradeRecord = gradeRecords.remove(0);
305: gradeRecord.setEnteredGrade(null); // Worth 0
306: newGradeRecords.add(gradeRecord);
307: for (CourseGradeRecord record : gradeRecords) {
308: record.setEnteredGrade("Whatever"); // Manual-only
309: newGradeRecords.add(record);
310: }
311: gradebookManager.updateCourseGradeRecords(courseGrade,
312: newGradeRecords);
313: gradebookManager.getPointsEarnedCourseGradeRecordsWithStats(
314: courseGrade, students);
315: Assert.assertTrue(courseGrade.getMean() == 50.0);
316: }
317:
318: public void testResetDefaultGradeScale() throws Exception {
319: // Because the default grading scale is set via a Java property rather than through
320: // the database, the last value set by these tests will hang around polluting the JVM.
321: // Do a little cleanup before leaving.
322: gradebookFrameworkService
323: .setDefaultGradingScale("LetterGradePlusMinusMapping");
324: }
325:
326: }
|