def test_complete_with_gradescope(self, runner): course_id = u"cmsc40300" course_name = u"Foobarmentals of Foobar II" admin_id = u"admin" instructor_ids = [u"instructor"] grader_ids = [u"grader"] student_ids = [u"student1", u"student2", u"student3", u"student4"] all_users = instructor_ids + grader_ids + student_ids admin, instructors, graders, students = self.create_clients( runner, admin_id, instructor_ids, grader_ids, student_ids, course_id, gradescope_api_key="gradescope-testing", verbose=True) self.create_users(admin, all_users) self.create_course(admin, course_id, course_name) course = Course.get_by_course_id(course_id) self.assertIsNotNone(course) self.assertEqual(course.name, course_name) result = admin.run("admin course set-attribute %s gradescope_id 4242" % (course_id)) self.assertEqual(result.exit_code, 0) self.add_users_to_course(admin, course_id, instructors, graders, students) deadline = get_datetime_now_utc() + timedelta(hours=1) deadline = convert_datetime_to_local(deadline) deadline = deadline.replace(tzinfo=None).isoformat(sep=" ") result = instructors[0].run( "instructor assignment add", ["pa1", "Programming Assignment 1", deadline]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor assignment set-attribute", ["pa1", "max_students", "2"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor assignment set-attribute", ["pa1", "gradescope_id", "3737"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor assignment set-attribute", ["pa1", "expected_files", "foo,b*,qux"]) self.assertEqual(result.exit_code, 0) teams = [u"student1-student2", u"student3-student4"] students_team = [(students[0], students[1]), (students[2], students[3])] self.register_team(students_team[0], teams[0], "pa1", course_id) self.register_team(students_team[1], teams[1], "pa1", course_id) _, _, team_commits = self.create_team_repos(admin, course_id, teams[0:2], students_team[0:2]) # Team 0 and 1 submit result = students_team[0][0].run("student assignment submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) result = students_team[1][0].run("student assignment submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) for team, student_team in zip(teams, students_team): result = student_team[0].run("student team show", [team]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) # Let the deadline "pass" new_now = get_datetime_now_utc() + timedelta(hours=2) set_testing_now(new_now) print() print("~~~ Time has moved 'forward' by two hours ~~~") print() # Instructor uploads to Gradescope. Both repos should be skipped # because we haven't created the the grading repos yet result = instructors[0].run("instructor grading gradescope-upload", ["--dry-run", "pa1"]) self.assertEqual(result.exit_code, 0) # Instructor creates grading repos result = instructors[0].run("instructor grading create-grading-repos", ["--master", "pa1"]) self.assertEqual(result.exit_code, 0) # Instructor uploads to Gradescope. Both repos should be skipped # because they're missing required file "qux" result = instructors[0].run("instructor grading gradescope-upload", ["--dry-run", "pa1"]) self.assertEqual(result.exit_code, 0) # We change the list of expected files result = instructors[0].run("instructor assignment set-attribute", ["pa1", "expected_files", "foo,b*"]) self.assertEqual(result.exit_code, 0) # Instructor uploads to Gradescope. Both repos should be uploaded # (but we're running in dry-run mode, so we don't actually contact # Gradescope) result = instructors[0].run("instructor grading gradescope-upload", ["--dry-run", "pa1"]) self.assertEqual(result.exit_code, 0)
def test_complete_with_submission_cancelling(self, runner): course_id = u"cmsc40300" course_name = u"Foobarmentals of Foobar II" admin_id = u"admin" instructor_ids = [u"instructor"] grader_ids= [u"grader"] student_ids = [u"student1", u"student2", u"student3", u"student4"] all_users = instructor_ids + grader_ids + student_ids admin, instructors, graders, students = self.create_clients(runner, course_id, admin_id, instructor_ids, grader_ids, student_ids) self.create_users(admin, all_users) self.create_course(admin, course_id, course_name) result = admin.run("admin course set-option %s default-extensions 3" % (course_id)) self.assertEquals(result.exit_code, 0) result = admin.run("admin course set-option %s extension-policy per_student" % (course_id)) self.assertEquals(result.exit_code, 0) self.add_users_to_course(admin, course_id, instructors, graders, students) deadline = get_datetime_now_utc() - timedelta(hours=23) deadline = deadline.isoformat(sep=" ") result = instructors[0].run("instructor assignment add", ["pa1", "Programming Assignment 1", deadline]) self.assertEquals(result.exit_code, 0) teams = [u"the-flaming-foobars", u"the-magnificent-mallocs"] students_team = [ (students[0], students[1]), (students[2], students[3])] self.register_team(students_team[0], teams[0], "pa1", course_id) self.register_team(students_team[1], teams[1], "pa1", course_id) _, _, team_commits = self.create_team_repos(admin, course_id, teams[0:2], students_team[0:2]) # Team 0 cancels their submission # Fails because there is nothing to cancel result = students_team[0][0].run("student assignment cancel-submit", [teams[0], "pa1", "--yes"]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) # Team 0 and 1 submit with one extension to pa1 result = students_team[0][0].run("student assignment submit", [teams[0], "pa1", team_commits[0][0].hexsha, "--extensions", "1", "--yes"]) self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS) result = students_team[1][0].run("student assignment submit", [teams[1], "pa1", team_commits[1][0].hexsha, "--extensions", "1", "--yes"]) self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS) # Team 0 cancels their submission result = students_team[0][0].run("student assignment cancel-submit", [teams[0], "pa1", "--yes"]) self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS) # Team 0 cancels their submission (again) # Fails because there is nothing to cancel result = students_team[0][0].run("student assignment cancel-submit", [teams[0], "pa1", "--yes"]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) # Team 1 resubmits and is successful because the deadline hasn't passed yet result = students_team[1][0].run("student assignment submit", [teams[1], "pa1", team_commits[1][1].hexsha, "--extensions", "1", "--force", "--yes"]) self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS) # Let the deadline "pass" new_now = get_datetime_now_utc() + timedelta(hours=2) set_testing_now(new_now) print print "~~~ Time has moved 'forward' by two hours ~~~" print # Team 0 submits and is successful because they cancelled their previous submission result = students_team[0][0].run("student assignment submit", [teams[0], "pa1", team_commits[0][1].hexsha, "--extensions", "2", "--yes"]) self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS) # Team 1 submits and fails because their previous submission is final result = students_team[1][0].run("student assignment submit", [teams[1], "pa1", team_commits[1][0].hexsha, "--extensions", "2", "--yes"]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) # Team 1 cancels their submission # Fails because the previous submission is final result = students_team[1][0].run("student assignment cancel-submit", [teams[1], "pa1", "--yes"]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) for team, student_team in zip(teams, students_team): result = student_team[0].run("student team show", [team]) self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)
def test_complete_with_multiple_instructors_multiple_graders(self, runner): course_id = u"cmsc40200" course_name = u"Foobarmentals of Foobar" admin_id = u"admin" instructor_ids = [u"instructor1", u"instructor2"] grader_ids = [u"grader1", u"grader2"] student_ids = [u"student1", u"student2", u"student3", u"student4"] all_users = instructor_ids + grader_ids + student_ids admin, instructors, graders, students = self.create_clients( runner, admin_id, instructor_ids, grader_ids, student_ids, course_id, verbose=True) self.create_users(admin, all_users) self.create_course(admin, course_id, course_name) self.add_users_to_course(admin, course_id, instructors, graders, students) students_team = [[s] for s in students] deadline = get_datetime_now_utc() + timedelta(hours=1) deadline = convert_datetime_to_local(deadline) deadline = deadline.replace(tzinfo=None).isoformat(sep=" ") result = instructors[0].run( "instructor assignment add", ["pa1", "Programming Assignment 1", deadline]) self.assertEqual(result.exit_code, 0) pa1_rubric = """Points: - The PA1 Tests: Points Possible: 50 Points Obtained: - The PA1 Design: Points Possible: 50 Points Obtained: Total Points: 0 / 100 """ with open("pa1.rubric.txt", "w") as f: f.write(pa1_rubric) result = instructors[0].run("instructor assignment add-rubric", ["pa1", "pa1.rubric.txt"]) self.assertEqual(result.exit_code, 0) result = admin.run( "admin course show", ["--include-users", "--include-assignments", course_id]) self.assertEqual(result.exit_code, 0) for student_id, student in zip(student_ids, students): self.register_team([student], student_id, "pa1", course_id) for student_id, student in zip(student_ids, students): result = student.run("student team list") self.assertEqual(result.exit_code, 0) self.assertIn(student_id, result.output) result = student.run("student team show", [student_id]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor team list") self.assertEqual(result.exit_code, 0) for student_id in student_ids: result = instructors[0].run("instructor team show", [student_id]) self.assertEqual(result.exit_code, 0) student_git_paths, student_git_repos, team_commits = self.create_team_repos( admin, course_id, student_ids, students_team) for student_id, student in zip(student_ids, students): result = student.run("student assignment submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) result = student.run("student team show", [student_id]) self.assertEqual(result.exit_code, 0) # Let the deadline "pass" new_now = get_datetime_now_utc() + timedelta(hours=2) set_testing_now(new_now) print() print("~~~ Time has moved 'forward' by two hours ~~~") print() # The "master instructor" creates the grading repos result = instructors[0].run("instructor grading list-submissions", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading create-grading-repos", ["--master", "pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading assign-grader", ["pa1", "student1", "grader1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading assign-grader", ["pa1", "student2", "grader1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading assign-grader", ["pa1", "student3", "grader2"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading assign-grader", ["pa1", "student4", "grader2"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run( "instructor grading list-grader-assignments", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading show-grading-status", ["--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading push-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) # The non-master instructor downloads the grading repos result = instructors[1].run("instructor grading create-grading-repos", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[1].run("instructor grading show-grading-status", ["--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) # Grader 1 pulls their grading result = graders[0].run("grader pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) student1_grading_repo_path = "chisubmit-test/repositories/%s/%s/%s" % ( course_id, "pa1", "student1") student2_grading_repo_path = "chisubmit-test/repositories/%s/%s/%s" % ( course_id, "pa1", "student2") student_git_repos[0], student_git_paths[0] = graders[ 0].get_local_git_repository(student1_grading_repo_path) student_git_repos[1], student_git_paths[1] = graders[ 0].get_local_git_repository(student2_grading_repo_path) student1_rubric_path = "%s/pa1.rubric.txt" % student_git_paths[0] student2_rubric_path = "%s/pa1.rubric.txt" % student_git_paths[1] # Grader 1 grades student1 and pushes the grading. student1_rubric = """Points: - The PA1 Tests: Points Possible: 50 Points Obtained: 45 - The PA1 Design: Points Possible: 50 Points Obtained: 30 Penalties: Used O(n^156) algorithm: -10 Submitted code in a Word document: -30 Bonuses: Worked alone: 15 Total Points: 50 / 100 Comments: > None""" with open(student1_rubric_path, "w") as f: f.write(student1_rubric) result = graders[0].run("grader validate-rubrics", ["pa1"]) self.assertEqual(result.exit_code, 0) student_git_repos[0].index.add(["pa1.rubric.txt"]) student_git_repos[0].index.commit("Finished grading") result = graders[0].run("grader push-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) # The non-master instructor pulls the repos and generates a report result = instructors[1].run("instructor grading pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[1].run("instructor grading show-grading-status", ["--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) # Grader 1 grades student2 and pushes the grading. student2_rubric = """Points: - The PA1 Tests: Points Possible: 50 Points Obtained: 50 - The PA1 Design: Points Possible: 50 Points Obtained: 45 Total Points: 95 / 100 Comments: > Great job!""" with open(student2_rubric_path, "w") as f: f.write(student2_rubric) result = graders[0].run("grader validate-rubrics", ["pa1"]) self.assertEqual(result.exit_code, 0) student_git_repos[1].index.add(["pa1.rubric.txt"]) student_git_repos[1].index.commit("Finished grading") result = graders[0].run("grader push-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) # The non-master instructor pulls the repos and generates a report result = instructors[1].run("instructor grading pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[1].run("instructor grading show-grading-status", ["--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) # Grader 2 pulls their grading result = graders[1].run("grader pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) student3_grading_repo_path = "chisubmit-test/repositories/%s/%s/%s" % ( course_id, "pa1", "student3") student4_grading_repo_path = "chisubmit-test/repositories/%s/%s/%s" % ( course_id, "pa1", "student4") student_git_repos[2], student_git_paths[2] = graders[ 1].get_local_git_repository(student3_grading_repo_path) student_git_repos[3], student_git_paths[3] = graders[ 1].get_local_git_repository(student4_grading_repo_path) student3_rubric_path = "%s/pa1.rubric.txt" % student_git_paths[2] student4_rubric_path = "%s/pa1.rubric.txt" % student_git_paths[3] # Grader 2 adds the empty rubrics (which should be generated by pull-grading) result = graders[1].run("grader validate-rubrics", ["pa1"]) self.assertEqual(result.exit_code, 0) student_git_repos[2].index.add(["pa1.rubric.txt"]) student_git_repos[2].index.commit("Added rubric") student_git_repos[3].index.add(["pa1.rubric.txt"]) student_git_repos[3].index.commit("Added rubric") result = graders[1].run("grader push-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) # The non-master instructor pulls the repos and generates a report result = instructors[1].run("instructor grading pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[1].run("instructor grading show-grading-status", ["--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) # Grader 2 grades student3 but does only a partial grading of student4 student3_rubric = """Points: - The PA1 Tests: Points Possible: 50 Points Obtained: 20 - The PA1 Design: Points Possible: 50 Points Obtained: 15 Total Points: 35 / 100 Comments: > Needs improvement!""" with open(student3_rubric_path, "w") as f: f.write(student3_rubric) student4_rubric = """Points: - The PA1 Tests: Points Possible: 50 Points Obtained: 35 - The PA1 Design: Points Possible: 50 Points Obtained: Total Points: 35 / 100 Comments: > """ with open(student4_rubric_path, "w") as f: f.write(student4_rubric) result = graders[1].run("grader validate-rubrics", ["pa1"]) self.assertEqual(result.exit_code, 0) student_git_repos[2].index.add(["pa1.rubric.txt"]) student_git_repos[2].index.commit("Finished grading") student_git_repos[3].index.add(["pa1.rubric.txt"]) student_git_repos[3].index.commit("Grading in progress") result = graders[1].run("grader push-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) # The non-master instructor pulls the repos and generates a report result = instructors[1].run("instructor grading pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[1].run("instructor grading show-grading-status", ["--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) # Grader 2 finishes grading student4_rubric = """Points: - The PA1 Tests: Points Possible: 50 Points Obtained: 35 - The PA1 Design: Points Possible: 50 Points Obtained: 25 Total Points: 60 / 100 Comments: > """ with open(student4_rubric_path, "w") as f: f.write(student4_rubric) result = graders[1].run("grader validate-rubrics", ["pa1"]) self.assertEqual(result.exit_code, 0) student_git_repos[3].index.add(["pa1.rubric.txt"]) student_git_repos[3].index.commit("Finished grading") result = graders[1].run("grader push-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) # The non-master instructor pulls the repos and generates a report result = instructors[1].run("instructor grading pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[1].run("instructor grading show-grading-status", ["--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) # The master instructor pulls the repos and pushes them to the students result = instructors[0].run("instructor grading pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading show-grading-status", ["--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading collect-rubrics", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run( "instructor grading show-grading-status", ["--use-stored-grades", "--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading list-grades") self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading push-grading", ["--to-students", "--yes", "pa1"]) self.assertEqual(result.exit_code, 0) for student_id, student in zip(student_ids, students): repo, path = student.get_local_git_repository(student_id) repo.remote("origin").pull("pa1-grading:pa1-grading") repo.heads["pa1-grading"].checkout() self.assertTrue(os.path.exists(path + "/pa1.rubric.txt"))
def test_complete_with_submission_grace_period(self, runner): course_id = u"cmsc40300" course_name = u"Foobarmentals of Foobar II" admin_id = u"admin" instructor_ids = [u"instructor"] grader_ids= [u"grader"] student_ids = [u"student1", u"student2", u"student3", u"student4"] all_users = instructor_ids + grader_ids + student_ids admin, instructors, graders, students = self.create_clients(runner, admin_id, instructor_ids, grader_ids, student_ids, course_id, verbose = True) self.create_users(admin, all_users) self.create_course(admin, course_id, course_name) course = Course.get_by_course_id(course_id) self.assertIsNotNone(course) self.assertEquals(course.name, course_name) result = admin.run("admin course set-attribute %s default_extensions 2" % (course_id)) self.assertEquals(result.exit_code, 0) result = admin.run("admin course set-attribute %s extension_policy per-student" % (course_id)) self.assertEquals(result.exit_code, 0) self.add_users_to_course(admin, course_id, instructors, graders, students) deadline = get_datetime_now_utc() - timedelta(minutes=5) deadline = deadline.isoformat(sep=" ") result = instructors[0].run("instructor assignment add", ["pa1", "Programming Assignment 1", deadline]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor assignment set-attribute", ["pa1", "max_students", "2"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor assignment set-attribute", ["pa1", "grace_period", "00:15"]) self.assertEquals(result.exit_code, 0) teams = [u"student1-student2", u"student3-student4"] students_team = [ (students[0], students[1]), (students[2], students[3])] self.register_team(students_team[0], teams[0], "pa1", course_id) self.register_team(students_team[1], teams[1], "pa1", course_id) _, _, team_commits = self.create_team_repos(admin, course_id, teams[0:2], students_team[0:2]) # Team 0 submits during the grace period, and doesn't have to use an extension. result = students_team[0][0].run("student assignment submit", ["pa1", "--yes"]) self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS) t = course.get_team(teams[0]) self.assertEqual(t.get_extensions_available(), 2) # Let the grace period "pass" new_now = get_datetime_now_utc() + timedelta(minutes=11) set_testing_now(new_now) print print "~~~ Time has moved 'forward' to one minute after the grace period hours ~~~" print # Team 1 submits and has to use an extensions because the grace period is over result = students_team[1][0].run("student assignment submit", ["pa1", "--yes"]) self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS) t = course.get_team(teams[1]) self.assertEqual(t.get_extensions_available(), 1) for team, student_team in zip(teams, students_team): result = student_team[0].run("student team show", [team]) self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)
def test_complete_with_submission_cancelling(self, runner): course_id = u"cmsc40300" course_name = u"Foobarmentals of Foobar II" admin_id = u"admin" instructor_ids = [u"instructor"] grader_ids= [u"grader"] student_ids = [u"student1", u"student2", u"student3", u"student4"] all_users = instructor_ids + grader_ids + student_ids admin, instructors, graders, students = self.create_clients(runner, admin_id, instructor_ids, grader_ids, student_ids, course_id, verbose = True) self.create_users(admin, all_users) self.create_course(admin, course_id, course_name) result = admin.run("admin course set-attribute %s default_extensions 3" % (course_id)) self.assertEqual(result.exit_code, 0) result = admin.run("admin course set-attribute %s extension_policy per-student" % (course_id)) self.assertEqual(result.exit_code, 0) self.add_users_to_course(admin, course_id, instructors, graders, students) deadline = get_datetime_now_utc() - timedelta(hours=23) deadline = deadline.isoformat(sep=" ") result = instructors[0].run("instructor assignment add", ["pa1", "Programming Assignment 1", deadline]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor assignment set-attribute", ["pa1", "max_students", "2"]) self.assertEqual(result.exit_code, 0) teams = [u"student1-student2", u"student3-student4"] students_team = [ (students[0], students[1]), (students[2], students[3])] self.register_team(students_team[0], teams[0], "pa1", course_id) self.register_team(students_team[1], teams[1], "pa1", course_id) _, _, team_commits = self.create_team_repos(admin, course_id, teams[0:2], students_team[0:2]) # Team 0 cancels their submission # Fails because there is nothing to cancel result = students_team[0][0].run("student assignment cancel-submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_FAIL) # Team 0 and 1 submit with one extension to pa1 result = students_team[0][0].run("student assignment submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) result = students_team[1][0].run("student assignment submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) # Team 0 cancels their submission result = students_team[0][0].run("student assignment cancel-submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) # Team 0 cancels their submission (again) # Fails because there is nothing to cancel result = students_team[0][0].run("student assignment cancel-submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_FAIL) # Team 1 resubmits and is successful because the deadline hasn't passed yet result = students_team[1][0].run("student assignment submit", ["pa1", "--yes", "--commit-sha", team_commits[1][0].hexsha]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) # Let the deadline "pass" new_now = get_datetime_now_utc() + timedelta(hours=2) set_testing_now(new_now) print() print("~~~ Time has moved 'forward' by two hours ~~~") print() # Team 1 cancels their submission and submits again. While the deadline # has passed, the instructor has not yet created the grading repos, # so the students can still cancel their submission. result = students_team[1][0].run("student assignment cancel-submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) result = students_team[1][0].run("student assignment submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) # The instructor waits 24 hours to create the grading repos # (this allows Team 1's repo to be ready for grading) new_now = get_datetime_now_utc() + timedelta(hours=24) set_testing_now(new_now) print() print("~~~ Time has moved 'forward' by 24 hours ~~~") print() # Instructor creates master grading repos. This flags the repo for Team 1 as sent to the graders. result = instructors[0].run("instructor grading create-grading-repos", ["--master", "pa1"]) self.assertEqual(result.exit_code, 0) # Team 0 submits and is successful because they cancelled their previous submission result = students_team[0][0].run("student assignment submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) # Team 1 submits and fails because their previous submission is final result = students_team[1][0].run("student assignment submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_FAIL) # Team 1 cancels their submission # Fails because the previous submission is final result = students_team[1][0].run("student assignment cancel-submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_FAIL) for team, student_team in zip(teams, students_team): result = student_team[0].run("student team show", [team]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS)
def test_complete_with_multiple_instructors_multiple_graders(self, runner): course_id = u"cmsc40200" course_name = u"Foobarmentals of Foobar" admin_id = u"admin" instructor_ids = [u"instructor1", u"instructor2"] grader_ids= [u"grader1", u"grader2"] student_ids = [u"student1", u"student2", u"student3", u"student4"] all_users = instructor_ids + grader_ids + student_ids admin, instructors, graders, students = self.create_clients(runner, admin_id, instructor_ids, grader_ids, student_ids, course_id, verbose = True) self.create_users(admin, all_users) self.create_course(admin, course_id, course_name) self.add_users_to_course(admin, course_id, instructors, graders, students) students_team = [[s] for s in students] deadline = get_datetime_now_utc() + timedelta(hours=1) deadline = convert_datetime_to_local(deadline) deadline = deadline.replace(tzinfo=None).isoformat(sep=" ") result = instructors[0].run("instructor assignment add", ["pa1", "Programming Assignment 1", deadline]) self.assertEqual(result.exit_code, 0) pa1_rubric = """Points: - The PA1 Tests: Points Possible: 50 Points Obtained: - The PA1 Design: Points Possible: 50 Points Obtained: Total Points: 0 / 100 """ with open("pa1.rubric.txt", "w") as f: f.write(pa1_rubric) result = instructors[0].run("instructor assignment add-rubric", ["pa1", "pa1.rubric.txt"]) self.assertEqual(result.exit_code, 0) result = admin.run("admin course show", ["--include-users", "--include-assignments", course_id]) self.assertEqual(result.exit_code, 0) for student_id, student in zip(student_ids, students): self.register_team([student], student_id, "pa1", course_id) for student_id, student in zip(student_ids, students): result = student.run("student team list") self.assertEqual(result.exit_code, 0) self.assertIn(student_id, result.output) result = student.run("student team show", [student_id]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor team list") self.assertEqual(result.exit_code, 0) for student_id in student_ids: result = instructors[0].run("instructor team show", [student_id]) self.assertEqual(result.exit_code, 0) student_git_paths, student_git_repos, team_commits = self.create_team_repos(admin, course_id, student_ids, students_team) for student_id, student in zip(student_ids, students): result = student.run("student assignment submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) result = student.run("student team show", [student_id]) self.assertEqual(result.exit_code, 0) # Let the deadline "pass" new_now = get_datetime_now_utc() + timedelta(hours=2) set_testing_now(new_now) print() print("~~~ Time has moved 'forward' by two hours ~~~") print() # The "master instructor" creates the grading repos result = instructors[0].run("instructor grading list-submissions", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading create-grading-repos", ["--master", "pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading assign-grader", ["pa1", "student1", "grader1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading assign-grader", ["pa1", "student2", "grader1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading assign-grader", ["pa1", "student3", "grader2"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading assign-grader", ["pa1", "student4", "grader2"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading list-grader-assignments", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading show-grading-status", ["--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading push-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) # The non-master instructor downloads the grading repos result = instructors[1].run("instructor grading create-grading-repos", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[1].run("instructor grading show-grading-status", ["--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) # Grader 1 pulls their grading result = graders[0].run("grader pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) student1_grading_repo_path = "chisubmit-test/repositories/%s/%s/%s" % (course_id, "pa1", "student1") student2_grading_repo_path = "chisubmit-test/repositories/%s/%s/%s" % (course_id, "pa1", "student2") student_git_repos[0], student_git_paths[0] = graders[0].get_local_git_repository(student1_grading_repo_path) student_git_repos[1], student_git_paths[1] = graders[0].get_local_git_repository(student2_grading_repo_path) student1_rubric_path = "%s/pa1.rubric.txt" % student_git_paths[0] student2_rubric_path = "%s/pa1.rubric.txt" % student_git_paths[1] # Grader 1 grades student1 and pushes the grading. student1_rubric = """Points: - The PA1 Tests: Points Possible: 50 Points Obtained: 45 - The PA1 Design: Points Possible: 50 Points Obtained: 30 Penalties: Used O(n^156) algorithm: -10 Submitted code in a Word document: -30 Bonuses: Worked alone: 15 Total Points: 50 / 100 Comments: > None""" with open(student1_rubric_path, "w") as f: f.write(student1_rubric) result = graders[0].run("grader validate-rubrics", ["pa1"]) self.assertEqual(result.exit_code, 0) student_git_repos[0].index.add(["pa1.rubric.txt"]) student_git_repos[0].index.commit("Finished grading") result = graders[0].run("grader push-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) # The non-master instructor pulls the repos and generates a report result = instructors[1].run("instructor grading pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[1].run("instructor grading show-grading-status", ["--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) # Grader 1 grades student2 and pushes the grading. student2_rubric = """Points: - The PA1 Tests: Points Possible: 50 Points Obtained: 50 - The PA1 Design: Points Possible: 50 Points Obtained: 45 Total Points: 95 / 100 Comments: > Great job!""" with open(student2_rubric_path, "w") as f: f.write(student2_rubric) result = graders[0].run("grader validate-rubrics", ["pa1"]) self.assertEqual(result.exit_code, 0) student_git_repos[1].index.add(["pa1.rubric.txt"]) student_git_repos[1].index.commit("Finished grading") result = graders[0].run("grader push-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) # The non-master instructor pulls the repos and generates a report result = instructors[1].run("instructor grading pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[1].run("instructor grading show-grading-status", ["--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) # Grader 2 pulls their grading result = graders[1].run("grader pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) student3_grading_repo_path = "chisubmit-test/repositories/%s/%s/%s" % (course_id, "pa1", "student3") student4_grading_repo_path = "chisubmit-test/repositories/%s/%s/%s" % (course_id, "pa1", "student4") student_git_repos[2], student_git_paths[2] = graders[1].get_local_git_repository(student3_grading_repo_path) student_git_repos[3], student_git_paths[3] = graders[1].get_local_git_repository(student4_grading_repo_path) student3_rubric_path = "%s/pa1.rubric.txt" % student_git_paths[2] student4_rubric_path = "%s/pa1.rubric.txt" % student_git_paths[3] # Grader 2 adds the empty rubrics (which should be generated by pull-grading) result = graders[1].run("grader validate-rubrics", ["pa1"]) self.assertEqual(result.exit_code, 0) student_git_repos[2].index.add(["pa1.rubric.txt"]) student_git_repos[2].index.commit("Added rubric") student_git_repos[3].index.add(["pa1.rubric.txt"]) student_git_repos[3].index.commit("Added rubric") result = graders[1].run("grader push-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) # The non-master instructor pulls the repos and generates a report result = instructors[1].run("instructor grading pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[1].run("instructor grading show-grading-status", ["--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) # Grader 2 grades student3 but does only a partial grading of student4 student3_rubric = """Points: - The PA1 Tests: Points Possible: 50 Points Obtained: 20 - The PA1 Design: Points Possible: 50 Points Obtained: 15 Total Points: 35 / 100 Comments: > Needs improvement!""" with open(student3_rubric_path, "w") as f: f.write(student3_rubric) student4_rubric = """Points: - The PA1 Tests: Points Possible: 50 Points Obtained: 35 - The PA1 Design: Points Possible: 50 Points Obtained: Total Points: 35 / 100 Comments: > """ with open(student4_rubric_path, "w") as f: f.write(student4_rubric) result = graders[1].run("grader validate-rubrics", ["pa1"]) self.assertEqual(result.exit_code, 0) student_git_repos[2].index.add(["pa1.rubric.txt"]) student_git_repos[2].index.commit("Finished grading") student_git_repos[3].index.add(["pa1.rubric.txt"]) student_git_repos[3].index.commit("Grading in progress") result = graders[1].run("grader push-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) # The non-master instructor pulls the repos and generates a report result = instructors[1].run("instructor grading pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[1].run("instructor grading show-grading-status", ["--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) # Grader 2 finishes grading student4_rubric = """Points: - The PA1 Tests: Points Possible: 50 Points Obtained: 35 - The PA1 Design: Points Possible: 50 Points Obtained: 25 Total Points: 60 / 100 Comments: > """ with open(student4_rubric_path, "w") as f: f.write(student4_rubric) result = graders[1].run("grader validate-rubrics", ["pa1"]) self.assertEqual(result.exit_code, 0) student_git_repos[3].index.add(["pa1.rubric.txt"]) student_git_repos[3].index.commit("Finished grading") result = graders[1].run("grader push-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) # The non-master instructor pulls the repos and generates a report result = instructors[1].run("instructor grading pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[1].run("instructor grading show-grading-status", ["--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) # The master instructor pulls the repos and pushes them to the students result = instructors[0].run("instructor grading pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading show-grading-status", ["--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading collect-rubrics", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading show-grading-status", ["--use-stored-grades", "--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading list-grades") self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading push-grading", ["--to-students", "--yes", "pa1"]) self.assertEqual(result.exit_code, 0) for student_id, student in zip(student_ids, students): repo, path = student.get_local_git_repository(student_id) repo.remote("origin").pull("pa1-grading:pa1-grading") repo.heads["pa1-grading"].checkout() self.assertTrue(os.path.exists(path + "/pa1.rubric.txt"))
def test_complete_with_extensions_per_team(self, runner): course_id = u"cmsc40200" course_name = u"Foobarmentals of Foobar" admin_id = u"admin" instructor_ids = [u"instructor"] grader_ids= [u"grader"] student_ids = [u"student1", u"student2", u"student3", u"student4"] all_users = instructor_ids + grader_ids + student_ids admin, instructors, graders, students = self.create_clients(runner, admin_id, instructor_ids, grader_ids, student_ids, course_id, verbose = True) self.create_users(admin, all_users) self.create_course(admin, course_id, course_name) result = admin.run("admin course set-attribute %s default_extensions 2" % (course_id)) self.assertEqual(result.exit_code, 0) result = admin.run("admin course set-attribute %s extension_policy per-team" % (course_id)) self.assertEqual(result.exit_code, 0) self.add_users_to_course(admin, course_id, instructors, graders, students) teams = ["student1-student2", "student3-student4"] students_team = [students[0:2], students[2:4]] deadline = get_datetime_now_utc() - timedelta(hours=23) deadline = convert_datetime_to_local(deadline) deadline = deadline.replace(tzinfo=None).isoformat(sep=" ") result = instructors[0].run("instructor assignment add", ["pa1", "Programming Assignment 1", deadline]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor assignment set-attribute", ["pa1", "min_students", "2"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor assignment set-attribute", ["pa1", "max_students", "2"]) self.assertEqual(result.exit_code, 0) pa1_rubric = """Points: - The PA1 Tests: Points Possible: 50 Points Obtained: - The PA1 Design: Points Possible: 50 Points Obtained: Total Points: 0 / 100 """ with open("pa1.rubric.txt", "w") as f: f.write(pa1_rubric) result = instructors[0].run("instructor assignment add-rubric", ["pa1", "pa1.rubric.txt"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor assignment show-rubric", ["pa1"]) self.assertEqual(result.exit_code, 0) deadline = get_datetime_now_utc() - timedelta(hours=49) deadline = deadline.isoformat(sep=" ") result = instructors[0].run("instructor assignment add", ["pa2", "Programming Assignment 2", deadline]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor assignment set-attribute", ["pa2", "min_students", "2"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor assignment set-attribute", ["pa2", "max_students", "2"]) self.assertEqual(result.exit_code, 0) pa2_rubric = """Points: - The PA2 Tests: Points Possible: 50 Points Obtained: - The PA2 Design: Points Possible: 50 Points Obtained: Total Points: 0 / 100 """ with open("pa2.rubric.txt", "w") as f: f.write(pa2_rubric) result = instructors[0].run("instructor assignment add-rubric", ["pa2", "pa2.rubric.txt"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor assignment show-rubric", ["pa2"]) self.assertEqual(result.exit_code, 0) result = admin.run("admin course show", ["--include-users", "--include-assignments", course_id]) self.assertEqual(result.exit_code, 0) self.register_team(students_team[0], teams[0], "pa1", course_id) self.register_team(students_team[1], teams[1], "pa1", course_id) self.register_team(students_team[0], teams[0], "pa2", course_id) result = students_team[0][0].run("student team list") self.assertEqual(result.exit_code, 0) self.assertIn(teams[0], result.output) self.assertNotIn(teams[1], result.output) result = students_team[1][0].run("student team list") self.assertEqual(result.exit_code, 0) self.assertIn(teams[1], result.output) self.assertNotIn(teams[0], result.output) result = students_team[0][0].run("student team show", [teams[0]]) self.assertEqual(result.exit_code, 0) result = students_team[0][0].run("student team show", [teams[1]]) self.assertEqual(result.exit_code, CHISUBMIT_FAIL) result = students_team[1][0].run("student team show", [teams[1]]) self.assertEqual(result.exit_code, 0) result = students_team[1][0].run("student team show", [teams[0]]) self.assertEqual(result.exit_code, CHISUBMIT_FAIL) result = instructors[0].run("instructor team list") self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor team show", [teams[0]]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor team show", [teams[1]]) self.assertEqual(result.exit_code, 0) team_git_paths, team_git_repos, team_commits = self.create_team_repos(admin, course_id, teams, students_team) # Submit with just the right number result = students_team[0][0].run("student assignment submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) result = students_team[0][0].run("student team show", [teams[0]]) self.assertEqual(result.exit_code, 0) # Try submitting an already-submitted assignment, with the same # commit as before (without --commit-sha) result = students_team[0][0].run("student assignment submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_FAIL) # Try submitting an already-submitted assignment, with the same # commit as before (with --commit-sha) result = students_team[0][0].run("student assignment submit", ["pa1", "--yes", "--commit-sha", team_commits[0][1].hexsha]) self.assertEqual(result.exit_code, CHISUBMIT_FAIL) # Submit an already-submitted assignment result = students_team[0][0].run("student assignment submit", ["pa1", "--yes", "--commit-sha", team_commits[0][0].hexsha]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) result = students_team[0][0].run("student team show", [teams[0]]) self.assertEqual(result.exit_code, 0) # Try submitting for a project the team is not registered for result = students_team[1][0].run("student assignment submit", ["pa2", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_FAIL) result = students_team[1][0].run("student assignment submit", ["pa1", "--yes", "--commit-sha", team_commits[1][0].hexsha]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) result = students_team[1][0].run("student assignment submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) result = instructors[0].run("instructor grading list-submissions", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor team pull-repos", ["repos/all/"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor team pull-repos", ["--assignment", "pa1", "repos/pa1/"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor team pull-repos", ["--assignment", "pa1", "repos/ready/", "--only-ready-for-grading"]) self.assertEqual(result.exit_code, 0) # Let the deadline "pass" new_now = get_datetime_now_utc() + timedelta(hours=2) set_testing_now(new_now) print() print("~~~ Time has moved 'forward' by two hours ~~~") print() result = instructors[0].run("instructor grading list-submissions", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor team pull-repos", ["repos/all/"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor team pull-repos", ["--assignment", "pa1", "repos/pa1/"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor team pull-repos", ["--assignment", "pa1", "repos/ready/", "--only-ready-for-grading"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading create-grading-repos", ["--master", "pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading assign-graders", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading list-grader-assignments", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading push-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) result = graders[0].run("grader pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) team1_grading_repo_path = "chisubmit-test/repositories/%s/%s/%s" % (course_id, "pa1", teams[0]) team2_grading_repo_path = "chisubmit-test/repositories/%s/%s/%s" % (course_id, "pa1", teams[1]) team_git_repos[0], team_git_paths[0] = graders[0].get_local_git_repository(team1_grading_repo_path) team_git_repos[1], team_git_paths[1] = graders[0].get_local_git_repository(team2_grading_repo_path) team1_rubric_path = "%s/pa1.rubric.txt" % team_git_paths[0] team2_rubric_path = "%s/pa1.rubric.txt" % team_git_paths[1] team1_rubric = """Points: - The PA1 Tests: Points Possible: 50 Points Obtained: 45 - The PA1 Design: Points Possible: 50 Points Obtained: 30 Penalties: Used O(n^156) algorithm: -10 Submitted code in a Word document: -30 Bonuses: Worked alone: 15 Total Points: 50 / 100 Comments: > None""" with open(team1_rubric_path, "w") as f: f.write(team1_rubric) result = graders[0].run("grader validate-rubrics", ["pa1", "--only", teams[0]]) self.assertEqual(result.exit_code, 0) team_git_repos[0].index.add(["pa1.rubric.txt"]) team_git_repos[0].index.commit("Finished grading") with open("%s/bar" % team_git_paths[1], "a") as f: f.write("Great job!\n") team2_rubric = """Points: - The PA1 Tests: Points Possible: 50 Points Obtained: 50 - The PA1 Design: Points Possible: 50 Points Obtained: 45 Total Points: 95 / 100 Comments: > Great job!""" with open(team2_rubric_path, "w") as f: f.write(team2_rubric) result = graders[0].run("grader validate-rubrics", ["pa1", "--only", teams[1]]) self.assertEqual(result.exit_code, 0) team_git_repos[1].index.add(["pa1.rubric.txt"]) team_git_repos[1].index.add(["bar"]) team_git_repos[1].index.commit("Finished grading") result = graders[0].run("grader validate-rubrics", ["pa1"]) self.assertEqual(result.exit_code, 0) result = graders[0].run("grader push-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) result = graders[0].run("instructor grading validate-rubrics", ["pa1", "--only", teams[0]]) self.assertEqual(result.exit_code, 0) result = graders[0].run("instructor grading validate-rubrics", ["pa1", "--only", teams[1]]) self.assertEqual(result.exit_code, 0) result = graders[0].run("instructor grading validate-rubrics", ["pa1", "--grader", "grader"]) self.assertEqual(result.exit_code, 0) result = graders[0].run("instructor grading validate-rubrics", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading show-grading-status", ["--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading collect-rubrics", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading show-grading-status", ["--use-stored-grades", "--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading list-grades") self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading push-grading", ["--to-students", "--yes", "pa1"]) self.assertEqual(result.exit_code, 0) team_git_repos[0], team_git_paths[0] = students_team[0][0].get_local_git_repository(teams[0]) team_git_repos[0].remote("origin").pull("pa1-grading:pa1-grading") team_git_repos[0].heads["pa1-grading"].checkout() self.assertTrue(os.path.exists(team_git_paths[0] + "/pa1.rubric.txt")) team_git_repos[1], team_git_paths[1] = students_team[1][0].get_local_git_repository(teams[1]) team_git_repos[1].remote("origin").pull("pa1-grading:pa1-grading") team_git_repos[1].heads["pa1-grading"].checkout() self.assertTrue(os.path.exists(team_git_paths[0] + "/pa1.rubric.txt")) self.assertIn("Great job!", open(team_git_paths[1]+"/bar").read())
def test_complete_with_extensions_per_team(self, runner): course_id = u"cmsc40200" course_name = u"Foobarmentals of Foobar" admin_id = u"admin" instructor_ids = [u"instructor"] grader_ids = [u"grader"] student_ids = [u"student1", u"student2", u"student3", u"student4"] all_users = instructor_ids + grader_ids + student_ids admin, instructors, graders, students = self.create_clients( runner, course_id, admin_id, instructor_ids, grader_ids, student_ids) self.create_users(admin, all_users) self.create_course(admin, course_id, course_name) result = admin.run("admin course set-option %s default-extensions 2" % (course_id)) self.assertEquals(result.exit_code, 0) result = admin.run( "admin course set-option %s extension-policy per_team" % (course_id)) self.assertEquals(result.exit_code, 0) self.add_users_to_course(admin, course_id, instructors, graders, students) teams = ["the-flaming-foobars", "the-magnificent-mallocs"] students_team = [students[0:2], students[2:4]] deadline = get_datetime_now_utc() - timedelta(hours=23) deadline = convert_datetime_to_local(deadline) deadline = deadline.replace(tzinfo=None).isoformat(sep=" ") result = instructors[0].run( "instructor assignment add", ["pa1", "Programming Assignment 1", deadline]) self.assertEquals(result.exit_code, 0) result = instructors[0].run( "instructor assignment add-grade-component", ["pa1", "tests", "The PA1 Tests", "50"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run( "instructor assignment add-grade-component", ["pa1", "design", "The PA1 Design", "50"]) self.assertEquals(result.exit_code, 0) deadline = get_datetime_now_utc() - timedelta(hours=49) deadline = deadline.isoformat(sep=" ") result = instructors[0].run( "instructor assignment add", ["pa2", "Programming Assignment 2", deadline]) self.assertEquals(result.exit_code, 0) result = instructors[0].run( "instructor assignment add-grade-component", ["pa2", "tests", "The PA2 Tests", "50"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run( "instructor assignment add-grade-component", ["pa2", "design", "The PA2 Design", "50"]) self.assertEquals(result.exit_code, 0) result = admin.run( "admin course show", ["--include-users", "--include-assignments", course_id]) self.assertEquals(result.exit_code, 0) self.register_team(students_team[0], teams[0], "pa1", course_id) self.register_team(students_team[1], teams[1], "pa1", course_id) self.register_team(students_team[0], teams[0], "pa2", course_id) result = students_team[0][0].run("student team list") self.assertEquals(result.exit_code, 0) self.assertIn(teams[0], result.output) self.assertNotIn(teams[1], result.output) result = students_team[1][0].run("student team list") self.assertEquals(result.exit_code, 0) self.assertIn(teams[1], result.output) self.assertNotIn(teams[0], result.output) result = students_team[0][0].run("student team show", [teams[1]]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) result = students_team[1][0].run("student team show", [teams[0]]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) result = instructors[0].run("instructor team set-attribute", [teams[0], "alias", "foobar " + teams[0]]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor team set-attribute", [teams[1], "alias", "foobar " + teams[1]]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor team list") self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor team show", [teams[0]]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor team show", [teams[1]]) self.assertEquals(result.exit_code, 0) team_git_paths, team_git_repos, team_commits = self.create_team_repos( admin, course_id, teams, students_team) # Try to submit without enough extensions result = students_team[0][0].run("student assignment submit", [ teams[0], "pa1", team_commits[0][0].hexsha, "--extensions", "0", "--yes" ]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) # Try to submit with too many extensions result = students_team[0][0].run("student assignment submit", [ teams[0], "pa1", team_commits[0][0].hexsha, "--extensions", "2", "--yes" ]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) # Submit with just the right number result = students_team[0][0].run("student assignment submit", [ teams[0], "pa1", team_commits[0][0].hexsha, "--extensions", "1", "--yes" ]) self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS) result = students_team[0][0].run("student team show", [teams[0]]) self.assertEquals(result.exit_code, 0) # Try submitting an already-submitted assignment result = students_team[0][0].run("student assignment submit", [ teams[0], "pa1", team_commits[0][1].hexsha, "--extensions", "1", "--yes" ]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) # Try submitting an already-submitted assignment, with the same # commit as before result = students_team[0][0].run("student assignment submit", [ teams[0], "pa1", team_commits[0][0].hexsha, "--extensions", "1", "--yes", "--force" ]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) # Submit an already-submitted assignment result = students_team[0][0].run("student assignment submit", [ teams[0], "pa1", team_commits[0][1].hexsha, "--extensions", "1", "--yes", "--force" ]) self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS) result = students_team[0][0].run("student team show", [teams[0]]) self.assertEquals(result.exit_code, 0) # Try requesting more extensions than the team has result = students_team[0][0].run("student assignment submit", [ teams[0], "pa2", team_commits[0][1].hexsha, "--extensions", "3", "--yes" ]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) # Try submitting for a project the team is not registered for result = students_team[1][0].run("student assignment submit", [ teams[1], "pa2", team_commits[1][1].hexsha, "--extensions", "0", "--yes" ]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) result = students_team[1][0].run("student assignment submit", [ teams[1], "pa1", team_commits[1][1].hexsha, "--extensions", "1", "--yes" ]) self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS) result = instructors[0].run("instructor grading list-submissions", ["pa1"]) self.assertEquals(result.exit_code, 0) # Let the deadline "pass" new_now = get_datetime_now_utc() + timedelta(hours=2) set_testing_now(new_now) print print "~~~ Time has moved 'forward' by two hours ~~~" print result = instructors[0].run("instructor grading list-submissions", ["pa1"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading create-grading-repos", ["pa1"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run( "instructor grading create-grading-branches", ["pa1"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading set-grade", [teams[0], "pa1", "tests", "100"]) self.assertEquals(result.exit_code, 1) result = instructors[0].run("instructor grading set-grade", [teams[0], "pa1", "tests", "40"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading set-grade", [teams[1], "pa1", "tests", "45"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading list-grades") self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading set-grade", [teams[0], "pa1", "tests", "50"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading list-grades") self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading add-rubrics", ["pa1", "--commit"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading assign-graders", ["pa1"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run( "instructor grading list-grader-assignments", ["pa1"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading push-grading-branches", ["--to-staging", "pa1"]) self.assertEquals(result.exit_code, 0) result = graders[0].run("grader create-local-grading-repos", [graders[0].user_id, "pa1"]) self.assertEquals(result.exit_code, 0) team1_grading_repo_path = ".chisubmit/repositories/%s/%s/%s" % ( course_id, "pa1", teams[0]) team2_grading_repo_path = ".chisubmit/repositories/%s/%s/%s" % ( course_id, "pa1", teams[1]) team_git_repos[0], team_git_paths[0] = graders[ 0].get_local_git_repository(team1_grading_repo_path) team_git_repos[1], team_git_paths[1] = graders[ 0].get_local_git_repository(team2_grading_repo_path) team1_rubric_path = "%s/pa1.rubric.txt" % team_git_paths[0] team2_rubric_path = "%s/pa1.rubric.txt" % team_git_paths[1] team1_rubric = """Points: The PA1 Tests: Points Possible: 50 Points Obtained: 45 The PA1 Design: Points Possible: 50 Points Obtained: 30 Penalties: Used O(n^156) algorithm: -10 Submitted code in a Word document: -30 Total Points: 35 / 100 Comments: > None""" with open(team1_rubric_path, "w") as f: f.write(team1_rubric) result = graders[0].run( "grader validate-rubrics", [graders[0].user_id, "pa1", "--only", teams[0]]) self.assertEquals(result.exit_code, 0) team_git_repos[0].index.add(["pa1.rubric.txt"]) team_git_repos[0].index.commit("Finished grading") with open("%s/bar" % team_git_paths[1], "a") as f: f.write("Great job!\n") team2_rubric = """Points: The PA1 Tests: Points Possible: 50 Points Obtained: 50 The PA1 Design: Points Possible: 50 Points Obtained: 45 Total Points: 95 / 100 Comments: > Great job!""" with open(team2_rubric_path, "w") as f: f.write(team2_rubric) result = graders[0].run( "grader validate-rubrics", [graders[0].user_id, "pa1", "--only", teams[1]]) self.assertEquals(result.exit_code, 0) team_git_repos[1].index.add(["pa1.rubric.txt"]) team_git_repos[1].index.add(["bar"]) team_git_repos[1].index.commit("Finished grading") result = graders[0].run("grader validate-rubrics", [graders[0].user_id, "pa1"]) self.assertEquals(result.exit_code, 0) result = graders[0].run("grader push-grading-branches", [graders[0].user_id, "pa1"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading pull-grading-branches", ["--from-staging", "pa1"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading collect-rubrics", ["pa1"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading list-grades") self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading push-grading-branches", ["--to-students", "pa1"]) self.assertEquals(result.exit_code, 0) team_git_repos[0], team_git_paths[0] = students_team[0][ 0].get_local_git_repository(teams[0]) team_git_repos[0].remote("origin").pull("pa1-grading:pa1-grading") team_git_repos[0].heads["pa1-grading"].checkout() self.assertTrue(os.path.exists(team_git_paths[0] + "/pa1.rubric.txt")) team_git_repos[1], team_git_paths[1] = students_team[1][ 0].get_local_git_repository(teams[1]) team_git_repos[1].remote("origin").pull("pa1-grading:pa1-grading") team_git_repos[1].heads["pa1-grading"].checkout() self.assertTrue(os.path.exists(team_git_paths[0] + "/pa1.rubric.txt")) self.assertIn("Great job!", open(team_git_paths[1] + "/bar").read())
def test_complete_with_extensions_per_team(self, runner): course_id = u"cmsc40200" course_name = u"Foobarmentals of Foobar" admin_id = u"admin" instructor_ids = [u"instructor"] grader_ids = [u"grader"] student_ids = [u"student1", u"student2", u"student3", u"student4"] all_users = instructor_ids + grader_ids + student_ids admin, instructors, graders, students = self.create_clients( runner, admin_id, instructor_ids, grader_ids, student_ids, course_id, verbose=True) self.create_users(admin, all_users) self.create_course(admin, course_id, course_name) result = admin.run( "admin course set-attribute %s default_extensions 2" % (course_id)) self.assertEqual(result.exit_code, 0) result = admin.run( "admin course set-attribute %s extension_policy per-team" % (course_id)) self.assertEqual(result.exit_code, 0) self.add_users_to_course(admin, course_id, instructors, graders, students) teams = ["student1-student2", "student3-student4"] students_team = [students[0:2], students[2:4]] deadline = get_datetime_now_utc() - timedelta(hours=23) deadline = convert_datetime_to_local(deadline) deadline = deadline.replace(tzinfo=None).isoformat(sep=" ") result = instructors[0].run( "instructor assignment add", ["pa1", "Programming Assignment 1", deadline]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor assignment set-attribute", ["pa1", "min_students", "2"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor assignment set-attribute", ["pa1", "max_students", "2"]) self.assertEqual(result.exit_code, 0) pa1_rubric = """Points: - The PA1 Tests: Points Possible: 50 Points Obtained: - The PA1 Design: Points Possible: 50 Points Obtained: Total Points: 0 / 100 """ with open("pa1.rubric.txt", "w") as f: f.write(pa1_rubric) result = instructors[0].run("instructor assignment add-rubric", ["pa1", "pa1.rubric.txt"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor assignment show-rubric", ["pa1"]) self.assertEqual(result.exit_code, 0) deadline = get_datetime_now_utc() - timedelta(hours=49) deadline = deadline.isoformat(sep=" ") result = instructors[0].run( "instructor assignment add", ["pa2", "Programming Assignment 2", deadline]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor assignment set-attribute", ["pa2", "min_students", "2"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor assignment set-attribute", ["pa2", "max_students", "2"]) self.assertEqual(result.exit_code, 0) pa2_rubric = """Points: - The PA2 Tests: Points Possible: 50 Points Obtained: - The PA2 Design: Points Possible: 50 Points Obtained: Total Points: 0 / 100 """ with open("pa2.rubric.txt", "w") as f: f.write(pa2_rubric) result = instructors[0].run("instructor assignment add-rubric", ["pa2", "pa2.rubric.txt"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor assignment show-rubric", ["pa2"]) self.assertEqual(result.exit_code, 0) result = admin.run( "admin course show", ["--include-users", "--include-assignments", course_id]) self.assertEqual(result.exit_code, 0) self.register_team(students_team[0], teams[0], "pa1", course_id) self.register_team(students_team[1], teams[1], "pa1", course_id) self.register_team(students_team[0], teams[0], "pa2", course_id) result = students_team[0][0].run("student team list") self.assertEqual(result.exit_code, 0) self.assertIn(teams[0], result.output) self.assertNotIn(teams[1], result.output) result = students_team[1][0].run("student team list") self.assertEqual(result.exit_code, 0) self.assertIn(teams[1], result.output) self.assertNotIn(teams[0], result.output) result = students_team[0][0].run("student team show", [teams[0]]) self.assertEqual(result.exit_code, 0) result = students_team[0][0].run("student team show", [teams[1]]) self.assertEqual(result.exit_code, CHISUBMIT_FAIL) result = students_team[1][0].run("student team show", [teams[1]]) self.assertEqual(result.exit_code, 0) result = students_team[1][0].run("student team show", [teams[0]]) self.assertEqual(result.exit_code, CHISUBMIT_FAIL) result = instructors[0].run("instructor team list") self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor team show", [teams[0]]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor team show", [teams[1]]) self.assertEqual(result.exit_code, 0) team_git_paths, team_git_repos, team_commits = self.create_team_repos( admin, course_id, teams, students_team) # Submit with just the right number result = students_team[0][0].run("student assignment submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) result = students_team[0][0].run("student team show", [teams[0]]) self.assertEqual(result.exit_code, 0) # Try submitting an already-submitted assignment, with the same # commit as before (without --commit-sha) result = students_team[0][0].run("student assignment submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_FAIL) # Try submitting an already-submitted assignment, with the same # commit as before (with --commit-sha) result = students_team[0][0].run( "student assignment submit", ["pa1", "--yes", "--commit-sha", team_commits[0][1].hexsha]) self.assertEqual(result.exit_code, CHISUBMIT_FAIL) # Submit an already-submitted assignment result = students_team[0][0].run( "student assignment submit", ["pa1", "--yes", "--commit-sha", team_commits[0][0].hexsha]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) result = students_team[0][0].run("student team show", [teams[0]]) self.assertEqual(result.exit_code, 0) # Try submitting for a project the team is not registered for result = students_team[1][0].run("student assignment submit", ["pa2", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_FAIL) result = students_team[1][0].run( "student assignment submit", ["pa1", "--yes", "--commit-sha", team_commits[1][0].hexsha]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) result = students_team[1][0].run("student assignment submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) result = instructors[0].run("instructor grading list-submissions", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor team pull-repos", ["repos/all/"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor team pull-repos", ["--assignment", "pa1", "repos/pa1/"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor team pull-repos", [ "--assignment", "pa1", "repos/ready/", "--only-ready-for-grading" ]) self.assertEqual(result.exit_code, 0) # Let the deadline "pass" new_now = get_datetime_now_utc() + timedelta(hours=2) set_testing_now(new_now) print() print("~~~ Time has moved 'forward' by two hours ~~~") print() result = instructors[0].run("instructor grading list-submissions", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor team pull-repos", ["repos/all/"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor team pull-repos", ["--assignment", "pa1", "repos/pa1/"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor team pull-repos", [ "--assignment", "pa1", "repos/ready/", "--only-ready-for-grading" ]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading create-grading-repos", ["--master", "pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading assign-graders", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run( "instructor grading list-grader-assignments", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading push-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) result = graders[0].run("grader pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) team1_grading_repo_path = "chisubmit-test/repositories/%s/%s/%s" % ( course_id, "pa1", teams[0]) team2_grading_repo_path = "chisubmit-test/repositories/%s/%s/%s" % ( course_id, "pa1", teams[1]) team_git_repos[0], team_git_paths[0] = graders[ 0].get_local_git_repository(team1_grading_repo_path) team_git_repos[1], team_git_paths[1] = graders[ 0].get_local_git_repository(team2_grading_repo_path) team1_rubric_path = "%s/pa1.rubric.txt" % team_git_paths[0] team2_rubric_path = "%s/pa1.rubric.txt" % team_git_paths[1] team1_rubric = """Points: - The PA1 Tests: Points Possible: 50 Points Obtained: 45 - The PA1 Design: Points Possible: 50 Points Obtained: 30 Penalties: Used O(n^156) algorithm: -10 Submitted code in a Word document: -30 Bonuses: Worked alone: 15 Total Points: 50 / 100 Comments: > None""" with open(team1_rubric_path, "w") as f: f.write(team1_rubric) result = graders[0].run("grader validate-rubrics", ["pa1", "--only", teams[0]]) self.assertEqual(result.exit_code, 0) team_git_repos[0].index.add(["pa1.rubric.txt"]) team_git_repos[0].index.commit("Finished grading") with open("%s/bar" % team_git_paths[1], "a") as f: f.write("Great job!\n") team2_rubric = """Points: - The PA1 Tests: Points Possible: 50 Points Obtained: 50 - The PA1 Design: Points Possible: 50 Points Obtained: 45 Total Points: 95 / 100 Comments: > Great job!""" with open(team2_rubric_path, "w") as f: f.write(team2_rubric) result = graders[0].run("grader validate-rubrics", ["pa1", "--only", teams[1]]) self.assertEqual(result.exit_code, 0) team_git_repos[1].index.add(["pa1.rubric.txt"]) team_git_repos[1].index.add(["bar"]) team_git_repos[1].index.commit("Finished grading") result = graders[0].run("grader validate-rubrics", ["pa1"]) self.assertEqual(result.exit_code, 0) result = graders[0].run("grader push-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading pull-grading", ["pa1"]) self.assertEqual(result.exit_code, 0) result = graders[0].run("instructor grading validate-rubrics", ["pa1", "--only", teams[0]]) self.assertEqual(result.exit_code, 0) result = graders[0].run("instructor grading validate-rubrics", ["pa1", "--only", teams[1]]) self.assertEqual(result.exit_code, 0) result = graders[0].run("instructor grading validate-rubrics", ["pa1", "--grader", "grader"]) self.assertEqual(result.exit_code, 0) result = graders[0].run("instructor grading validate-rubrics", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading show-grading-status", ["--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading collect-rubrics", ["pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run( "instructor grading show-grading-status", ["--use-stored-grades", "--by-grader", "pa1"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading list-grades") self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor grading push-grading", ["--to-students", "--yes", "pa1"]) self.assertEqual(result.exit_code, 0) team_git_repos[0], team_git_paths[0] = students_team[0][ 0].get_local_git_repository(teams[0]) team_git_repos[0].remote("origin").pull("pa1-grading:pa1-grading") team_git_repos[0].heads["pa1-grading"].checkout() self.assertTrue(os.path.exists(team_git_paths[0] + "/pa1.rubric.txt")) team_git_repos[1], team_git_paths[1] = students_team[1][ 0].get_local_git_repository(teams[1]) team_git_repos[1].remote("origin").pull("pa1-grading:pa1-grading") team_git_repos[1].heads["pa1-grading"].checkout() self.assertTrue(os.path.exists(team_git_paths[0] + "/pa1.rubric.txt")) self.assertIn("Great job!", open(team_git_paths[1] + "/bar").read())
def test_complete_with_extensions_per_team(self, runner): course_id = u"cmsc40200" course_name = u"Foobarmentals of Foobar" admin_id = u"admin" instructor_ids = [u"instructor"] grader_ids= [u"grader"] student_ids = [u"student1", u"student2", u"student3", u"student4"] all_users = instructor_ids + grader_ids + student_ids admin, instructors, graders, students = self.create_clients(runner, course_id, admin_id, instructor_ids, grader_ids, student_ids) self.create_users(admin, all_users) self.create_course(admin, course_id, course_name) result = admin.run("admin course set-option %s default-extensions 2" % (course_id)) self.assertEquals(result.exit_code, 0) result = admin.run("admin course set-option %s extension-policy per_team" % (course_id)) self.assertEquals(result.exit_code, 0) self.add_users_to_course(admin, course_id, instructors, graders, students) teams = ["the-flaming-foobars", "the-magnificent-mallocs"] students_team = [students[0:2], students[2:4]] deadline = get_datetime_now_utc() - timedelta(hours=23) deadline = convert_datetime_to_local(deadline) deadline = deadline.replace(tzinfo=None).isoformat(sep=" ") result = instructors[0].run("instructor assignment add", ["pa1", "Programming Assignment 1", deadline]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor assignment add-grade-component", ["pa1", "tests", "The PA1 Tests", "50"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor assignment add-grade-component", ["pa1", "design", "The PA1 Design", "50"]) self.assertEquals(result.exit_code, 0) deadline = get_datetime_now_utc() - timedelta(hours=49) deadline = deadline.isoformat(sep=" ") result = instructors[0].run("instructor assignment add", ["pa2", "Programming Assignment 2", deadline]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor assignment add-grade-component", ["pa2", "tests", "The PA2 Tests", "50"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor assignment add-grade-component", ["pa2", "design", "The PA2 Design", "50"]) self.assertEquals(result.exit_code, 0) result = admin.run("admin course show", ["--include-users", "--include-assignments", course_id]) self.assertEquals(result.exit_code, 0) self.register_team(students_team[0], teams[0], "pa1", course_id) self.register_team(students_team[1], teams[1], "pa1", course_id) self.register_team(students_team[0], teams[0], "pa2", course_id) result = students_team[0][0].run("student team list") self.assertEquals(result.exit_code, 0) self.assertIn(teams[0], result.output) self.assertNotIn(teams[1], result.output) result = students_team[1][0].run("student team list") self.assertEquals(result.exit_code, 0) self.assertIn(teams[1], result.output) self.assertNotIn(teams[0], result.output) result = students_team[0][0].run("student team show", [teams[1]]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) result = students_team[1][0].run("student team show", [teams[0]]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) result = instructors[0].run("instructor team set-attribute", [teams[0], "alias", "foobar "+teams[0]]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor team set-attribute", [teams[1], "alias", "foobar "+teams[1]]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor team list") self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor team show", [teams[0]]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor team show", [teams[1]]) self.assertEquals(result.exit_code, 0) team_git_paths, team_git_repos, team_commits = self.create_team_repos(admin, course_id, teams, students_team) # Try to submit without enough extensions result = students_team[0][0].run("student assignment submit", [teams[0], "pa1", team_commits[0][0].hexsha, "--extensions", "0", "--yes"]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) # Try to submit with too many extensions result = students_team[0][0].run("student assignment submit", [teams[0], "pa1", team_commits[0][0].hexsha, "--extensions", "2", "--yes"]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) # Submit with just the right number result = students_team[0][0].run("student assignment submit", [teams[0], "pa1", team_commits[0][0].hexsha, "--extensions", "1", "--yes"]) self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS) result = students_team[0][0].run("student team show", [teams[0]]) self.assertEquals(result.exit_code, 0) # Try submitting an already-submitted assignment result = students_team[0][0].run("student assignment submit", [teams[0], "pa1", team_commits[0][1].hexsha, "--extensions", "1", "--yes"]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) # Try submitting an already-submitted assignment, with the same # commit as before result = students_team[0][0].run("student assignment submit", [teams[0], "pa1", team_commits[0][0].hexsha, "--extensions", "1", "--yes", "--force"]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) # Submit an already-submitted assignment result = students_team[0][0].run("student assignment submit", [teams[0], "pa1", team_commits[0][1].hexsha, "--extensions", "1", "--yes", "--force"]) self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS) result = students_team[0][0].run("student team show", [teams[0]]) self.assertEquals(result.exit_code, 0) # Try requesting more extensions than the team has result = students_team[0][0].run("student assignment submit", [teams[0], "pa2", team_commits[0][1].hexsha, "--extensions", "3", "--yes"]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) # Try submitting for a project the team is not registered for result = students_team[1][0].run("student assignment submit", [teams[1], "pa2", team_commits[1][1].hexsha, "--extensions", "0", "--yes"]) self.assertEquals(result.exit_code, CHISUBMIT_FAIL) result = students_team[1][0].run("student assignment submit", [teams[1], "pa1", team_commits[1][1].hexsha, "--extensions", "1", "--yes"]) self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS) result = instructors[0].run("instructor grading list-submissions", ["pa1"]) self.assertEquals(result.exit_code, 0) # Let the deadline "pass" new_now = get_datetime_now_utc() + timedelta(hours=2) set_testing_now(new_now) print print "~~~ Time has moved 'forward' by two hours ~~~" print result = instructors[0].run("instructor grading list-submissions", ["pa1"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading create-grading-repos", ["pa1"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading create-grading-branches", ["pa1"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading set-grade", [teams[0], "pa1", "tests", "100"]) self.assertEquals(result.exit_code, 1) result = instructors[0].run("instructor grading set-grade", [teams[0], "pa1", "tests", "40"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading set-grade", [teams[1], "pa1", "tests", "45"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading list-grades") self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading set-grade", [teams[0], "pa1", "tests", "50"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading list-grades") self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading add-rubrics", ["pa1", "--commit"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading assign-graders", ["pa1"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading list-grader-assignments", ["pa1"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading push-grading-branches", ["--to-staging", "pa1"]) self.assertEquals(result.exit_code, 0) result = graders[0].run("grader create-local-grading-repos", [graders[0].user_id, "pa1"]) self.assertEquals(result.exit_code, 0) team1_grading_repo_path = ".chisubmit/repositories/%s/%s/%s" % (course_id, "pa1", teams[0]) team2_grading_repo_path = ".chisubmit/repositories/%s/%s/%s" % (course_id, "pa1", teams[1]) team_git_repos[0], team_git_paths[0] = graders[0].get_local_git_repository(team1_grading_repo_path) team_git_repos[1], team_git_paths[1] = graders[0].get_local_git_repository(team2_grading_repo_path) team1_rubric_path = "%s/pa1.rubric.txt" % team_git_paths[0] team2_rubric_path = "%s/pa1.rubric.txt" % team_git_paths[1] team1_rubric = """Points: The PA1 Tests: Points Possible: 50 Points Obtained: 45 The PA1 Design: Points Possible: 50 Points Obtained: 30 Penalties: Used O(n^156) algorithm: -10 Submitted code in a Word document: -30 Total Points: 35 / 100 Comments: > None""" with open(team1_rubric_path, "w") as f: f.write(team1_rubric) result = graders[0].run("grader validate-rubrics", [graders[0].user_id, "pa1", "--only", teams[0]]) self.assertEquals(result.exit_code, 0) team_git_repos[0].index.add(["pa1.rubric.txt"]) team_git_repos[0].index.commit("Finished grading") with open("%s/bar" % team_git_paths[1], "a") as f: f.write("Great job!\n") team2_rubric = """Points: The PA1 Tests: Points Possible: 50 Points Obtained: 50 The PA1 Design: Points Possible: 50 Points Obtained: 45 Total Points: 95 / 100 Comments: > Great job!""" with open(team2_rubric_path, "w") as f: f.write(team2_rubric) result = graders[0].run("grader validate-rubrics", [graders[0].user_id, "pa1", "--only", teams[1]]) self.assertEquals(result.exit_code, 0) team_git_repos[1].index.add(["pa1.rubric.txt"]) team_git_repos[1].index.add(["bar"]) team_git_repos[1].index.commit("Finished grading") result = graders[0].run("grader validate-rubrics", [graders[0].user_id, "pa1"]) self.assertEquals(result.exit_code, 0) result = graders[0].run("grader push-grading-branches", [graders[0].user_id, "pa1"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading pull-grading-branches", ["--from-staging", "pa1"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading collect-rubrics", ["pa1"]) self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading list-grades") self.assertEquals(result.exit_code, 0) result = instructors[0].run("instructor grading push-grading-branches", ["--to-students", "pa1"]) self.assertEquals(result.exit_code, 0) team_git_repos[0], team_git_paths[0] = students_team[0][0].get_local_git_repository(teams[0]) team_git_repos[0].remote("origin").pull("pa1-grading:pa1-grading") team_git_repos[0].heads["pa1-grading"].checkout() self.assertTrue(os.path.exists(team_git_paths[0] + "/pa1.rubric.txt")) team_git_repos[1], team_git_paths[1] = students_team[1][0].get_local_git_repository(teams[1]) team_git_repos[1].remote("origin").pull("pa1-grading:pa1-grading") team_git_repos[1].heads["pa1-grading"].checkout() self.assertTrue(os.path.exists(team_git_paths[0] + "/pa1.rubric.txt")) self.assertIn("Great job!", open(team_git_paths[1]+"/bar").read())
def test_complete_with_submission_grace_period(self, runner): course_id = u"cmsc40300" course_name = u"Foobarmentals of Foobar II" admin_id = u"admin" instructor_ids = [u"instructor"] grader_ids = [u"grader"] student_ids = [u"student1", u"student2", u"student3", u"student4"] all_users = instructor_ids + grader_ids + student_ids admin, instructors, graders, students = self.create_clients( runner, admin_id, instructor_ids, grader_ids, student_ids, course_id, verbose=True) self.create_users(admin, all_users) self.create_course(admin, course_id, course_name) course = Course.get_by_course_id(course_id) self.assertIsNotNone(course) self.assertEqual(course.name, course_name) result = admin.run( "admin course set-attribute %s default_extensions 2" % (course_id)) self.assertEqual(result.exit_code, 0) result = admin.run( "admin course set-attribute %s extension_policy per-student" % (course_id)) self.assertEqual(result.exit_code, 0) self.add_users_to_course(admin, course_id, instructors, graders, students) deadline = get_datetime_now_utc() - timedelta(minutes=5) deadline = deadline.isoformat(sep=" ") result = instructors[0].run( "instructor assignment add", ["pa1", "Programming Assignment 1", deadline]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor assignment set-attribute", ["pa1", "max_students", "2"]) self.assertEqual(result.exit_code, 0) result = instructors[0].run("instructor assignment set-attribute", ["pa1", "grace_period", "00:15"]) self.assertEqual(result.exit_code, 0) teams = [u"student1-student2", u"student3-student4"] students_team = [(students[0], students[1]), (students[2], students[3])] self.register_team(students_team[0], teams[0], "pa1", course_id) self.register_team(students_team[1], teams[1], "pa1", course_id) _, _, team_commits = self.create_team_repos(admin, course_id, teams[0:2], students_team[0:2]) # Team 0 submits during the grace period, and doesn't have to use an extension. result = students_team[0][0].run("student assignment submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) t = course.get_team(teams[0]) self.assertEqual(t.get_extensions_available(), 2) # Let the grace period "pass" new_now = get_datetime_now_utc() + timedelta(minutes=11) set_testing_now(new_now) print() print( "~~~ Time has moved 'forward' to one minute after the grace period hours ~~~" ) print() # Team 1 submits and has to use an extensions because the grace period is over result = students_team[1][0].run("student assignment submit", ["pa1", "--yes"]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS) t = course.get_team(teams[1]) self.assertEqual(t.get_extensions_available(), 1) for team, student_team in zip(teams, students_team): result = student_team[0].run("student team show", [team]) self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS)