use of de.tum.in.www1.artemis.domain.exam.ExerciseGroup in project ArTEMiS by ls1intum.
the class ExamIntegrationTest method lockAllRepositories.
@Test
@WithMockUser(username = "instructor1", roles = "INSTRUCTOR")
public void lockAllRepositories() throws Exception {
ExerciseGroup exerciseGroup1 = new ExerciseGroup();
Exam exam = database.addExam(course1);
exam.addExerciseGroup(exerciseGroup1);
exam = examRepository.save(exam);
Exam examWithExerciseGroups = examRepository.findWithExerciseGroupsAndExercisesById(exam.getId()).get();
exerciseGroup1 = examWithExerciseGroups.getExerciseGroups().get(0);
ProgrammingExercise programmingExercise = ModelFactory.generateProgrammingExerciseForExam(exerciseGroup1);
programmingExercise = programmingExerciseRepository.save(programmingExercise);
exerciseGroup1.addExercise(programmingExercise);
ProgrammingExercise programmingExercise2 = ModelFactory.generateProgrammingExerciseForExam(exerciseGroup1);
programmingExercise2 = programmingExerciseRepository.save(programmingExercise2);
exerciseGroup1.addExercise(programmingExercise2);
exerciseGroupRepository.save(exerciseGroup1);
Integer numOfLockedExercises = request.postWithResponseBody("/api/courses/" + course1.getId() + "/exams/" + exam.getId() + "/student-exams/lock-all-repositories", Optional.empty(), Integer.class, HttpStatus.OK);
assertThat(numOfLockedExercises).isEqualTo(2);
verify(programmingExerciseScheduleService, times(1)).lockAllStudentRepositories(programmingExercise);
verify(programmingExerciseScheduleService, times(1)).lockAllStudentRepositories(programmingExercise2);
}
use of de.tum.in.www1.artemis.domain.exam.ExerciseGroup in project ArTEMiS by ls1intum.
the class ExamIntegrationTest method testGetExam_asInstructor_WithTestRunQuizExerciseSubmissions.
@Test
@WithMockUser(username = "instructor1", roles = "INSTRUCTOR")
public void testGetExam_asInstructor_WithTestRunQuizExerciseSubmissions() throws Exception {
Course course = database.addEmptyCourse();
Exam exam = database.addExamWithExerciseGroup(course, true);
ExerciseGroup exerciseGroup = exam.getExerciseGroups().get(0);
examRepository.save(exam);
StudentParticipation studentParticipation = new StudentParticipation();
studentParticipation.setTestRun(true);
QuizExercise quizExercise = database.createQuizForExam(exerciseGroup);
quizExercise.setStudentParticipations(Set.of(studentParticipation));
studentParticipation.setExercise(quizExercise);
exerciseRepo.save(quizExercise);
studentParticipationRepository.save(studentParticipation);
Exam returnedExam = request.get("/api/courses/" + course.getId() + "/exams/" + exam.getId() + "?withExerciseGroups=true", HttpStatus.OK, Exam.class);
assertThat(returnedExam.getExerciseGroups()).anyMatch(groups -> groups.getExercises().stream().anyMatch(Exercise::getTestRunParticipationsExist));
verify(examAccessService, times(1)).checkCourseAndExamAccessForEditorElseThrow(course.getId(), exam.getId());
}
use of de.tum.in.www1.artemis.domain.exam.ExerciseGroup in project ArTEMiS by ls1intum.
the class ExamIntegrationTest method testStartExercisesWithTextExercise.
@Test
@WithMockUser(username = "instructor1", roles = "INSTRUCTOR")
public void testStartExercisesWithTextExercise() throws Exception {
// TODO IMPORTANT test more complex exam configurations (mixed exercise type, more variants and more registered students)
// registering users
var student1 = database.getUserByLogin("student1");
var student2 = database.getUserByLogin("student2");
var registeredUsers = Set.of(student1, student2);
exam2.setRegisteredUsers(registeredUsers);
// setting dates
exam2.setStartDate(now().plusHours(2));
exam2.setEndDate(now().plusHours(3));
exam2.setVisibleDate(now().plusHours(1));
// creating exercise
ExerciseGroup exerciseGroup = exam2.getExerciseGroups().get(0);
TextExercise textExercise = ModelFactory.generateTextExerciseForExam(exerciseGroup);
exerciseGroup.addExercise(textExercise);
exerciseGroupRepository.save(exerciseGroup);
textExercise = exerciseRepo.save(textExercise);
List<StudentExam> createdStudentExams = new ArrayList<>();
// creating student exams
for (User user : registeredUsers) {
StudentExam studentExam = new StudentExam();
studentExam.addExercise(textExercise);
studentExam.setUser(user);
exam2.addStudentExam(studentExam);
createdStudentExams.add(studentExamRepository.save(studentExam));
}
exam2 = examRepository.save(exam2);
// invoke start exercises
Integer noGeneratedParticipations = request.postWithResponseBody("/api/courses/" + course1.getId() + "/exams/" + exam2.getId() + "/student-exams/start-exercises", Optional.empty(), Integer.class, HttpStatus.OK);
assertThat(noGeneratedParticipations).isEqualTo(exam2.getStudentExams().size());
List<Participation> studentParticipations = participationTestRepository.findAllWithSubmissions();
for (Participation participation : studentParticipations) {
assertThat(participation.getExercise()).isEqualTo(textExercise);
assertThat(participation.getExercise().getCourseViaExerciseGroupOrCourseMember()).isNotNull();
assertThat(participation.getExercise().getExerciseGroup()).isEqualTo(exam2.getExerciseGroups().get(0));
assertThat(participation.getSubmissions()).hasSize(1);
var textSubmission = (TextSubmission) participation.getSubmissions().iterator().next();
assertThat(textSubmission.getText()).isNull();
}
// Cleanup of Bidirectional Relationships
for (StudentExam studentExam : createdStudentExams) {
exam2.removeStudentExam(studentExam);
}
examRepository.save(exam2);
}
use of de.tum.in.www1.artemis.domain.exam.ExerciseGroup in project ArTEMiS by ls1intum.
the class ExamIntegrationTest method testUpdateOrderOfExerciseGroups.
@Test
@WithMockUser(username = "instructor1", roles = "INSTRUCTOR")
public void testUpdateOrderOfExerciseGroups() throws Exception {
ExerciseGroup exerciseGroup1 = new ExerciseGroup();
exerciseGroup1.setTitle("first");
ExerciseGroup exerciseGroup2 = new ExerciseGroup();
exerciseGroup2.setTitle("second");
ExerciseGroup exerciseGroup3 = new ExerciseGroup();
exerciseGroup3.setTitle("third");
Exam exam = database.addExam(course1);
exam.addExerciseGroup(exerciseGroup1);
exam.addExerciseGroup(exerciseGroup2);
exam.addExerciseGroup(exerciseGroup3);
examRepository.save(exam);
Exam examWithExerciseGroups = examRepository.findWithExerciseGroupsById(exam.getId()).get();
exerciseGroup1 = examWithExerciseGroups.getExerciseGroups().get(0);
exerciseGroup2 = examWithExerciseGroups.getExerciseGroups().get(1);
exerciseGroup3 = examWithExerciseGroups.getExerciseGroups().get(2);
TextExercise exercise1_1 = ModelFactory.generateTextExerciseForExam(exerciseGroup1);
TextExercise exercise1_2 = ModelFactory.generateTextExerciseForExam(exerciseGroup1);
TextExercise exercise2_1 = ModelFactory.generateTextExerciseForExam(exerciseGroup2);
TextExercise exercise3_1 = ModelFactory.generateTextExerciseForExam(exerciseGroup3);
TextExercise exercise3_2 = ModelFactory.generateTextExerciseForExam(exerciseGroup3);
TextExercise exercise3_3 = ModelFactory.generateTextExerciseForExam(exerciseGroup3);
exercise1_1 = textExerciseRepository.save(exercise1_1);
exercise1_2 = textExerciseRepository.save(exercise1_2);
exercise2_1 = textExerciseRepository.save(exercise2_1);
exercise3_1 = textExerciseRepository.save(exercise3_1);
exercise3_2 = textExerciseRepository.save(exercise3_2);
exercise3_3 = textExerciseRepository.save(exercise3_3);
examWithExerciseGroups = examRepository.findWithExerciseGroupsById(exam.getId()).get();
exerciseGroup1 = examWithExerciseGroups.getExerciseGroups().get(0);
exerciseGroup2 = examWithExerciseGroups.getExerciseGroups().get(1);
exerciseGroup3 = examWithExerciseGroups.getExerciseGroups().get(2);
List<ExerciseGroup> orderedExerciseGroups = new ArrayList<>();
orderedExerciseGroups.add(exerciseGroup2);
orderedExerciseGroups.add(exerciseGroup3);
orderedExerciseGroups.add(exerciseGroup1);
// Should save new order
request.put("/api/courses/" + course1.getId() + "/exams/" + exam.getId() + "/exercise-groups-order", orderedExerciseGroups, HttpStatus.OK);
verify(examAccessService, times(1)).checkCourseAndExamAccessForEditorElseThrow(course1.getId(), exam.getId());
List<ExerciseGroup> savedExerciseGroups = examRepository.findWithExerciseGroupsById(exam.getId()).get().getExerciseGroups();
assertThat(savedExerciseGroups.get(0).getTitle()).isEqualTo("second");
assertThat(savedExerciseGroups.get(1).getTitle()).isEqualTo("third");
assertThat(savedExerciseGroups.get(2).getTitle()).isEqualTo("first");
// Exercises should be preserved
Exam savedExam = examRepository.findWithExerciseGroupsAndExercisesById(exam.getId()).get();
ExerciseGroup savedExerciseGroup1 = savedExam.getExerciseGroups().get(2);
ExerciseGroup savedExerciseGroup2 = savedExam.getExerciseGroups().get(0);
ExerciseGroup savedExerciseGroup3 = savedExam.getExerciseGroups().get(1);
assertThat(savedExerciseGroup1.getExercises()).hasSize(2);
assertThat(savedExerciseGroup2.getExercises()).hasSize(1);
assertThat(savedExerciseGroup3.getExercises()).hasSize(3);
assertThat(savedExerciseGroup1.getExercises()).contains(exercise1_1);
assertThat(savedExerciseGroup1.getExercises()).contains(exercise1_2);
assertThat(savedExerciseGroup2.getExercises()).contains(exercise2_1);
assertThat(savedExerciseGroup3.getExercises()).contains(exercise3_1);
assertThat(savedExerciseGroup3.getExercises()).contains(exercise3_2);
assertThat(savedExerciseGroup3.getExercises()).contains(exercise3_3);
// Should fail with too many exercise groups
orderedExerciseGroups.add(exerciseGroup1);
request.put("/api/courses/" + course1.getId() + "/exams/" + exam.getId() + "/exercise-groups-order", orderedExerciseGroups, HttpStatus.FORBIDDEN);
// Should fail with too few exercise groups
orderedExerciseGroups.remove(3);
orderedExerciseGroups.remove(2);
request.put("/api/courses/" + course1.getId() + "/exams/" + exam.getId() + "/exercise-groups-order", orderedExerciseGroups, HttpStatus.FORBIDDEN);
// Should fail with different exercise group
orderedExerciseGroups = new ArrayList<>();
orderedExerciseGroups.add(exerciseGroup2);
orderedExerciseGroups.add(exerciseGroup3);
orderedExerciseGroups.add(ModelFactory.generateExerciseGroup(true, exam));
request.put("/api/courses/" + course1.getId() + "/exams/" + exam.getId() + "/exercise-groups-order", orderedExerciseGroups, HttpStatus.FORBIDDEN);
}
use of de.tum.in.www1.artemis.domain.exam.ExerciseGroup in project ArTEMiS by ls1intum.
the class ExamIntegrationTest method testGetStatsForExamAssessmentDashboard.
public void testGetStatsForExamAssessmentDashboard(int numberOfCorrectionRounds) throws Exception {
User examTutor1 = userRepo.findOneByLogin("tutor1").get();
User examTutor2 = userRepo.findOneByLogin("tutor2").get();
var examVisibleDate = ZonedDateTime.now().minusMinutes(5);
var examStartDate = ZonedDateTime.now().plusMinutes(5);
var examEndDate = ZonedDateTime.now().plusMinutes(20);
Course course = database.addEmptyCourse();
Exam exam = database.addExam(course, examVisibleDate, examStartDate, examEndDate);
exam.setNumberOfCorrectionRoundsInExam(numberOfCorrectionRounds);
exam = examRepository.save(exam);
exam = database.addExerciseGroupsAndExercisesToExam(exam, false);
var stats = request.get("/api/courses/" + course.getId() + "/exams/" + exam.getId() + "/stats-for-exam-assessment-dashboard", HttpStatus.OK, StatsForDashboardDTO.class);
assertThat(stats.getNumberOfSubmissions()).isInstanceOf(DueDateStat.class);
assertThat(stats.getTutorLeaderboardEntries()).isInstanceOf(List.class);
assertThat(stats.getNumberOfAssessmentsOfCorrectionRounds()).isInstanceOf(DueDateStat[].class);
assertThat(stats.getNumberOfAssessmentLocks()).isZero();
assertThat(stats.getNumberOfSubmissions().inTime()).isZero();
assertThat(stats.getNumberOfAssessmentsOfCorrectionRounds()[0].inTime()).isZero();
assertThat(stats.getTotalNumberOfAssessmentLocks()).isZero();
var lockedSubmissions = request.get("/api/courses/" + course.getId() + "/exams/" + exam.getId() + "/lockedSubmissions", HttpStatus.OK, List.class);
assertThat(lockedSubmissions).isEmpty();
// register users. Instructors are ignored from scores as they are exclusive for test run exercises
Set<User> registeredStudents = users.stream().filter(user -> !user.getLogin().contains("instructor") && !user.getLogin().contains("admin")).collect(Collectors.toSet());
exam.setRegisteredUsers(registeredStudents);
exam.setNumberOfExercisesInExam(exam.getExerciseGroups().size());
exam.setRandomizeExerciseOrder(false);
exam = examRepository.save(exam);
exam = examRepository.findWithRegisteredUsersAndExerciseGroupsAndExercisesById(exam.getId()).get();
// generate individual student exams
List<StudentExam> studentExams = request.postListWithResponseBody("/api/courses/" + course.getId() + "/exams/" + exam.getId() + "/generate-student-exams", Optional.empty(), StudentExam.class, HttpStatus.OK);
Integer noGeneratedParticipations = request.postWithResponseBody("/api/courses/" + course.getId() + "/exams/" + exam.getId() + "/student-exams/start-exercises", Optional.empty(), Integer.class, HttpStatus.OK);
// set start and submitted date as results are created below
studentExams.forEach(studentExam -> {
studentExam.setStarted(true);
studentExam.setStartedDate(ZonedDateTime.now().minusMinutes(2));
studentExam.setSubmitted(true);
studentExam.setSubmissionDate(ZonedDateTime.now().minusMinutes(1));
});
studentExamRepository.saveAll(studentExams);
// Fetch the created participations and assign them to the exercises
int participationCounter = 0;
List<Exercise> exercisesInExam = exam.getExerciseGroups().stream().map(ExerciseGroup::getExercises).flatMap(Collection::stream).collect(Collectors.toList());
for (var exercise : exercisesInExam) {
List<StudentParticipation> participations = studentParticipationRepository.findByExerciseIdWithEagerLegalSubmissionsResult(exercise.getId());
exercise.setStudentParticipations(new HashSet<>(participations));
participationCounter += exercise.getStudentParticipations().size();
}
assertEquals(participationCounter, noGeneratedParticipations);
// Assign submissions to the participations
for (var exercise : exercisesInExam) {
for (var participation : exercise.getStudentParticipations()) {
Submission submission;
assertThat(participation.getSubmissions()).hasSize(1);
submission = participation.getSubmissions().iterator().next();
submission.submitted(true);
submission.setSubmissionDate(ZonedDateTime.now().minusMinutes(6));
submissionRepository.save(submission);
}
}
// check the stats again - check the count of submitted submissions
stats = request.get("/api/courses/" + course.getId() + "/exams/" + exam.getId() + "/stats-for-exam-assessment-dashboard", HttpStatus.OK, StatsForDashboardDTO.class);
assertThat(stats.getNumberOfAssessmentLocks()).isZero();
// 75 = (15 users * 5 exercises); quiz submissions are not counted
assertThat(stats.getNumberOfSubmissions().inTime()).isEqualTo(75L);
assertThat(stats.getNumberOfAssessmentsOfCorrectionRounds()[0].inTime()).isZero();
assertThat(stats.getNumberOfComplaints()).isZero();
assertThat(stats.getTotalNumberOfAssessmentLocks()).isZero();
// Score used for all exercise results
Double resultScore = 75.0;
// Lock all submissions
for (var exercise : exercisesInExam) {
for (var participation : exercise.getStudentParticipations()) {
Submission submission;
assertThat(participation.getSubmissions()).hasSize(1);
submission = participation.getSubmissions().iterator().next();
// Create results
var result = new Result().score(resultScore).resultString("Good");
if (exercise instanceof QuizExercise) {
result.completionDate(ZonedDateTime.now().minusMinutes(4));
result.setRated(true);
}
result.setAssessmentType(AssessmentType.SEMI_AUTOMATIC);
result.setParticipation(participation);
result.setAssessor(examTutor1);
result = resultRepository.save(result);
result.setSubmission(submission);
submission.addResult(result);
submissionRepository.save(submission);
}
}
// check the stats again
database.changeUser("tutor1");
stats = request.get("/api/courses/" + course.getId() + "/exams/" + exam.getId() + "/stats-for-exam-assessment-dashboard", HttpStatus.OK, StatsForDashboardDTO.class);
assertThat(stats.getNumberOfAssessmentLocks()).isEqualTo(75L);
// 75 = (15 users * 5 exercises); quiz submissions are not counted
assertThat(stats.getNumberOfSubmissions().inTime()).isEqualTo(75L);
// the 15 quiz submissions are already assessed
assertThat(stats.getNumberOfAssessmentsOfCorrectionRounds()[0].inTime()).isEqualTo(15L);
assertThat(stats.getNumberOfComplaints()).isZero();
assertThat(stats.getTotalNumberOfAssessmentLocks()).isEqualTo(75L);
// test the query needed for assessment information
database.changeUser("tutor2");
exam.getExerciseGroups().forEach(group -> {
var locks = group.getExercises().stream().map(exercise -> resultRepository.countNumberOfLockedAssessmentsByOtherTutorsForExamExerciseForCorrectionRounds(exercise, numberOfCorrectionRounds, examTutor2)[0].inTime()).reduce(Long::sum).get();
if (group.getExercises().stream().anyMatch(exercise -> !(exercise instanceof QuizExercise)))
assertThat(locks).isEqualTo(15L);
});
database.changeUser("instructor1");
lockedSubmissions = request.get("/api/courses/" + course.getId() + "/exams/" + exam.getId() + "/lockedSubmissions", HttpStatus.OK, List.class);
assertThat(lockedSubmissions).hasSize(75);
// Finish assessment of all submissions
for (var exercise : exercisesInExam) {
for (var participation : exercise.getStudentParticipations()) {
Submission submission;
assertThat(participation.getSubmissions()).hasSize(1);
submission = participation.getSubmissions().iterator().next();
var result = submission.getLatestResult().completionDate(ZonedDateTime.now().minusMinutes(5));
result.setRated(true);
resultRepository.save(result);
}
}
// check the stats again
stats = request.get("/api/courses/" + course.getId() + "/exams/" + exam.getId() + "/stats-for-exam-assessment-dashboard", HttpStatus.OK, StatsForDashboardDTO.class);
assertThat(stats.getNumberOfAssessmentLocks()).isZero();
// 75 = (15 users * 5 exercises); quiz submissions are not counted
assertThat(stats.getNumberOfSubmissions().inTime()).isEqualTo(75L);
// 75 + the 15 quiz submissions
assertThat(stats.getNumberOfAssessmentsOfCorrectionRounds()[0].inTime()).isEqualTo(90L);
assertThat(stats.getNumberOfComplaints()).isZero();
assertThat(stats.getTotalNumberOfAssessmentLocks()).isZero();
lockedSubmissions = request.get("/api/courses/" + course.getId() + "/exams/" + exam.getId() + "/lockedSubmissions", HttpStatus.OK, List.class);
assertThat(lockedSubmissions).isEmpty();
if (numberOfCorrectionRounds == 2) {
lockAndAssessForSecondCorrection(exam, course, exercisesInExam, numberOfCorrectionRounds);
}
}
Aggregations