001package edu.pdx.cs.joy.grader; 002 003import com.google.common.io.CharStreams; 004import edu.pdx.cs.joy.grader.gradebook.*; 005import org.junit.jupiter.api.Test; 006import org.junit.jupiter.api.io.TempDir; 007 008import java.io.*; 009import java.time.LocalDateTime; 010import java.util.Arrays; 011import java.util.stream.Collectors; 012 013import static org.hamcrest.MatcherAssert.assertThat; 014import static org.hamcrest.Matchers.*; 015 016public class SummaryReportTest { 017 018 @Test 019 public void ungradedAssignmentsDoNotCountTowardsGraded() { 020 GradeBook gradeBook = new GradeBook("test"); 021 Student student = new Student("student"); 022 gradeBook.addStudent(student); 023 Assignment assignment = new Assignment("assignment", 4.0); 024 gradeBook.addAssignment(assignment); 025 026 Grade grade = new Grade(assignment, Grade.NO_GRADE); 027 student.setGrade(assignment.getName(), grade); 028 029 assertThat(SummaryReport.noStudentHasGradeFor(assignment, gradeBook), equalTo(true)); 030 031 } 032 033 @Test 034 public void reportsAreGeneratedInCorrectDirectories(@TempDir File tempDirectory) throws IOException { 035 GradeBook gradeBook = new GradeBook("test"); 036 Assignment assignment = new Assignment("assignment", 4.0); 037 gradeBook.addAssignment(assignment); 038 039 double undergradScore = 3.0; 040 Student undergrad = addStudentInSectionWithScore(gradeBook, assignment, "undergrad", Student.Section.UNDERGRADUATE, undergradScore); 041 042 double gradScore = 3.5; 043 Student grad = addStudentInSectionWithScore(gradeBook, assignment, "grad", Student.Section.GRADUATE, gradScore); 044 045 SummaryReport.dumpReports(gradeBook.getStudentIds(), gradeBook, tempDirectory, false); 046 047 assertThatStudentHasReportInDirectoryWithScore(undergrad, tempDirectory, SummaryReport.UNDERGRADUATE_DIRECTORY_NAME, undergradScore); 048 assertThatStudentHasReportInDirectoryWithScore(grad, tempDirectory, SummaryReport.GRADUATE_DIRECTORY_NAME, gradScore); 049 } 050 051 private Student addStudentInSectionWithScore(GradeBook gradeBook, Assignment assignment, String studentId, Student.Section enrolledSection, double undergradScore) { 052 Student undergrad = new Student(studentId); 053 undergrad.setEnrolledSection(enrolledSection); 054 gradeBook.addStudent(undergrad); 055 undergrad.setGrade(assignment, undergradScore); 056 return undergrad; 057 } 058 059 private void assertThatStudentHasReportInDirectoryWithScore(Student student, File tempDirectory, String dirFileName, double studentScore) throws IOException { 060 File directory = new File(tempDirectory, dirFileName); 061 assertThat(directory.exists(), equalTo(true)); 062 063 File reportFile = new File(directory, SummaryReport.getReportFileName(student.getId())); 064 assertThat(reportFile.exists(), equalTo(true)); 065 066 String reportContents = readTextFromFile(reportFile); 067 assertThat(reportContents, containsString(String.valueOf(studentScore))); 068 } 069 070 private String readTextFromFile(File file) throws IOException { 071 StringWriter writer = new StringWriter(); 072 CharStreams.copy(new FileReader(file), writer); 073 return writer.getBuffer().toString(); 074 } 075 076 @Test 077 public void totalsArePrintedForAllStudents() { 078 GradeBook gradeBook = new GradeBook("test"); 079 Assignment assignment = new Assignment("assignment", 4.0); 080 gradeBook.addAssignment(assignment); 081 082 String worseUndergradStudentName = "worseUndergrad"; 083 addStudentInSectionWithScore(gradeBook, assignment, worseUndergradStudentName, Student.Section.UNDERGRADUATE, 3.0); 084 085 String betterUndergradStudentName = "betterUndergrad"; 086 addStudentInSectionWithScore(gradeBook, assignment, betterUndergradStudentName, Student.Section.UNDERGRADUATE, 3.5); 087 088 String worseGradStudentName = "worseGrad"; 089 addStudentInSectionWithScore(gradeBook, assignment, worseGradStudentName, Student.Section.GRADUATE, 3.0); 090 091 String betterGradStudentName = "betterGrad"; 092 addStudentInSectionWithScore(gradeBook, assignment, betterGradStudentName, Student.Section.GRADUATE, 3.5); 093 094 calculateTotalGradesForStudents(gradeBook, false); 095 096 CapturingPrintWriter out = new CapturingPrintWriter(); 097 SummaryReport.printOutStudentTotals(gradeBook.studentsStream().collect(Collectors.toSet()), out); 098 099 String written = out.getTextWrittenToWriter(); 100 String[] strings = { betterUndergradStudentName, worseUndergradStudentName, betterGradStudentName, worseGradStudentName }; 101 assertThat(written, stringContainsInOrder(Arrays.asList(strings))); 102 } 103 104 private void calculateTotalGradesForStudents(GradeBook gradeBook, boolean assignLetterGrades) { 105 PrintWriter pw = new PrintWriter(new Writer() { 106 @Override 107 public void write(char[] cbuf, int off, int len) { 108 109 } 110 111 @Override 112 public void flush() { 113 114 } 115 116 @Override 117 public void close() { 118 119 } 120 }); 121 122 gradeBook.studentsStream().forEach(student -> SummaryReport.dumpReportTo(gradeBook, student, pw, assignLetterGrades)); 123 } 124 125 private static class CapturingPrintWriter extends PrintWriter { 126 public CapturingPrintWriter() { 127 super(new StringWriter()); 128 } 129 130 public String getTextWrittenToWriter() { 131 return ((StringWriter) this.out).getBuffer().toString(); 132 } 133 } 134 135 @Test 136 public void assignLetterGradesAccordingToGradeBookRangesForSection() { 137 GradeBook gradeBook = new GradeBook("test"); 138 Assignment assignment = new Assignment("assignment", 10.0); 139 gradeBook.addAssignment(assignment); 140 141 GradeBook.LetterGradeRanges undergradLetterGradeRanges = gradeBook.getLetterGradeRanges(Student.Section.UNDERGRADUATE); 142 undergradLetterGradeRanges.getRange(LetterGrade.A).setRange(95, 100); 143 undergradLetterGradeRanges.getRange(LetterGrade.A_MINUS).setRange(90, 94); 144 undergradLetterGradeRanges.validate(); 145 146 GradeBook.LetterGradeRanges gradLetterGradeRanges = gradeBook.getLetterGradeRanges(Student.Section.GRADUATE); 147 gradLetterGradeRanges.getRange(LetterGrade.A).setRange(92, 100); 148 gradLetterGradeRanges.getRange(LetterGrade.A_MINUS).setRange(90, 91); 149 gradLetterGradeRanges.validate(); 150 151 String betterUndergradStudentName = "betterUndergrad"; 152 Student betterUndergrad = addStudentInSectionWithScore(gradeBook, assignment, betterUndergradStudentName, Student.Section.UNDERGRADUATE, 9.7); 153 assertThat(betterUndergrad.getLetterGrade(), nullValue()); 154 155 String worseUndergradStudentName = "worseUndergrad"; 156 Student worseUndergrad = addStudentInSectionWithScore(gradeBook, assignment, worseUndergradStudentName, Student.Section.UNDERGRADUATE, 9.2); 157 assertThat(worseUndergrad.getLetterGrade(), nullValue()); 158 159 String gradStudentName = "grad"; 160 Student grad = addStudentInSectionWithScore(gradeBook, assignment, gradStudentName, Student.Section.GRADUATE, 9.2); 161 assertThat(grad.getLetterGrade(), nullValue()); 162 163 calculateTotalGradesForStudents(gradeBook, true); 164 165 assertThat(betterUndergrad.getLetterGrade(), equalTo(LetterGrade.A)); 166 assertThat(worseUndergrad.getLetterGrade(), equalTo(LetterGrade.A_MINUS)); 167 assertThat(grad.getLetterGrade(), equalTo(LetterGrade.A)); 168 } 169 170 @Test 171 public void assignmentDueInThePastIsLate() { 172 Assignment assignment = new Assignment("Test", 4.0); 173 LocalDateTime dueDate = LocalDateTime.now().minusDays(3); 174 assignment.setDueDate(dueDate); 175 176 assertThat(SummaryReport.dueDateHasPassed(assignment), equalTo(true)); 177 } 178 179 @Test 180 public void assignmentDueInTheFutureIsNotLate() { 181 Assignment assignment = new Assignment("Test", 4.0); 182 LocalDateTime dueDate = LocalDateTime.now().plusDays(3); 183 assignment.setDueDate(dueDate); 184 185 assertThat(SummaryReport.dueDateHasPassed(assignment), equalTo(false)); 186 } 187 188 @Test 189 void assignmentWithAllZeroGradesDoesNotAppearInReport(@TempDir File tempDirectory) throws IOException { 190 GradeBook gradeBook = new GradeBook("test"); 191 String someNonZeroGradesName = "someNonZeroGrades"; 192 String allZeroGradesName = "allZeroGrades"; 193 194 Assignment someNonZeroGrades = gradeBook.addAssignment(new Assignment(someNonZeroGradesName, 10.0)); 195 Assignment allZeroGrades = gradeBook.addAssignment(new Assignment(allZeroGradesName, 10.0)); 196 197 Student studentWithSomeNonZeroGrades = 198 gradeBook.addStudent(new Student("studentWithSomeNonZeroGrades")) 199 .setLastName("studentWithSomeNonZeroGrades") 200 .setEnrolledSection(Student.Section.UNDERGRADUATE) 201 .setGrade(someNonZeroGrades, 5.0) 202 .setGrade(allZeroGrades, 0.0); 203 204 Student studentWithAllZeroGrades = 205 gradeBook.addStudent(new Student("studentWithAllZeroGrades")) 206 .setLastName("studentWithAllZeroGrades") 207 .setEnrolledSection(Student.Section.UNDERGRADUATE) 208 .setGrade(someNonZeroGrades, 0.0) 209 .setGrade(allZeroGrades, 0.0); 210 211 assertThat(SummaryReport.noStudentHasGradeFor(allZeroGrades, gradeBook), equalTo(true)); 212 213 SummaryReport.dumpReports(gradeBook.getStudentIds(), gradeBook, tempDirectory, false); 214 215 File studentWithSomeNonZeroGradesReportFile = getStudentReportFile(tempDirectory, studentWithSomeNonZeroGrades); 216 assertThat(studentWithSomeNonZeroGradesReportFile.exists(), equalTo(true)); 217 218 String studentWithSomeNonZeroGradesReport = readTextFromFile(studentWithSomeNonZeroGradesReportFile); 219 assertThat(studentWithSomeNonZeroGradesReport, containsString(someNonZeroGradesName)); 220 assertThat(studentWithSomeNonZeroGradesReport, not(containsString(allZeroGradesName))); 221 222 File studentWithAllZeroGradesReportFile = getStudentReportFile(tempDirectory, studentWithAllZeroGrades); 223 assertThat(studentWithAllZeroGradesReportFile.exists(), equalTo(true)); 224 225 String studentWithAllZeroGradesReport = readTextFromFile(studentWithAllZeroGradesReportFile); 226 assertThat(studentWithAllZeroGradesReport, containsString(someNonZeroGradesName)); 227 assertThat(studentWithAllZeroGradesReport, not(containsString(allZeroGradesName))); 228 229 } 230 231 private static File getStudentReportFile(File directory, Student student) { 232 String sectionDirName; 233 switch (student.getEnrolledSection()) { 234 case GRADUATE: 235 sectionDirName = SummaryReport.GRADUATE_DIRECTORY_NAME; 236 break; 237 case UNDERGRADUATE: 238 sectionDirName = SummaryReport.UNDERGRADUATE_DIRECTORY_NAME; 239 break; 240 default: 241 throw new UnsupportedOperationException("Don't know how to handle section: " + student.getEnrolledSection()); 242 } 243 244 File sectionDirectory = new File(directory, sectionDirName); 245 return new File(sectionDirectory, SummaryReport.getReportFileName(student.getId())); 246 } 247 248 @Test 249 void missingGradeIsClearInReport(@TempDir File tempDirectory) throws IOException { 250 GradeBook gradeBook = new GradeBook("test"); 251 252 String assignmentName = "Assignment"; 253 Assignment assignment = gradeBook.addAssignment(new Assignment(assignmentName, 10.0)); 254 Assignment assignment2 = gradeBook.addAssignment(new Assignment("Assignment 2", 10.0)); 255 256 Student studentWithMissingGrade = 257 gradeBook.addStudent(new Student("studentWithMissingGrade")) 258 .setLastName("studentWithMissingGrade") 259 .setEnrolledSection(Student.Section.UNDERGRADUATE) 260 .setGrade(assignment, Grade.NO_GRADE) 261 .setGrade(assignment2, 10.0); 262 263 Student studentWithGrade = 264 gradeBook.addStudent(new Student("studentWithGrade")) 265 .setLastName("studentWithGrade") 266 .setEnrolledSection(Student.Section.UNDERGRADUATE) 267 .setGrade(assignment, 10.0) 268 .setGrade(assignment2, 10.0); 269 270 SummaryReport.dumpReports(gradeBook.getStudentIds(), gradeBook, tempDirectory, false); 271 272 File studentWithMissingGradeReportFile = getStudentReportFile(tempDirectory, studentWithMissingGrade); 273 assertThat(studentWithMissingGradeReportFile.exists(), equalTo(true)); 274 275 String studentWithSomeNonZeroGradesReport = readTextFromFile(studentWithMissingGradeReportFile); 276 assertThat(studentWithSomeNonZeroGradesReport, not(containsString(String.valueOf(Grade.NO_GRADE)))); 277 assertThat(studentWithSomeNonZeroGradesReport, containsString("NOT GRADED")); 278 } 279 280}