001package edu.pdx.cs.joy.grader; 002 003import edu.pdx.cs.joy.grader.gradebook.Assignment; 004import edu.pdx.cs.joy.grader.gradebook.GradeBook; 005import edu.pdx.cs.joy.grader.gradebook.Student; 006import org.junit.jupiter.api.Test; 007import org.mockito.ArgumentCaptor; 008import org.slf4j.Logger; 009import org.slf4j.LoggerFactory; 010 011import java.io.Reader; 012import java.io.StringReader; 013import java.util.regex.Matcher; 014 015import static org.hamcrest.MatcherAssert.assertThat; 016import static org.hamcrest.Matchers.containsString; 017import static org.hamcrest.Matchers.equalTo; 018import static org.junit.jupiter.api.Assertions.assertThrows; 019import static org.mockito.Mockito.*; 020 021public class ProjectGradesImporterTest { 022 023 private Logger logger = LoggerFactory.getLogger(this.getClass().getPackage().getName()); 024 025 @Test 026 public void gradedProjectWithNoGradeThrowsScoreNotFoundException() throws ProjectGradesImporter.ScoreNotFoundException { 027 GradedProject project = new GradedProject(); 028 project.addLine("asdfhjkl"); 029 project.addLine("iadguow"); 030 031 assertThrows(ProjectGradesImporter.ScoreNotFoundException.class, () -> 032 ProjectGradesImporter.getScoreFrom(project.getReader()) 033 ); 034 } 035 036 @Test 037 public void scoreRegularExpressionWorkWithSimpleCase() { 038 Matcher matcher = ProjectGradesImporter.scorePattern.matcher("3.0 out of 4.5"); 039 assertThat(matcher.find(), equalTo(true)); 040 assertThat(matcher.groupCount(), equalTo(2)); 041 assertThat(matcher.group(1), equalTo("3.0")); 042 assertThat(matcher.group(2), equalTo("4.5")); 043 } 044 045 @Test 046 public void gradedProjectWithOutOfHasValidScore() throws ProjectGradesImporter.ScoreNotFoundException { 047 GradedProject project = new GradedProject(); 048 project.addLine("3.4 out of 3.5"); 049 project.addLine("iadguow"); 050 051 ProjectGradesImporter.ProjectScore score = ProjectGradesImporter.getScoreFrom(project.getReader()); 052 assertThat(score.getScore(), equalTo(3.4)); 053 assertThat(score.getTotalPoints(), equalTo(3.5)); 054 } 055 056 @Test 057 public void scoreMatchesRegardlessOfCase() { 058 Matcher matcher = ProjectGradesImporter.scorePattern.matcher("4.0 OUT OF 5.0"); 059 assertThat(matcher.find(), equalTo(true)); 060 assertThat(matcher.groupCount(), equalTo(2)); 061 assertThat(matcher.group(1), equalTo("4.0")); 062 assertThat(matcher.group(2), equalTo("5.0")); 063 } 064 065 @Test 066 public void scoreMatchesIntegerPoints() { 067 Matcher matcher = ProjectGradesImporter.scorePattern.matcher("4 out of 5"); 068 assertThat(matcher.find(), equalTo(true)); 069 assertThat(matcher.groupCount(), equalTo(2)); 070 assertThat(matcher.group(1), equalTo("4")); 071 assertThat(matcher.group(2), equalTo("5")); 072 } 073 074 @Test 075 public void scoreMatchesInTheMiddleOfOtherText() { 076 Matcher matcher = ProjectGradesImporter.scorePattern.matcher("You got 4 out of 5 points"); 077 assertThat(matcher.find(), equalTo(true)); 078 assertThat(matcher.groupCount(), equalTo(2)); 079 assertThat(matcher.group(1), equalTo("4")); 080 assertThat(matcher.group(2), equalTo("5")); 081 } 082 083 @Test 084 public void gradedProjectWithIntegerPoints() throws ProjectGradesImporter.ScoreNotFoundException { 085 GradedProject project = new GradedProject(); 086 project.addLine("3 out of 5"); 087 project.addLine("iadguow"); 088 089 ProjectGradesImporter.ProjectScore score = ProjectGradesImporter.getScoreFrom(project.getReader()); 090 assertThat(score.getScore(), equalTo(3.0)); 091 assertThat(score.getTotalPoints(), equalTo(5.0)); 092 } 093 094 private class GradedProject { 095 private StringBuilder sb = new StringBuilder(); 096 097 public void addLine(String line) { 098 sb.append(line); 099 sb.append("\n"); 100 } 101 102 public Reader getReader() { 103 return new StringReader(sb.toString()); 104 } 105 } 106 107 @Test 108 public void onlyFirstScoreIsReturned() throws ProjectGradesImporter.ScoreNotFoundException { 109 GradedProject project = new GradedProject(); 110 project.addLine("3.4 out of 3.5"); 111 project.addLine("iadguow"); 112 project.addLine("3.3 out of 3.4"); 113 114 ProjectGradesImporter.ProjectScore score = ProjectGradesImporter.getScoreFrom(project.getReader()); 115 assertThat(score.getScore(), equalTo(3.4)); 116 assertThat(score.getTotalPoints(), equalTo(3.5)); 117 } 118 119 @Test 120 public void scoreIsRecordedInGradeBook() throws ProjectGradesImporter.ScoreNotFoundException { 121 String studentId = "student"; 122 Assignment assignment = new Assignment("project", 6.0); 123 124 GradeBook gradeBook = new GradeBook("test"); 125 gradeBook.addStudent(new Student(studentId)); 126 gradeBook.addAssignment(assignment); 127 128 String score = "5.8"; 129 GradedProject project = new GradedProject(); 130 project.addLine(score + " out of 6.0"); 131 project.addLine(""); 132 project.addLine("asdfasd"); 133 134 Logger logger = mock(Logger.class); 135 ProjectGradesImporter importer = new ProjectGradesImporter(gradeBook, assignment, logger); 136 importer.recordScoreFromProjectReport(studentId, project.getReader()); 137 138 assertThat(gradeBook.getStudent(studentId).get().getGrade(assignment.getName()).getScore(), equalTo(5.8)); 139 assertThat(gradeBook.isDirty(), equalTo(true)); 140 141 ArgumentCaptor<String> message = ArgumentCaptor.forClass(String.class); 142 verify(logger).info(message.capture()); 143 assertThat(message.getValue(), containsString("Recorded grade of " + score + " for " + studentId)); 144 } 145 146 @Test 147 public void throwIllegalStateExceptionWhenTotalPointsInReportDoesNotMatchGradeBook() throws ProjectGradesImporter.ScoreNotFoundException { 148 String studentId = "student"; 149 Assignment assignment = new Assignment("project", 8.0); 150 151 GradeBook gradeBook = new GradeBook("test"); 152 gradeBook.addStudent(new Student(studentId)); 153 gradeBook.addAssignment(assignment); 154 155 GradedProject project = new GradedProject(); 156 project.addLine("5.8 out of 6.0"); 157 project.addLine(""); 158 project.addLine("asdfasd"); 159 160 ProjectGradesImporter importer = new ProjectGradesImporter(gradeBook, assignment, logger); 161 assertThrows(IllegalStateException.class, () -> 162 importer.recordScoreFromProjectReport(studentId, project.getReader()) 163 ); 164 } 165 166 @Test 167 public void logWarningWhenStudentDoesNotExistInGradeBook() throws ProjectGradesImporter.ScoreNotFoundException { 168 String studentId = "student"; 169 Assignment assignment = new Assignment("project", 6.0); 170 171 GradeBook gradeBook = new GradeBook("test"); 172 gradeBook.addAssignment(assignment); 173 174 GradedProject project = new GradedProject(); 175 project.addLine("5.8 out of 6.0"); 176 project.addLine(""); 177 project.addLine("asdfasd"); 178 179 Logger logger = mock(Logger.class); 180 ProjectGradesImporter importer = new ProjectGradesImporter(gradeBook, assignment, logger); 181 182 importer.recordScoreFromProjectReport(studentId, project.getReader()); 183 184 assertThat(gradeBook.containsStudent(studentId), equalTo(false)); 185 186 ArgumentCaptor<String> message = ArgumentCaptor.forClass(String.class); 187 verify(logger, times(1)).warn(message.capture()); 188 assertThat(message.getValue(), containsString("Student \"" + studentId + "\" not found in gradebook")); 189 } 190 191}