Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Development: Improve metrics integration test coverage #9306

Merged
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
9dfef93
+Enabled shouldReturnAverageScores() test
raffifasaro Sep 5, 2024
520571d
+shouldReturnCategories() test
raffifasaro Sep 10, 2024
78c0daa
Merge remote-tracking branch 'origin/develop' into chore/learning-ana…
raffifasaro Sep 11, 2024
5ab6ddf
+ shouldReturnTeamId() test
raffifasaro Sep 11, 2024
487e291
Merge remote-tracking branch 'origin/develop' into chore/learning-ana…
raffifasaro Sep 12, 2024
1c48a08
Merge fix
raffifasaro Sep 12, 2024
dfb6b15
Score test fix
raffifasaro Sep 12, 2024
88eb745
Some fixes
raffifasaro Sep 13, 2024
7c46d4f
Merge branch 'develop' into chore/learning-analytics/improve-metrics-…
raffifasaro Sep 13, 2024
387a22b
fix Score test
raffifasaro Sep 14, 2024
e31e5fb
fix Completed Test
raffifasaro Sep 14, 2024
31d97f1
fix AverageScore Test
raffifasaro Sep 14, 2024
8d140de
remove CourseUtilService changes
raffifasaro Sep 14, 2024
19b5f9f
Fixed CompetencyInformation test
raffifasaro Sep 14, 2024
5484e11
Merge branch 'develop' into chore/learning-analytics/improve-metrics-…
raffifasaro Sep 15, 2024
b6932b6
Added ExerciseTestRepository
raffifasaro Sep 16, 2024
557ba36
code improvements
raffifasaro Sep 16, 2024
8efbfd0
code review fixes
raffifasaro Sep 17, 2024
a800f5c
Merge branch 'develop' into chore/learning-analytics/improve-metrics-…
raffifasaro Sep 17, 2024
91f5e94
Merge remote-tracking branch 'origin/develop' into chore/learning-ana…
raffifasaro Sep 20, 2024
ae410d7
Merge branch 'develop' into chore/learning-analytics/improve-metrics-…
raffifasaro Sep 20, 2024
8097510
Merge branch 'develop' into chore/learning-analytics/improve-metrics-…
raffifasaro Sep 22, 2024
db4dec4
Merge branch 'develop' into chore/learning-analytics/improve-metrics-…
raffifasaro Sep 27, 2024
67404e3
Merge branch 'develop' into chore/learning-analytics/improve-metrics-…
raffifasaro Sep 28, 2024
435ea12
Merge remote-tracking branch 'origin/develop' into chore/learning-ana…
raffifasaro Sep 30, 2024
f0da21e
resolve merge conflicts
raffifasaro Sep 30, 2024
d51b4b7
Apply suggestions from code review
raffifasaro Oct 1, 2024
272b155
fix israted error
raffifasaro Oct 1, 2024
a050d9a
Apply suggestions from code review
raffifasaro Oct 1, 2024
45f39d4
change fixes
raffifasaro Oct 1, 2024
921483e
Merge branch 'develop' into chore/learning-analytics/improve-metrics-…
raffifasaro Oct 1, 2024
663c231
Merge branch 'develop' into chore/learning-analytics/improve-metrics-…
MaximilianAnzinger Oct 4, 2024
28850fb
replace exercise repository by test repository in tests
MaximilianAnzinger Oct 4, 2024
136d987
Merge branch 'develop' into chore/learning-analytics/improve-metrics-…
raffifasaro Oct 5, 2024
3e848fa
Merge branch 'develop' into chore/learning-analytics/improve-metrics-…
raffifasaro Oct 7, 2024
46597a7
requested change fix
raffifasaro Oct 7, 2024
bc729ea
Merge branch 'develop' into chore/learning-analytics/improve-metrics-…
raffifasaro Oct 8, 2024
61bd9e7
Merge branch 'develop' into chore/learning-analytics/improve-metrics-…
raffifasaro Oct 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ jacocoTestCoverageVerification {
counter = "CLASS"
value = "MISSEDCOUNT"
// TODO: in the future the following value should become less than 10
maximum = 40
maximum = 39
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,9 @@ AND EXISTS (
""")
Set<String> findAllCategoryNames(@Param("courseId") Long courseId);

@EntityGraph(attributePaths = "categories")
List<Exercise> findAllWithCategoriesByCourseId(Long courseId);
raffifasaro marked this conversation as resolved.
Show resolved Hide resolved

@Query("""
SELECT DISTINCT e
FROM Exercise e
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import de.tum.cit.aet.artemis.exercise.ExerciseUtilService;
import de.tum.cit.aet.artemis.exercise.programming.MockDelegate;
import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository;
import de.tum.cit.aet.artemis.exercise.service.LearningMetricsService;
import de.tum.cit.aet.artemis.lti.service.Lti13Service;
import de.tum.cit.aet.artemis.modeling.service.ModelingSubmissionService;
import de.tum.cit.aet.artemis.programming.domain.VcsRepositoryUri;
Expand Down Expand Up @@ -164,6 +165,9 @@ public abstract class AbstractArtemisIntegrationTest implements MockDelegate {
@SpyBean
protected CompetencyProgressService competencyProgressService;

@SpyBean
protected LearningMetricsService learningMetricsService;

@Autowired
protected RequestUtilService request;

Expand Down
114 changes: 110 additions & 4 deletions src/test/java/de/tum/cit/aet/artemis/MetricsIntegrationTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package de.tum.cit.aet.artemis;

import static de.tum.cit.aet.artemis.core.config.Constants.MIN_SCORE_GREEN;
import static de.tum.cit.aet.artemis.core.util.TimeUtil.toRelativeTime;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
Expand All @@ -26,11 +27,14 @@
import de.tum.cit.aet.artemis.assessment.service.ParticipantScoreScheduleService;
import de.tum.cit.aet.artemis.atlas.dto.metrics.ResourceTimestampDTO;
import de.tum.cit.aet.artemis.atlas.dto.metrics.StudentMetricsDTO;
import de.tum.cit.aet.artemis.atlas.repository.CompetencyMetricsRepository;
import de.tum.cit.aet.artemis.core.domain.Course;
import de.tum.cit.aet.artemis.exercise.domain.Exercise;
import de.tum.cit.aet.artemis.exercise.domain.Submission;
import de.tum.cit.aet.artemis.exercise.dto.ExerciseInformationDTO;
import de.tum.cit.aet.artemis.exercise.repository.ExerciseMetricsRepository;
import de.tum.cit.aet.artemis.lecture.repository.LectureUnitMetricsRepository;
import de.tum.cit.aet.artemis.team.TeamFactory;

class MetricsIntegrationTest extends AbstractSpringIntegrationIndependentTest {

Expand All @@ -39,25 +43,41 @@
@Autowired
private ExerciseMetricsRepository exerciseMetricsRepository;

@Autowired
private CompetencyMetricsRepository competencyMetricsRepository;

@Autowired
private LectureUnitMetricsRepository lectureUnitMetricsRepository;

private Course course;

private Course courseWithTestRuns;

private Course courseWithCompetencies;

private long userID;

private static final String STUDENT_OF_COURSE = TEST_PREFIX + "student1";

@BeforeEach
void setupTestScenario() {
void setupTestScenario() throws Exception {
// Prevents the ParticipantScoreScheduleService from scheduling tasks related to prior results
ReflectionTestUtils.setField(participantScoreScheduleService, "lastScheduledRun", Optional.of(Instant.now()));
ParticipantScoreScheduleService.DEFAULT_WAITING_TIME_FOR_SCHEDULED_TASKS = 100;
participantScoreScheduleService.activate();

userUtilService.addUsers(TEST_PREFIX, 3, 1, 1, 1);

course = courseUtilService.createCourseWithAllExerciseTypesAndParticipationsAndSubmissionsAndResults(TEST_PREFIX, true);
course = courseUtilService.createCourseWithAllExerciseTypesAndParticipationsAndSubmissionsAndResultsAndScores(TEST_PREFIX, true);
courseWithTestRuns = courseUtilService.createCourseWithAllExerciseTypesAndParticipationsAndSubmissionsAndResultsAndTestRunsAndTwoUsers(TEST_PREFIX, true);
courseWithCompetencies = courseUtilService.createCoursesWithExercisesAndLecturesAndLectureUnitsAndCompetencies(TEST_PREFIX, true, true, 1).getFirst();

userUtilService.createAndSaveUser(TEST_PREFIX + "user1337");
userID = userUtilService.getUserByLogin(TEST_PREFIX + "student1").getId();

// course.getExercises().forEach(exercise -> studentScoreUtilService.createStudentScore(exercise, userUtilService.getUserByLogin(STUDENT_OF_COURSE), 0.5));
course.getExercises().forEach(
exercise -> exercise.setTeams(Set.of(TeamFactory.generateTeamForExercise(exercise, "testTeam", "test", 3, userUtilService.getUserByLogin(STUDENT_OF_COURSE)))));
}

@AfterEach
Expand Down Expand Up @@ -93,7 +113,20 @@
assertThat(exerciseInformation).allSatisfy((id, dto) -> assertThat(id).isEqualTo(dto.id()));
}

@Disabled // TODO: reduce jacoco missing by one after enabled
@Test
@WithMockUser(username = STUDENT_OF_COURSE, roles = "USER")
void shouldReturnCategories() throws Exception {
final var result = request.get("/api/metrics/course/" + course.getId() + "/student", HttpStatus.OK, StudentMetricsDTO.class);
assertThat(result).isNotNull();
raffifasaro marked this conversation as resolved.
Show resolved Hide resolved
assertThat(result.exerciseMetrics()).isNotNull();
final var categories = result.exerciseMetrics().categories();

final var expectedCategories = exerciseRepository.findAllWithCategoriesByCourseId(course.getId()).stream()
.collect(Collectors.toMap(Exercise::getId, Exercise::getCategories));

assertThat(categories).isEqualTo(expectedCategories);
}

@Test
@WithMockUser(username = STUDENT_OF_COURSE, roles = "USER")
void shouldReturnAverageScores() throws Exception {
Expand All @@ -111,9 +144,24 @@
final var expectedMap = exercises.stream().map(Exercise::getId).collect(
Collectors.toMap(Function.identity(), id -> resultRepository.findAllByParticipationExerciseId(id).stream().mapToDouble(Result::getScore).average().orElse(0)));

assertThat(averageScores).isEqualTo(expectedMap);

Check failure on line 147 in src/test/java/de/tum/cit/aet/artemis/MetricsIntegrationTest.java

View workflow job for this annotation

GitHub Actions / H2 Tests

de.tum.cit.aet.artemis.MetricsIntegrationTest$ExerciseMetrics ► shouldReturnAverageScores()

Failed test found in: build/test-results/test/TEST-de.tum.cit.aet.artemis.MetricsIntegrationTest$ExerciseMetrics.xml Error: org.opentest4j.AssertionFailedError:
Raw output
org.opentest4j.AssertionFailedError: 
expected: {140L=10.0, 141L=12.0, 142L=0.0, 143L=20.0, 144L=0.0}
 but was: null
	at app//de.tum.cit.aet.artemis.MetricsIntegrationTest$ExerciseMetrics.shouldReturnAverageScores(MetricsIntegrationTest.java:147)
	at java.base@21.0.4/java.lang.reflect.Method.invoke(Method.java:580)
	at java.base@21.0.4/java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:194)
	at java.base@21.0.4/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:387)
	at java.base@21.0.4/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1312)
	at java.base@21.0.4/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1843)
	at java.base@21.0.4/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1808)
	at java.base@21.0.4/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:188)
}

@Test
@WithMockUser(username = STUDENT_OF_COURSE, roles = "USER")
void shouldReturnScore() throws Exception {
final var result = request.get("/api/metrics/course/" + course.getId() + "/student", HttpStatus.OK, StudentMetricsDTO.class);
assertThat(result).isNotNull();
assertThat(result.exerciseMetrics()).isNotNull();
final var score = result.exerciseMetrics().score();

final var exercises = exerciseRepository.findAllExercisesByCourseId(course.getId());
final var expectedScores = exercises.stream().collect(Collectors.toMap(Exercise::getId, exercise -> resultRepository
.getRatedResultsOrderedByParticipationIdLegalSubmissionIdResultIdDescForStudent(exercise.getId(), userID).stream().mapToDouble(Result::getScore).sum()));

assertThat(score).isEqualTo(expectedScores);
}

@Test
@WithMockUser(username = STUDENT_OF_COURSE, roles = "USER")
void shouldReturnAverageLatestSubmission() throws Exception {
Expand Down Expand Up @@ -181,7 +229,6 @@
Set<Long> exerciseIds = new HashSet<Long>();
final var exercises = exerciseRepository.findAllExercisesByCourseId(courseWithTestRuns.getId()).stream()
.map(exercise -> exerciseRepository.findWithEagerStudentParticipationsStudentAndSubmissionsById(exercise.getId()).orElseThrow());
final var userID = userUtilService.getUserByLogin(TEST_PREFIX + "student1").getId();

Set<ResourceTimestampDTO> expectedSet = exercises.flatMap(exercise -> {
exerciseIds.add(exercise.getId());
Expand All @@ -195,5 +242,64 @@
Set<ResourceTimestampDTO> result = exerciseMetricsRepository.findLatestSubmissionDatesForUser(exerciseIds, userID);
assertThat(result).isEqualTo(expectedSet);
}

@Disabled
@Test
@WithMockUser(username = STUDENT_OF_COURSE, roles = "USER")
void shouldReturnCompleted() throws Exception {

final var result = request.get("/api/metrics/course/" + course.getId() + "/student", HttpStatus.OK, StudentMetricsDTO.class);
assertThat(result).isNotNull();
assertThat(result.exerciseMetrics()).isNotNull();
final var completed = result.exerciseMetrics().completed();

final var exercises = exerciseRepository.getAllExercisesUserParticipatedInWithEagerParticipationsSubmissionsResultsFeedbacksTestCasesByUserId(userID);

final var expectedCompleted = exercises.stream().map(Exercise::getId)
.filter(id -> resultRepository.getRatedResultsOrderedByParticipationIdLegalSubmissionIdResultIdDescForStudent(id, userID).stream()
.anyMatch(result1 -> result1.getScore() != null && result1.getScore() >= MIN_SCORE_GREEN))
.collect(Collectors.toSet());

assertThat(completed).isEqualTo(expectedCompleted);
}
}

@Nested
class CompetencyMetrics {

@Disabled
@Test
@WithMockUser(username = STUDENT_OF_COURSE, roles = "USER")
void shouldReturnCompetencyInformation() throws Exception {
final var result = request.get("/api/metrics/course/" + courseWithCompetencies.getId() + "/student", HttpStatus.OK, StudentMetricsDTO.class);
assertThat(result).isNotNull();
assertThat(result.competencyMetrics()).isNotNull();

final var competencyInformation = result.competencyMetrics().competencyInformation();

final var expectedCompetencies = competencyMetricsRepository.findAllCompetencyInformationByCourseId(courseWithCompetencies.getId());

assertThat(competencyInformation.values()).containsExactlyInAnyOrderElementsOf(expectedCompetencies);
assertThat(competencyInformation).allSatisfy((id, dto) -> assertThat(id).isEqualTo(dto.id()));
}
}

@Nested
class LectureMetrics {

@Disabled
@Test
@WithMockUser(username = STUDENT_OF_COURSE, roles = "USER")
void shouldReturnLectureUnitInformation() throws Exception {
final var result = request.get("/api/metrics/course/" + courseWithCompetencies.getId() + "/student", HttpStatus.OK, StudentMetricsDTO.class);
assertThat(result).isNotNull();
assertThat(result.lectureUnitStudentMetricsDTO()).isNotNull();
final var lectureUnitInformation = result.lectureUnitStudentMetricsDTO().lectureUnitInformation();

final var expectedLectureUnits = lectureUnitMetricsRepository.findAllLectureUnitInformationByCourseId(courseWithCompetencies.getId());

assertThat(lectureUnitInformation.values()).containsExactlyInAnyOrderElementsOf(expectedLectureUnits);
assertThat(lectureUnitInformation).allSatisfy((id, dto) -> assertThat(id).isEqualTo(dto.id()));
}
}
}
Loading
Loading