diff --git a/src/main/java/de/unistuttgart/iste/meitrex/assignment_service/persistence/entity/grading/CodeAssignmentGradingMetadataEntity.java b/src/main/java/de/unistuttgart/iste/meitrex/assignment_service/persistence/entity/grading/CodeAssignmentGradingMetadataEntity.java index ca73ff6..f21d49f 100644 --- a/src/main/java/de/unistuttgart/iste/meitrex/assignment_service/persistence/entity/grading/CodeAssignmentGradingMetadataEntity.java +++ b/src/main/java/de/unistuttgart/iste/meitrex/assignment_service/persistence/entity/grading/CodeAssignmentGradingMetadataEntity.java @@ -37,4 +37,7 @@ public class CodeAssignmentGradingMetadataEntity { @Column(nullable = true, columnDefinition = "TEXT") private String feedbackTableHtml; + + @Column(nullable = true) + private String lastProcessedCommitSha; } \ No newline at end of file diff --git a/src/main/java/de/unistuttgart/iste/meitrex/assignment_service/service/GradingService.java b/src/main/java/de/unistuttgart/iste/meitrex/assignment_service/service/GradingService.java index fa23699..f024fb0 100644 --- a/src/main/java/de/unistuttgart/iste/meitrex/assignment_service/service/GradingService.java +++ b/src/main/java/de/unistuttgart/iste/meitrex/assignment_service/service/GradingService.java @@ -192,11 +192,33 @@ private List getCodeAssignmentGradingForAdmin(final AssignmentEntity as } + /** + * Returns the grading for the current user on the given code assignment. + */ private List getCodeAssignmentGradingForStudent(final AssignmentEntity assignment, final LoggedInUser currentUser) { log.info("[GRADING-FLOW] >>> getCodeAssignmentGradingForStudent START - assignmentId={}, studentId={}", assignment.getId(), currentUser.getId()); - final GradingEntity.PrimaryKey pk = new GradingEntity.PrimaryKey(assignment.getId(), currentUser.getId()); + GradingEntity gradingEntity = ensureGradingEntityExists(assignment.getId(), currentUser.getId()); + + findAndSetRepositoryLinkIfMissing(gradingEntity, assignment, currentUser); + + if (hasRepositoryLink(gradingEntity)) { + syncAndUpdateGrading(gradingEntity, assignment, currentUser); + } + + log.info("[GRADING-FLOW] Saving grading entity to database"); + gradingEntity = gradingRepository.save(gradingEntity); + log.info("[GRADING-FLOW] <<< getCodeAssignmentGradingForStudent END - returning grading"); + return List.of(assignmentMapper.gradingEntityToDto(gradingEntity)); + } + + /** + * Ensures a grading entity exists for the given assignment and student. + * Creates a new entity with metadata if it doesn't exist. + */ + private GradingEntity ensureGradingEntityExists(final UUID assignmentId, final UUID studentId) { + final GradingEntity.PrimaryKey pk = new GradingEntity.PrimaryKey(assignmentId, studentId); GradingEntity gradingEntity = gradingRepository.findById(pk).orElse(null); if (gradingEntity == null) { @@ -213,91 +235,169 @@ private List getCodeAssignmentGradingForStudent(final AssignmentEntity gradingEntity.setCodeAssignmentGradingMetadata(metadata); } - if (gradingEntity.getCodeAssignmentGradingMetadata() == null || - gradingEntity.getCodeAssignmentGradingMetadata().getRepoLink() == null) { - log.info("[GRADING-FLOW] Repository link not found, attempting to find student repository"); - try { - String assignmentName = contentServiceClient.queryContentsOfCourse(currentUser.getId(), assignment.getCourseId()).stream() - .filter(assignmentDto -> assignmentDto.getId().equals(assignment.getId())) - .findFirst() - .orElseThrow(() -> new EntityNotFoundException("Assignment with externalId %s not found".formatted(assignment.getExternalId()))) - .getMetadata().getName(); - - String courseTitle = courseServiceClient.queryCourseById(assignment.getCourseId()).getTitle(); - // no isPresent check, since if we are here, the external course must exist - String organizationName = externalCourseRepository.findById(courseTitle).get().getOrganizationName(); - - log.info("[GRADING-FLOW] Calling findRepository with assignmentName={}, organizationName={}", - assignmentName, organizationName); - String repoLink = codeAssessmentProvider.findRepository(assignmentName, organizationName, currentUser); - log.info("[GRADING-FLOW] Repository link found: {}", repoLink != null ? repoLink : "NULL"); - gradingEntity.getCodeAssignmentGradingMetadata().setRepoLink(repoLink); - } catch (ExternalPlatformConnectionException | UserServiceConnectionException | - ContentServiceConnectionException | CourseServiceConnectionException e) { - log.error("[GRADING-FLOW] ERROR: Failed to find repository for assignment {} and student {}: {}", assignment.getId(), currentUser.getId(), e.toString()); - } + return gradingEntity; + } + + /** + * Checks if the grading entity has a repository link set. + */ + private boolean hasRepositoryLink(final GradingEntity gradingEntity) { + return gradingEntity.getCodeAssignmentGradingMetadata() != null && + gradingEntity.getCodeAssignmentGradingMetadata().getRepoLink() != null; + } + + /** + * Finds and sets the repository link for the student if it's missing. + */ + private void findAndSetRepositoryLinkIfMissing(final GradingEntity gradingEntity, + final AssignmentEntity assignment, + final LoggedInUser currentUser) { + if (hasRepositoryLink(gradingEntity)) { + return; } - if (gradingEntity.getCodeAssignmentGradingMetadata() != null && - gradingEntity.getCodeAssignmentGradingMetadata().getRepoLink() != null) { - log.info("[GRADING-FLOW] Repository link exists: {}", - gradingEntity.getCodeAssignmentGradingMetadata().getRepoLink()); - ExternalGrading externalGrading; - try { - externalGrading = codeAssessmentProvider.syncGradeForStudent(gradingEntity.getCodeAssignmentGradingMetadata().getRepoLink(), currentUser); - log.info("[GRADING-FLOW] syncGradeForStudent completed - achievedPoints={}, totalPoints={}, status={}", - externalGrading.achievedPoints(), externalGrading.totalPoints(), externalGrading.status()); - } catch (ExternalPlatformConnectionException | UserServiceConnectionException e) { - log.error("[GRADING-FLOW] ERROR: Failed to sync student grade for assignment {} and student {}: {}", assignment.getId(), currentUser.getId(), e.toString()); - gradingEntity = gradingRepository.save(gradingEntity); - return List.of(assignmentMapper.gradingEntityToDto(gradingEntity)); - } + log.info("[GRADING-FLOW] Repository link not found, attempting to find student repository"); + try { + String assignmentName = contentServiceClient.queryContentsOfCourse(currentUser.getId(), assignment.getCourseId()).stream() + .filter(assignmentDto -> assignmentDto.getId().equals(assignment.getId())) + .findFirst() + .orElseThrow(() -> new EntityNotFoundException("Assignment with externalId %s not found".formatted(assignment.getExternalId()))) + .getMetadata().getName(); - if (externalGrading.achievedPoints() != null){ - gradingEntity.setAchievedCredits(externalGrading.achievedPoints()); - } - gradingEntity.setDate(externalGrading.date()); + String courseTitle = courseServiceClient.queryCourseById(assignment.getCourseId()).getTitle(); + String organizationName = externalCourseRepository.findById(courseTitle).get().getOrganizationName(); - CodeAssignmentGradingMetadataEntity metadata = gradingEntity.getCodeAssignmentGradingMetadata(); - metadata.setStatus(externalGrading.status()); - metadata.setFeedbackTableHtml(externalGrading.tableHtml()); + log.info("[GRADING-FLOW] Calling findRepository with assignmentName={}, organizationName={}", + assignmentName, organizationName); + String repoLink = codeAssessmentProvider.findRepository(assignmentName, organizationName, currentUser); + log.info("[GRADING-FLOW] Repository link found: {}", repoLink != null ? repoLink : "NULL"); + gradingEntity.getCodeAssignmentGradingMetadata().setRepoLink(repoLink); + } catch (ExternalPlatformConnectionException | UserServiceConnectionException | + ContentServiceConnectionException | CourseServiceConnectionException e) { + log.error("[GRADING-FLOW] ERROR: Failed to find repository for assignment {} and student {}: {}", + assignment.getId(), currentUser.getId(), e.toString()); + } + } - if (assignment.getTotalCredits() == null || (externalGrading.totalPoints() != null && externalGrading.totalPoints() > assignment.getTotalCredits())) { - assignment.setTotalCredits(externalGrading.totalPoints()); - } - - log.info("[GRADING-FLOW] Attempting to fetch student code from repository"); - try { - if (codeAssessmentProvider instanceof de.unistuttgart.iste.meitrex.assignment_service.service.code_assignment.GithubClassroom githubClassroom) { - log.info("[GRADING-FLOW] Calling fetchStudentCode for repoLink={}", - gradingEntity.getCodeAssignmentGradingMetadata().getRepoLink()); - - de.unistuttgart.iste.meitrex.assignment_service.service.code_assignment.StudentCodeSubmission codeSubmission = - githubClassroom.fetchStudentCode(gradingEntity.getCodeAssignmentGradingMetadata().getRepoLink(), currentUser); - - log.info("[GRADING-FLOW] fetchStudentCode completed successfully - files count: {}, commit: {}", - codeSubmission.getFiles().size(), codeSubmission.getCommitSha()); - - codeSubmission.setAssignmentId(assignment.getId()); - codeSubmission.setCourseId(assignment.getCourseId()); - - log.info("[GRADING-FLOW] Publishing StudentCodeSubmittedEvent"); - publishStudentCodeSubmittedEvent(codeSubmission); - log.info("[GRADING-FLOW] StudentCodeSubmittedEvent published successfully"); - } else { - log.warn("[GRADING-FLOW] Code assessment provider is not GithubClassroom instance: {}", - codeAssessmentProvider.getClass().getName()); - } - } catch (ExternalPlatformConnectionException | UserServiceConnectionException e) { - log.error("[GRADING-FLOW] ERROR: Failed to fetch student code for assignment {} and student {}: {}", - assignment.getId(), currentUser.getId(), e.toString(), e); + /** + * Syncs grading from external system, updates the grading entity, and handles code submission events. + */ + private void syncAndUpdateGrading(final GradingEntity gradingEntity, + final AssignmentEntity assignment, + final LoggedInUser currentUser) { + log.info("[GRADING-FLOW] Repository link exists: {}", + gradingEntity.getCodeAssignmentGradingMetadata().getRepoLink()); + ExternalGrading externalGrading; + try { + externalGrading = codeAssessmentProvider.syncGradeForStudent( + gradingEntity.getCodeAssignmentGradingMetadata().getRepoLink(), currentUser); + log.info("[GRADING-FLOW] syncGradeForStudent completed - achievedPoints={}, totalPoints={}, status={}", + externalGrading.achievedPoints(), externalGrading.totalPoints(), externalGrading.status()); + } catch (ExternalPlatformConnectionException | UserServiceConnectionException e) { + log.error("[GRADING-FLOW] ERROR: Failed to sync student grade for assignment {} and student {}: {}", + assignment.getId(), currentUser.getId(), e.toString()); + return; + } + + updateGradingFromExternalGrading(gradingEntity, externalGrading, assignment); + handleCodeSubmissionEvent(gradingEntity, externalGrading, assignment, currentUser); + } + + /** + * Updates the grading entity with data from external grading. + */ + private void updateGradingFromExternalGrading(final GradingEntity gradingEntity, + final ExternalGrading externalGrading, + final AssignmentEntity assignment) { + if (externalGrading.achievedPoints() != null) { + gradingEntity.setAchievedCredits(externalGrading.achievedPoints()); + } + gradingEntity.setDate(externalGrading.date()); + + CodeAssignmentGradingMetadataEntity metadata = gradingEntity.getCodeAssignmentGradingMetadata(); + metadata.setStatus(externalGrading.status()); + metadata.setFeedbackTableHtml(externalGrading.tableHtml()); + + if (assignment.getTotalCredits() == null || + (externalGrading.totalPoints() != null && externalGrading.totalPoints() > assignment.getTotalCredits())) { + assignment.setTotalCredits(externalGrading.totalPoints()); + } + } + + /** + * Handles code submission event publishing with commit-based deduplication. + */ + private void handleCodeSubmissionEvent(final GradingEntity gradingEntity, + final ExternalGrading externalGrading, + final AssignmentEntity assignment, + final LoggedInUser currentUser) { + CodeAssignmentGradingMetadataEntity metadata = gradingEntity.getCodeAssignmentGradingMetadata(); + String lastProcessedCommit = metadata.getLastProcessedCommitSha(); + String currentCommit = externalGrading.commitSha(); + + if (!shouldSendCodeSubmissionEvent(lastProcessedCommit, currentCommit, assignment.getId(), currentUser.getId())) { + return; + } + + log.info("[GRADING-FLOW] Attempting to fetch student code from repository"); + try { + if (codeAssessmentProvider instanceof de.unistuttgart.iste.meitrex.assignment_service.service.code_assignment.GithubClassroom githubClassroom) { + log.info("[GRADING-FLOW] Calling fetchStudentCode for repoLink={}", + metadata.getRepoLink()); + + de.unistuttgart.iste.meitrex.assignment_service.service.code_assignment.StudentCodeSubmission codeSubmission = + githubClassroom.fetchStudentCode(metadata.getRepoLink(), currentUser); + + log.info("[GRADING-FLOW] fetchStudentCode completed successfully - files count: {}, commit: {}", + codeSubmission.getFiles().size(), codeSubmission.getCommitSha()); + + codeSubmission.setAssignmentId(assignment.getId()); + codeSubmission.setCourseId(assignment.getCourseId()); + + log.info("[GRADING-FLOW] Publishing StudentCodeSubmittedEvent"); + publishStudentCodeSubmittedEvent(codeSubmission); + log.info("[GRADING-FLOW] StudentCodeSubmittedEvent published successfully"); + + metadata.setLastProcessedCommitSha(currentCommit != null ? currentCommit : "NO_COMMIT_SHA_PROCESSED"); + } else { + log.warn("[GRADING-FLOW] Code assessment provider is not GithubClassroom instance: {}", + codeAssessmentProvider.getClass().getName()); } + } catch (ExternalPlatformConnectionException | UserServiceConnectionException e) { + log.error("[GRADING-FLOW] ERROR: Failed to fetch student code for assignment {} and student {}: {}", + assignment.getId(), currentUser.getId(), e.toString()); } + } - log.info("[GRADING-FLOW] Saving grading entity to database"); - gradingEntity = gradingRepository.save(gradingEntity); - log.info("[GRADING-FLOW] <<< getCodeAssignmentGradingForStudent END - returning grading"); - return List.of(assignmentMapper.gradingEntityToDto(gradingEntity)); + /** + * Determines whether a code submission event should be sent based on commit SHA comparison. + */ + private boolean shouldSendCodeSubmissionEvent(final String lastProcessedCommit, + final String currentCommit, + final UUID assignmentId, + final UUID studentId) { + if (currentCommit != null) { + if (lastProcessedCommit == null || lastProcessedCommit.equals("NO_COMMIT_SHA_PROCESSED")) { + return true; + } else if (!currentCommit.equals(lastProcessedCommit)) { + return true; + } else { + log.debug("Skipping code submission event. Commit {} already processed for student {} on assignment {}", + currentCommit, studentId, assignmentId); + return false; + } + } else { + if (lastProcessedCommit == null || lastProcessedCommit.equals("NO_COMMIT_SHA_PROCESSED")) { + log.warn("No commit SHA available for assignment {} and student {}, sending event without commit tracking", + assignmentId, studentId); + return true; + } else { + log.debug("No commit SHA and event already sent once for student {} on assignment {}, skipping", + studentId, assignmentId); + return false; + } + } + } } /** @@ -555,6 +655,7 @@ private void logGradingImported(final GradingEntity gradingEntity) { .contentId(assignmentEntity.getAssessmentId()) .hintsUsed(0) .success(success) + .contentType(ContentProgressedEvent.ContentType.ASSIGNMENT) .timeToComplete(null) .correctness(correctness) .responses(responses) diff --git a/src/main/java/de/unistuttgart/iste/meitrex/assignment_service/service/code_assignment/ExternalGrading.java b/src/main/java/de/unistuttgart/iste/meitrex/assignment_service/service/code_assignment/ExternalGrading.java index 3497d87..218ba84 100644 --- a/src/main/java/de/unistuttgart/iste/meitrex/assignment_service/service/code_assignment/ExternalGrading.java +++ b/src/main/java/de/unistuttgart/iste/meitrex/assignment_service/service/code_assignment/ExternalGrading.java @@ -2,5 +2,12 @@ import java.time.OffsetDateTime; -public record ExternalGrading(String externalUsername, String status, OffsetDateTime date, String tableHtml, Double achievedPoints, Double totalPoints) { +public record ExternalGrading( + String externalUsername, + String status, + OffsetDateTime date, + String tableHtml, + Double achievedPoints, + Double totalPoints, + String commitSha) { } \ No newline at end of file diff --git a/src/main/java/de/unistuttgart/iste/meitrex/assignment_service/service/code_assignment/GithubClassroom.java b/src/main/java/de/unistuttgart/iste/meitrex/assignment_service/service/code_assignment/GithubClassroom.java index 1afda55..6b1b0f4 100644 --- a/src/main/java/de/unistuttgart/iste/meitrex/assignment_service/service/code_assignment/GithubClassroom.java +++ b/src/main/java/de/unistuttgart/iste/meitrex/assignment_service/service/code_assignment/GithubClassroom.java @@ -281,7 +281,7 @@ public List syncGrades(final String externalAssignmentId, final } } - gradings.add(new ExternalGrading(username, null, submissionDate, null, achieved, total)); + gradings.add(new ExternalGrading(username, null, submissionDate, null, achieved, total, null)); } return gradings; @@ -334,9 +334,10 @@ public ExternalGrading syncGradeForStudent(String repoLink, LoggedInUser current String status = run.get("status").getAsString(); String logsUrl = run.get("logs_url").getAsString(); String lastlyTested = run.get("updated_at").getAsString(); + String commitSha = run.has("head_sha") ? run.get("head_sha").getAsString() : null; if (!status.equals("completed")){ - return new ExternalGrading(null, status, OffsetDateTime.parse(lastlyTested), null, null, null); + return new ExternalGrading(null, status, OffsetDateTime.parse(lastlyTested), null, null, null, commitSha); } // Download logs @@ -378,7 +379,7 @@ public ExternalGrading syncGradeForStudent(String repoLink, LoggedInUser current double totalPoints = Double.parseDouble(matcher.group(1)); double maxPoints = Double.parseDouble(matcher.group(2)); String tableHtml = extractGradingTableAsHtml(logs); - return new ExternalGrading(null, status, OffsetDateTime.parse(lastlyTested), tableHtml, totalPoints, maxPoints); + return new ExternalGrading(null, status, OffsetDateTime.parse(lastlyTested), tableHtml, totalPoints, maxPoints, commitSha); } else { throw new ExternalPlatformConnectionException("Could not find totalPoints/maxPoints in logs."); } diff --git a/src/test/java/de/unistuttgart/iste/meitrex/assignment_service/api/MutationLogAssignmentCompletedTest.java b/src/test/java/de/unistuttgart/iste/meitrex/assignment_service/api/MutationLogAssignmentCompletedTest.java index ebb68cb..e836947 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/assignment_service/api/MutationLogAssignmentCompletedTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/assignment_service/api/MutationLogAssignmentCompletedTest.java @@ -125,6 +125,7 @@ void testValidLogAssignmentCompletedSuccessful(final GraphQlTester tester) { .correctness(35.0/50.0) .hintsUsed(0) .success(true) + .contentType(ContentProgressedEvent.ContentType.ASSIGNMENT) .responses(responses) .build(); @@ -207,6 +208,7 @@ void testValidLogAssignmentCompletedNotSuccessful(final GraphQlTester tester) { .correctness(15.0/50.0) .hintsUsed(0) .success(false) + .contentType(ContentProgressedEvent.ContentType.ASSIGNMENT) .responses(responses) .build(); @@ -294,6 +296,7 @@ void testValidLogAssignmentCompletedNewPercentage(final GraphQlTester tester) { .correctness(35.0/50.0) .hintsUsed(0) .success(false) + .contentType(ContentProgressedEvent.ContentType.ASSIGNMENT) .responses(responses) .build(); @@ -382,6 +385,7 @@ void testValidLogAssignmentCompletedZeroCredits(final GraphQlTester tester) { .correctness(1.0f) .hintsUsed(0) .success(true) + .contentType(ContentProgressedEvent.ContentType.ASSIGNMENT) .responses(responses) .build(); diff --git a/src/test/java/de/unistuttgart/iste/meitrex/assignment_service/api/QueryGetCodeGradingForAssignmentForStudentTest.java b/src/test/java/de/unistuttgart/iste/meitrex/assignment_service/api/QueryGetCodeGradingForAssignmentForStudentTest.java index 9d2c29c..e84fe86 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/assignment_service/api/QueryGetCodeGradingForAssignmentForStudentTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/assignment_service/api/QueryGetCodeGradingForAssignmentForStudentTest.java @@ -116,7 +116,7 @@ void testStudentGetsCodeAssignmentGradingSynced(GraphQlTester tester) throws Ext ); ExternalGrading externalGrading = new ExternalGrading("ext-user", gradingEntity.getCodeAssignmentGradingMetadata().getRepoLink(), OffsetDateTime.now(), - "feedback
", 42.0, 60.0); + "feedback
", 42.0, 60.0, "test-commit-sha"); when(codeAssessmentProvider.findRepository(eq(assignment.getExternalId()), any(), any())).thenReturn(gradingEntity.getCodeAssignmentGradingMetadata().getRepoLink()); @@ -227,7 +227,8 @@ void testStudentGetsCodeAssignmentGradingCreated(GraphQlTester tester) OffsetDateTime.now().truncatedTo(ChronoUnit.SECONDS), "feedback
", 35.0, - 50.0 + 50.0, + "test-commit-sha-2" ); when(codeAssessmentProvider.syncGradeForStudent(eq("https://github.com/user/repo"), any())) .thenReturn(externalGrading); diff --git a/src/test/java/de/unistuttgart/iste/meitrex/assignment_service/service/GradingServiceEventPublishingTest.java b/src/test/java/de/unistuttgart/iste/meitrex/assignment_service/service/GradingServiceEventPublishingTest.java index 8793e85..71ddc0e 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/assignment_service/service/GradingServiceEventPublishingTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/assignment_service/service/GradingServiceEventPublishingTest.java @@ -42,11 +42,9 @@ void setUp() { @Test void testPublishStudentCodeSubmittedEvent_Success() throws Exception { - // Arrange String repoUrl = "https://github.com/org/repo-student"; StudentCodeSubmission codeSubmission = createMockCodeSubmission(repoUrl); - // Create the event that would be published StudentCodeSubmittedEvent event = StudentCodeSubmittedEvent.builder() .studentId(codeSubmission.getStudentId()) .assignmentId(codeSubmission.getAssignmentId()) @@ -58,10 +56,8 @@ void testPublishStudentCodeSubmittedEvent_Success() throws Exception { .branch(codeSubmission.getBranch()) .build(); - // Act topicPublisher.notifyStudentCodeSubmitted(event); - // Assert ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(StudentCodeSubmittedEvent.class); verify(topicPublisher, times(1)).notifyStudentCodeSubmitted(eventCaptor.capture()); @@ -80,7 +76,6 @@ void testPublishStudentCodeSubmittedEvent_Success() throws Exception { @Test void testCodeSubmissionEventContent_AllFieldsPresent() { - // Arrange String repoUrl = "https://github.com/test/repo"; String commitSha = "abc123def456"; OffsetDateTime commitTime = OffsetDateTime.now(); @@ -89,7 +84,6 @@ void testCodeSubmissionEventContent_AllFieldsPresent() { Map files = new HashMap<>(); files.put("Test.java", "public class Test {}"); - // Act StudentCodeSubmittedEvent event = StudentCodeSubmittedEvent.builder() .studentId(studentId) .assignmentId(assignmentId) @@ -101,7 +95,6 @@ void testCodeSubmissionEventContent_AllFieldsPresent() { .branch(branch) .build(); - // Assert assertEquals(studentId, event.getStudentId()); assertEquals(assignmentId, event.getAssignmentId()); assertEquals(courseId, event.getCourseId()); @@ -114,7 +107,6 @@ void testCodeSubmissionEventContent_AllFieldsPresent() { @Test void testCodeSubmission_MultipleFiles() { - // Arrange StudentCodeSubmission codeSubmission = StudentCodeSubmission.builder() .studentId(studentId) .assignmentId(assignmentId) @@ -126,7 +118,6 @@ void testCodeSubmission_MultipleFiles() { .files(createMultipleFiles()) .build(); - // Act StudentCodeSubmittedEvent event = StudentCodeSubmittedEvent.builder() .studentId(codeSubmission.getStudentId()) .assignmentId(codeSubmission.getAssignmentId()) @@ -138,7 +129,6 @@ void testCodeSubmission_MultipleFiles() { .branch(codeSubmission.getBranch()) .build(); - // Assert assertNotNull(event.getFiles()); assertEquals(5, event.getFiles().size()); assertTrue(event.getFiles().containsKey("src/Main.java")); @@ -150,7 +140,6 @@ void testCodeSubmission_MultipleFiles() { @Test void testCodeSubmission_EmptyFiles() { - // Arrange StudentCodeSubmission codeSubmission = StudentCodeSubmission.builder() .studentId(studentId) .assignmentId(assignmentId) @@ -162,7 +151,6 @@ void testCodeSubmission_EmptyFiles() { .files(new HashMap<>()) .build(); - // Act StudentCodeSubmittedEvent event = StudentCodeSubmittedEvent.builder() .studentId(codeSubmission.getStudentId()) .assignmentId(codeSubmission.getAssignmentId()) @@ -174,14 +162,12 @@ void testCodeSubmission_EmptyFiles() { .branch(codeSubmission.getBranch()) .build(); - // Assert assertNotNull(event.getFiles()); assertTrue(event.getFiles().isEmpty()); } @Test void testCodeSubmission_VerifyMetadata() { - // Arrange String repoUrl = "https://github.com/student/assignment-repo"; String commitSha = "1234567890abcdef"; OffsetDateTime timestamp = OffsetDateTime.parse("2025-12-15T10:30:00Z"); @@ -198,7 +184,6 @@ void testCodeSubmission_VerifyMetadata() { .files(Map.of("Main.java", "code")) .build(); - // Assert assertEquals(repoUrl, submission.getRepositoryUrl()); assertEquals(commitSha, submission.getCommitSha()); assertEquals(timestamp, submission.getCommitTimestamp());