예제 #1
0
    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)
예제 #2
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)
예제 #3
0
    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"))
예제 #4
0
    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)
예제 #5
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, 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)
예제 #6
0
    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"))
예제 #7
0
    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())
    
    
        
예제 #8
0
    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())
예제 #9
0
    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())
예제 #10
0
    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())
    
    
        
예제 #11
0
    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)