Beispiel #1
0
 def is_ready_for_grading(self):
     if self.submitted_at is None:
         return False
     else:
         now = get_datetime_now_utc()
         deadline = self.assignment.deadline + timedelta(days=self.extensions_used)
         
         if now > deadline:
             return True
         else:
             return False
Beispiel #2
0
    def is_ready_for_grading(self):
        if self.submitted_at is None:
            return False
        else:
            now = get_datetime_now_utc()
            deadline = self.assignment.deadline + timedelta(
                days=self.extensions_used)

            if now > deadline:
                return True
            else:
                return False
Beispiel #3
0
def student_assignment_show_deadline(ctx, course, assignment_id, utc):
    assignment = course.get_assignment(assignment_id)
    if assignment is None:
        print("Assignment %s does not exist" % assignment_id)
        ctx.exit(CHISUBMIT_FAIL)

    now_utc = get_datetime_now_utc()
    now_local = convert_datetime_to_local(now_utc)

    deadline_utc = assignment.deadline
    deadline_local = convert_datetime_to_local(deadline_utc)

    print(assignment.name)
    print()
    if utc:
        print("      Now (Local): %s" % now_local.isoformat(" "))
        print(" Deadline (Local): %s" % deadline_local.isoformat(" "))
        print()
        print("        Now (UTC): %s" % now_utc.isoformat(" "))
        print("   Deadline (UTC): %s" % deadline_utc.isoformat(" "))
    else:
        print("      Now: %s" % now_local.isoformat(" "))
        print(" Deadline: %s" % deadline_local.isoformat(" "))

    print()

    extensions = compute_extensions_needed(now_utc, deadline_utc)

    if extensions == 0:
        diff = deadline_utc - now_utc
    else:
        diff = now_utc - deadline_utc

    days = diff.days
    hours = diff.seconds // 3600
    minutes = (diff.seconds // 60) % 60
    seconds = diff.seconds % 60

    if extensions == 0:
        print("The deadline has not yet passed")
        print("You have %i days, %i hours, %i minutes, %i seconds left" %
              (days, hours, minutes, seconds))
    else:
        print(
            "The deadline passed %i days, %i hours, %i minutes, %i seconds ago"
            % (days, hours, minutes, seconds))
        print(
            "If you submit your assignment now, you will need to use %i extensions"
            % extensions)

    return CHISUBMIT_SUCCESS
Beispiel #4
0
    def test_incorrect_insufficient_extensions_in_team(self):
        user = User.objects.get(username='******')
        self.client.force_authenticate(user=user)

        deadline = get_datetime_now_utc() - timedelta(hours=23 + 24 + 24)
        assignment_obj = Assignment.objects.get(assignment_id="pa1")
        assignment_obj.deadline = deadline
        assignment_obj.save()

        url = reverse('submit', args=["cmsc40100", "student1-student2", "pa1"])

        post_data = {
            "commit_sha": "COMMITSHATEST",
        }
        response = self.client.post(url, data=post_data)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
Beispiel #5
0
    def test_incorrect_insufficient_extensions_in_team(self):
        user = User.objects.get(username='******')
        self.client.force_authenticate(user=user)
        
        deadline = get_datetime_now_utc() - timedelta(hours=23 + 24 + 24)
        assignment_obj = Assignment.objects.get(assignment_id = "pa1")
        assignment_obj.deadline = deadline
        assignment_obj.save()

        url = reverse('submit', args=["cmsc40100", "student1-student2", "pa1"])
        
        post_data = {
                     "commit_sha": "COMMITSHATEST",
                    }
        response = self.client.post(url, data = post_data)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
Beispiel #6
0
def student_assignment_show_deadline(ctx, course, assignment_id, utc):
    assignment = course.get_assignment(assignment_id)
    if assignment is None:
        print("Assignment %s does not exist" % assignment_id)
        ctx.exit(CHISUBMIT_FAIL)

    now_utc = get_datetime_now_utc()
    now_local = convert_datetime_to_local(now_utc)

    deadline_utc = assignment.deadline
    deadline_local = convert_datetime_to_local(deadline_utc)

    print(assignment.name)
    print()
    if utc:
        print("      Now (Local): %s" % now_local.isoformat(" "))
        print(" Deadline (Local): %s" % deadline_local.isoformat(" "))
        print()
        print("        Now (UTC): %s" % now_utc.isoformat(" "))
        print("   Deadline (UTC): %s" % deadline_utc.isoformat(" "))
    else:
        print("      Now: %s" % now_local.isoformat(" "))
        print(" Deadline: %s" % deadline_local.isoformat(" "))

    print()

    extensions = compute_extensions_needed(now_utc, deadline_utc)

    if extensions == 0:
        diff = deadline_utc - now_utc
    else:
        diff = now_utc - deadline_utc

    days = diff.days
    hours = diff.seconds // 3600
    minutes = (diff.seconds//60)%60
    seconds = diff.seconds%60

    if extensions == 0:
        print("The deadline has not yet passed")
        print("You have %i days, %i hours, %i minutes, %i seconds left" % (days, hours, minutes, seconds))
    else:
        print("The deadline passed %i days, %i hours, %i minutes, %i seconds ago" % (days, hours, minutes, seconds))
        print("If you submit your assignment now, you will need to use %i extensions" % extensions)

    return CHISUBMIT_SUCCESS
Beispiel #7
0
    def test_correct_one_extension(self):
        user = User.objects.get(username='******')
        self.client.force_authenticate(user=user)

        deadline = get_datetime_now_utc() - timedelta(hours=23)
        assignment_obj = Assignment.objects.get(assignment_id="pa1")
        assignment_obj.deadline = deadline
        assignment_obj.save()

        url = reverse('submit', args=["cmsc40100", "student1-student2", "pa1"])

        post_data = {"commit_sha": "COMMITSHATEST", "extensions": 1}
        response = self.client.post(url, data=post_data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(response.data["in_grace_period"], False)
        self.assertEqual(response.data["submission"]["extensions_used"], 1)
        self.assertEqual(response.data["extensions_before"], 2)
        self.assertEqual(response.data["extensions_after"], 1)
Beispiel #8
0
 def has_assignment_ready_for_grading(self, assignment, when=None):
     ta = self.get_assignment(assignment.id)
     
     if ta is None:
         return False
     
     if ta.submitted_at is None:
         return False
     
     if when is None:
         when = get_datetime_now_utc()
         
     deadline = assignment.deadline + timedelta(days=ta.extensions_used)
     
     if when > deadline:
         return True
     else:
         return False
Beispiel #9
0
    def has_assignment_ready_for_grading(self, assignment, when=None):
        ta = self.get_assignment(assignment.id)

        if ta is None:
            return False

        if ta.submitted_at is None:
            return False

        if when is None:
            when = get_datetime_now_utc()

        deadline = assignment.deadline + timedelta(days=ta.extensions_used)

        if when > deadline:
            return True
        else:
            return False
Beispiel #10
0
    def test_correct_one_extension_grace_period(self):
        user = User.objects.get(username='******')
        self.client.force_authenticate(user=user)
        
        deadline = get_datetime_now_utc() - timedelta(hours=24, minutes=10)
        assignment_obj = Assignment.objects.get(assignment_id = "pa1")
        assignment_obj.deadline = deadline
        assignment_obj.grace_period = timedelta(minutes=15)        
        assignment_obj.save()

        url = reverse('submit', args=["cmsc40100", "student1-student2", "pa1"])
        
        post_data = {
                     "commit_sha": "COMMITSHATEST",
                    }
        response = self.client.post(url, data = post_data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(response.data["in_grace_period"], True)
        self.assertEqual(response.data["submission"]["extensions_used"], 1)
        self.assertEqual(response.data["extensions_before"], 2)
        self.assertEqual(response.data["extensions_after"], 1)
Beispiel #11
0
    def test_incorrect_insufficient_extensions_in_team_extensions_override(self):
        user = User.objects.get(username='******')
        self.client.force_authenticate(user=user)
        
        deadline = get_datetime_now_utc() - timedelta(hours=23 + 24 + 24)
        assignment_obj = Assignment.objects.get(assignment_id = "pa1")
        assignment_obj.deadline = deadline
        assignment_obj.save()

        url = reverse('submit', args=["cmsc40100", "student1-student2", "pa1"])
        
        post_data = {
                     "commit_sha": "COMMITSHATEST",
                     "extensions_override": 2            
                    }
        response = self.client.post(url, data = post_data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(response.data["in_grace_period"], False)
        self.assertEqual(response.data["submission"]["extensions_used"], 2)                           
        self.assertEqual(response.data["extensions_override"], 2)        
        self.assertEqual(response.data["extensions_before"], 2)
        self.assertEqual(response.data["extensions_after"], 0)
Beispiel #12
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())
    
    
        
Beispiel #13
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())
Beispiel #14
0
    def test_complete_with_registration_cancellation(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)

        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 registration, which they can do because they haven't submitted yet.
        result = students_team[0][0].run(
            "student assignment cancel-registration", ["pa1", "--yes"])
        self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS)

        # Team 0 tries to cancel their registration again, which doesn't work. There's nothing to cancel.
        result = students_team[0][0].run(
            "student assignment cancel-registration", ["pa1", "--yes"])
        self.assertEqual(result.exit_code, CHISUBMIT_FAIL)

        # Team 0 registers again
        result = students_team[0][0].run(
            "student assignment register",
            ["pa1", "--partner", students_team[0][1].user_id])
        self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS)

        # Team 1 submits.
        result = students_team[1][0].run("student assignment submit",
                                         ["pa1", "--yes"])
        self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS)

        # Team 1 tries to cancel their registration, which doesn't work. They have a submission.
        result = students_team[1][0].run(
            "student assignment cancel-registration", ["pa1", "--yes"])
        self.assertEqual(result.exit_code, CHISUBMIT_FAIL)

        # Team 1 cancels their submission
        result = students_team[1][0].run("student assignment cancel-submit",
                                         ["pa1", "--yes"])
        self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS)

        # Team 1 can now cancel their registration.
        result = students_team[1][0].run(
            "student assignment cancel-registration", ["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)
Beispiel #15
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())
    
    
        
Beispiel #16
0
    def test_complete_with_registration_cancellation(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)
            
        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 registration, which they can do because they haven't submitted yet. 
        result = students_team[0][0].run("student assignment cancel-registration", 
                                         ["pa1", "--yes"])        
        self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS)
        
        # Team 0 tries to cancel their registration again, which doesn't work. There's nothing to cancel.
        result = students_team[0][0].run("student assignment cancel-registration", 
                                         ["pa1", "--yes"])        
        self.assertEqual(result.exit_code, CHISUBMIT_FAIL)
        
        # Team 0 registers again     
        result = students_team[0][0].run("student assignment register", 
                                         ["pa1", "--partner", students_team[0][1].user_id])        
        self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS)
        
        # Team 1 submits.
        result = students_team[1][0].run("student assignment submit", 
                                         ["pa1", "--yes"])        
        self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS)

        # Team 1 tries to cancel their registration, which doesn't work. They have a submission.
        result = students_team[1][0].run("student assignment cancel-registration", 
                                         ["pa1", "--yes"])        
        self.assertEqual(result.exit_code, CHISUBMIT_FAIL)

        # Team 1 cancels their submission
        result = students_team[1][0].run("student assignment cancel-submit", 
                                         ["pa1", "--yes"])        
        self.assertEqual(result.exit_code, CHISUBMIT_SUCCESS)

        # Team 1 can now cancel their registration.
        result = students_team[1][0].run("student assignment cancel-registration", 
                                         ["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)
Beispiel #17
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())
Beispiel #18
0
def student_assignment_cancel_submit(ctx, course, team_id, assignment_id, yes):
    assignment = course.get_assignment(assignment_id)
    if assignment is None:
        print "Assignment %s does not exist" % assignment_id
        ctx.exit(CHISUBMIT_FAIL)
    
    team = course.get_team(team_id)
    if team is None:
        print "Team %s does not exist" % team_id
        ctx.exit(CHISUBMIT_FAIL)
        
    ta = team.get_assignment(assignment_id)
    if ta is None:
        print "Team %s is not registered for assignment %s" % (team_id, assignment_id)
        ctx.exit(CHISUBMIT_FAIL)
        
    if ta.submitted_at is None:
        print "Team %s has not made a submission for assignment %s," % (team_id, assignment_id)
        print "so there is nothing to cancel."
        ctx.exit(CHISUBMIT_FAIL)
        
    if ta.submitted_at is not None:
        now = get_datetime_now_utc()
        deadline = assignment.deadline + timedelta(days=ta.extensions_used)
        
        if now > deadline:
            print "You cannot cancel this submission."
            print "You made a submission before the deadline, and the deadline has passed."

            ctx.exit(CHISUBMIT_FAIL)        
            
    conn = create_connection(course, ctx.obj['config'])
    
    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)
        
    submission_commit = conn.get_commit(course, team, ta.commit_sha)
        
    print
    print "This is your existing submission for assignment %s:" % assignment.id 
    print
    if submission_commit is None:
        print "WARNING: Previously submitted commit '%s' is not in the repository!" % ta.commit_sha
    else:
        print_commit(submission_commit)
    print    

    print "Are you sure you want to cancel this submission? (y/n): ", 
    
    if not yes:
        yesno = raw_input()
    else:
        yesno = 'y'
        print 'y'
    
    if yesno in ('y', 'Y', 'yes', 'Yes', 'YES'):
        response = assignment.cancel(team_id)
        
        # TODO: Can't do this until GitLab supports updating tags
        #    
        # message = "Extensions: %i\n" % extensions_requested
        # if submission_tag is None:
        #     conn.create_submission_tag(course, team, tag_name, message, commit.sha)
        # else:
        #     conn.update_submission_tag(course, team, tag_name, message, commit.sha)
            
        print
        if response["success"]:
            print "Your submission has been cancelled."
        else:
            print "ERROR: Your submission was not cancelled."
Beispiel #19
0
    def test_complete_with_extensions_per_student(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 3" % (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(hours=23)
        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 set-attribute",
                                    ["pa1", "max_students", "2"])
        self.assertEquals(result.exit_code, 0)

        deadline = get_datetime_now_utc() - timedelta(hours=47)
        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 set-attribute",
                                    ["pa2", "max_students", "2"])
        self.assertEquals(result.exit_code, 0)

        deadline = get_datetime_now_utc() - timedelta(hours=47)
        deadline = deadline.isoformat(sep=" ")

        result = instructors[0].run(
            "instructor assignment add",
            ["pa3", "Programming Assignment 3", deadline])
        self.assertEquals(result.exit_code, 0)

        result = instructors[0].run("instructor assignment set-attribute",
                                    ["pa3", "max_students", "2"])
        self.assertEquals(result.exit_code, 0)

        deadline = get_datetime_now_utc() - timedelta(hours=23)
        deadline = deadline.replace(tzinfo=None).isoformat(sep=" ")

        result = instructors[0].run(
            "instructor assignment add",
            ["pa4", "Programming Assignment 4", deadline])
        self.assertEquals(result.exit_code, 0)

        result = instructors[0].run("instructor assignment set-attribute",
                                    ["pa4", "max_students", "2"])
        self.assertEquals(result.exit_code, 0)

        deadline = get_datetime_now_utc() + timedelta(hours=2)
        deadline = deadline.replace(tzinfo=None).isoformat(sep=" ")

        result = instructors[0].run(
            "instructor assignment add",
            ["pa5", "Programming Assignment 5", deadline])
        self.assertEquals(result.exit_code, 0)

        result = instructors[0].run("instructor assignment set-attribute",
                                    ["pa5", "max_students", "2"])
        self.assertEquals(result.exit_code, 0)

        teams = [
            u"student1-student2", u"student3-student4", u"student1-student3",
            u"student2-student4"
        ]

        students_team = [
            (students[0], students[1]), (students[2], students[3]),
            (students[0], students[2]), (students[1], students[3])
        ]

        self.register_team(students_team[0], teams[0], "pa1", course_id)
        self.register_team(students_team[1], teams[1], "pa2", course_id)

        team_git_paths, team_git_repos, team_commits = self.create_team_repos(
            admin, course_id, teams[0:2], students_team[0:2])

        self.register_team(students_team[2], teams[2], "pa3", course_id)
        self.register_team(students_team[2], teams[2], "pa4", course_id)
        self.register_team(students_team[2], teams[2], "pa5", course_id)
        self.register_team(students_team[3], teams[3], "pa3", course_id)
        self.register_team(students_team[3], teams[3], "pa4", course_id)
        self.register_team(students_team[3], teams[3], "pa5", course_id)

        x, y, z = self.create_team_repos(admin, course_id, teams[2:4],
                                         students_team[2:4])

        team_git_paths += x
        team_git_repos += y
        team_commits += z

        for s in students:
            result = s.run("student course show-extensions")
            self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        # Team 0 submits with one extension to pa1
        # Student 0 and 1 now have 2 extensions left each
        result = students_team[0][0].run("student assignment submit",
                                         ["pa1", "--yes"])
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        s1 = course.get_student(
            get_user_by_username(students_team[0][0].user_id))
        s2 = course.get_student(
            get_user_by_username(students_team[0][1].user_id))
        t = course.get_team(teams[0])

        self.assertEqual(t.get_extensions_available(), 2)
        self.assertEqual(s1.get_extensions_available(), 2)
        self.assertEqual(s2.get_extensions_available(), 2)

        for s in students:
            result = s.run("student course show-extensions")
            self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        # Team 1 submits with two extensions to pa2
        # Student 2 and 3 now have 1 extension left each
        result = students_team[1][0].run("student assignment submit",
                                         ["pa2", "--yes"])
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        s1 = course.get_student(
            get_user_by_username(students_team[1][0].user_id))
        s2 = course.get_student(
            get_user_by_username(students_team[1][1].user_id))
        t = course.get_team(teams[1])

        self.assertEqual(t.get_extensions_available(), 1)
        self.assertEqual(s1.get_extensions_available(), 1)
        self.assertEqual(s2.get_extensions_available(), 1)

        for s in students:
            result = s.run("student course show-extensions")
            self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        result = students_team[0][0].run("student team show", [teams[0]])
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        result = students_team[1][0].run("student team show", [teams[1]])
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        # Now we have two new teams:
        #
        # Team 2 with Student 0 and 2, with 2 and 1 extensions left respectively.
        # This team can only submit to projects requiring one extension
        #
        # Team 3 with Student 1 and 3, with 2 and 1 extensions left respectively.
        # This team can only submit to projects requiring one extension

        # Team 2 tries to submit to pa3, but they are denied because they would
        # need two extensions to submit.
        result = students_team[2][0].run("student assignment submit",
                                         ["pa3", "--yes"])
        self.assertEquals(result.exit_code, CHISUBMIT_FAIL)

        s1 = course.get_student(
            get_user_by_username(students_team[2][0].user_id))
        s2 = course.get_student(
            get_user_by_username(students_team[2][1].user_id))
        t = course.get_team(teams[2])

        self.assertEqual(t.get_extensions_available(), 1)
        self.assertEqual(s1.get_extensions_available(), 2)
        self.assertEqual(s2.get_extensions_available(), 1)

        # Team 2 tries submitting to pa4 and it goes through because it only
        # requires one extensions
        result = students_team[2][0].run("student assignment submit",
                                         ["pa4", "--yes"])
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        s1 = course.get_student(
            get_user_by_username(students_team[2][0].user_id))
        s2 = course.get_student(
            get_user_by_username(students_team[2][1].user_id))
        t = course.get_team(teams[2])

        self.assertEqual(t.get_extensions_available(), 0)
        self.assertEqual(s1.get_extensions_available(), 1)
        self.assertEqual(s2.get_extensions_available(), 0)

        for s in students:
            result = s.run("student course show-extensions")
            self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        # Team 2 tries submitting to pa5 with zero extensions and is accepted
        result = students_team[2][0].run("student assignment submit",
                                         ["pa5", "--yes"])
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        s1 = course.get_student(
            get_user_by_username(students_team[2][0].user_id))
        s2 = course.get_student(
            get_user_by_username(students_team[2][1].user_id))
        t = course.get_team(teams[2])

        self.assertEqual(t.get_extensions_available(), 0)
        self.assertEqual(s1.get_extensions_available(), 1)
        self.assertEqual(s2.get_extensions_available(), 0)

        for s in students:
            result = s.run("student course show-extensions")
            self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        # Team 3 tries submitting to pa5 and is accepted (doesn't require extensions)
        result = students_team[3][0].run("student assignment submit",
                                         ["pa5", "--yes"])
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        s1 = course.get_student(
            get_user_by_username(students_team[3][0].user_id))
        s2 = course.get_student(
            get_user_by_username(students_team[3][1].user_id))
        t = course.get_team(teams[3])

        self.assertEqual(t.get_extensions_available(), 1)
        self.assertEqual(s1.get_extensions_available(), 2)
        self.assertEqual(s2.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)

        for s in students:
            result = s.run("student course show-extensions")
            self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)
Beispiel #20
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)
Beispiel #21
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)
Beispiel #22
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)
Beispiel #23
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"))
Beispiel #24
0
def assignment_submit(course_id, assignment_id):
    now = get_datetime_now_utc()

    course = Course.query.filter_by(id=course_id).first()

    if course is None:
        abort(404)

    check_course_access_or_abort(g.user, course, 404, roles=["student"])

    assignment = Assignment.query.filter_by(id=assignment_id,
                                            course_id=course_id).first()
    # TODO 12DEC14: check permissions *before* 404
    if assignment is None:
        abort(404)

    if not g.user.is_student_in(course):
        error_msg = "You are not a student in course '%s'" % (course_id)
        return jsonify(errors={"register": error_msg}), 400

    if request.method == 'POST':
        input_data = request.get_json(force=True)
        if not isinstance(input_data, dict):
            return jsonify(error='Request data must be a JSON Object'), 400
        form = SubmitAssignmentInput.from_json(input_data)
        if not form.validate():
            return jsonify(errors=form.errors), 400

        team_id = form.team_id.data
        commit_sha = form.commit_sha.data
        extensions_requested = form.extensions.data
        dry_run = form.dry_run.data

        team = Team.query.filter_by(id=team_id).first()
        if team is None:
            abort(404)

        check_team_access_or_abort(g.user, team, 404)

        team_assignment = AssignmentsTeams.from_id(course.id, team.id,
                                                   assignment.id)
        if team_assignment is None:
            msg = "Team '%s' is not registered for assignment '%s'" % (
                team.id, assignment.id)
            return jsonify(errors={"team": msg}), 400

        if team_assignment.is_ready_for_grading():
            msg = "You cannot re-submit assignment %s." % (assignment.id)
            msg = " You made a submission before the deadline, and the deadline has passed."
            return jsonify(errors={"submit": msg}), 400

        response = {}

        response["dry_run"] = dry_run

        response["prior_submission"] = {}
        response["prior_submission"][
            "submitted_at"] = team_assignment.submitted_at
        response["prior_submission"]["commit_sha"] = team_assignment.commit_sha
        response["prior_submission"][
            "extensions_used"] = team_assignment.extensions_used

        response["submission"] = {}
        response["submission"]["course_id"] = course.id
        response["submission"]["assignment_id"] = assignment.id
        response["submission"]["submitted_at"] = now
        response["submission"]["deadline"] = assignment.deadline

        extensions_needed = compute_extensions_needed(
            submission_time=now, deadline=assignment.deadline)

        extension_policy = course.options.get("extension-policy", None)
        extensions_available = team.get_extensions_available(extension_policy)

        if extensions_available < 0:
            error_msg = "The number of available extensions is negative"
            return jsonify(errors={"fatal": error_msg}), 500

        response["submission"]["extensions_requested"] = extensions_requested
        response["submission"]["extensions_needed"] = extensions_needed

        response["team"] = {}
        response["team"]["id"] = team.id
        response["team"]["extensions_available_before"] = extensions_available

        if extensions_available + team_assignment.extensions_used >= extensions_needed and extensions_requested == extensions_needed:
            response["success"] = True

            # If the team has already used extensions for a previous submission,
            # they don't count towards the number of extensions needed
            # They are 'credited' to the available extensions
            extensions_available += team_assignment.extensions_used

            extensions_available -= extensions_needed
            if not dry_run:
                team_assignment.extensions_used = extensions_needed
                team_assignment.commit_sha = commit_sha
                team_assignment.submitted_at = now

                db.session.add(team_assignment)
                db.session.commit()
        else:
            response["success"] = False

        response["team"]["extensions_available"] = extensions_available

        return jsonify(response)
Beispiel #25
0
def student_assignment_cancel_submit(ctx, course, team_id, assignment_id, yes):
    assignment = course.get_assignment(assignment_id)
    if assignment is None:
        print "Assignment %s does not exist" % assignment_id
        ctx.exit(CHISUBMIT_FAIL)

    team = course.get_team(team_id)
    if team is None:
        print "Team %s does not exist" % team_id
        ctx.exit(CHISUBMIT_FAIL)

    ta = team.get_assignment(assignment_id)
    if ta is None:
        print "Team %s is not registered for assignment %s" % (team_id,
                                                               assignment_id)
        ctx.exit(CHISUBMIT_FAIL)

    if ta.submitted_at is None:
        print "Team %s has not made a submission for assignment %s," % (
            team_id, assignment_id)
        print "so there is nothing to cancel."
        ctx.exit(CHISUBMIT_FAIL)

    if ta.submitted_at is not None:
        now = get_datetime_now_utc()
        deadline = assignment.deadline + timedelta(days=ta.extensions_used)

        if now > deadline:
            print "You cannot cancel this submission."
            print "You made a submission before the deadline, and the deadline has passed."

            ctx.exit(CHISUBMIT_FAIL)

    conn = create_connection(course, ctx.obj['config'])

    if conn is None:
        print "Could not connect to git server."
        ctx.exit(CHISUBMIT_FAIL)

    submission_commit = conn.get_commit(course, team, ta.commit_sha)

    print
    print "This is your existing submission for assignment %s:" % assignment.id
    print
    if submission_commit is None:
        print "WARNING: Previously submitted commit '%s' is not in the repository!" % ta.commit_sha
    else:
        print_commit(submission_commit)
    print

    print "Are you sure you want to cancel this submission? (y/n): ",

    if not yes:
        yesno = raw_input()
    else:
        yesno = 'y'
        print 'y'

    if yesno in ('y', 'Y', 'yes', 'Yes', 'YES'):
        response = assignment.cancel(team_id)

        # TODO: Can't do this until GitLab supports updating tags
        #
        # message = "Extensions: %i\n" % extensions_requested
        # if submission_tag is None:
        #     conn.create_submission_tag(course, team, tag_name, message, commit.sha)
        # else:
        #     conn.update_submission_tag(course, team, tag_name, message, commit.sha)

        print
        if response["success"]:
            print "Your submission has been cancelled."
        else:
            print "ERROR: Your submission was not cancelled."
Beispiel #26
0
def assignment_submit(course_id, assignment_id):
    now = get_datetime_now_utc()
    
    course = Course.query.filter_by(id=course_id).first()
    
    if course is None:
        abort(404)
        
    check_course_access_or_abort(g.user, course, 404, roles=["student"])    
    
    assignment = Assignment.query.filter_by(id=assignment_id, course_id=course_id).first()
    # TODO 12DEC14: check permissions *before* 404
    if assignment is None:
        abort(404)

    if not g.user.is_student_in(course):
        error_msg = "You are not a student in course '%s'" % (course_id)
        return jsonify(errors={"register": error_msg}), 400

    if request.method == 'POST':       
        input_data = request.get_json(force=True)
        if not isinstance(input_data, dict):
            return jsonify(error='Request data must be a JSON Object'), 400
        form = SubmitAssignmentInput.from_json(input_data)
        if not form.validate():
            return jsonify(errors=form.errors), 400
        
        team_id = form.team_id.data
        commit_sha = form.commit_sha.data
        extensions_requested = form.extensions.data
        dry_run = form.dry_run.data
        
        team = Team.query.filter_by(id=team_id).first()
        if team is None:
            abort(404)

        check_team_access_or_abort(g.user, team, 404)
        
        team_assignment = AssignmentsTeams.from_id(course.id,team.id,assignment.id)
        if team_assignment is None:
            msg = "Team '%s' is not registered for assignment '%s'" % (team.id, assignment.id)
            return jsonify(errors={"team":msg}), 400
        
        if team_assignment.is_ready_for_grading():
            msg = "You cannot re-submit assignment %s." % (assignment.id)
            msg = " You made a submission before the deadline, and the deadline has passed."
            return jsonify(errors={"submit":msg}), 400
        
        response = {}

        response["dry_run"] = dry_run
        
        response["prior_submission"] = {}
        response["prior_submission"]["submitted_at"] = team_assignment.submitted_at
        response["prior_submission"]["commit_sha"] = team_assignment.commit_sha
        response["prior_submission"]["extensions_used"] = team_assignment.extensions_used
        
        response["submission"] = {}
        response["submission"]["course_id"] = course.id
        response["submission"]["assignment_id"] = assignment.id
        response["submission"]["submitted_at"] = now
        response["submission"]["deadline"] = assignment.deadline
        
        extensions_needed = compute_extensions_needed(submission_time = now, deadline = assignment.deadline)
                
        extension_policy = course.options.get("extension-policy", None)
        extensions_available = team.get_extensions_available(extension_policy)
                
        if extensions_available < 0:
            error_msg = "The number of available extensions is negative"
            return jsonify(errors={"fatal": error_msg}), 500            

        response["submission"]["extensions_requested"] = extensions_requested
        response["submission"]["extensions_needed"] = extensions_needed

        response["team"] = {}
        response["team"]["id"] = team.id
        response["team"]["extensions_available_before"] = extensions_available
        
        if extensions_available + team_assignment.extensions_used >= extensions_needed and extensions_requested == extensions_needed: 
            response["success"] = True
            
            # If the team has already used extensions for a previous submission,
            # they don't count towards the number of extensions needed
            # They are 'credited' to the available extensions
            extensions_available += team_assignment.extensions_used
            
            extensions_available -= extensions_needed
            if not dry_run:
                team_assignment.extensions_used = extensions_needed
                team_assignment.commit_sha = commit_sha
                team_assignment.submitted_at = now
                
                db.session.add(team_assignment)
                db.session.commit()
        else:
            response["success"] = False
                
        response["team"]["extensions_available"] = extensions_available
        
        return jsonify(response)
Beispiel #27
0
    def test_complete_with_extensions_per_student(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 3" % (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(hours=23)
        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 set-attribute", 
                                    ["pa1", "max_students", "2"])
        self.assertEquals(result.exit_code, 0)

        deadline = get_datetime_now_utc() - timedelta(hours=47)
        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 set-attribute", 
                                    ["pa2", "max_students", "2"])
        self.assertEquals(result.exit_code, 0)

        deadline = get_datetime_now_utc() - timedelta(hours=47)
        deadline = deadline.isoformat(sep=" ")

        result = instructors[0].run("instructor assignment add", 
                                    ["pa3", "Programming Assignment 3", deadline])
        self.assertEquals(result.exit_code, 0)

        result = instructors[0].run("instructor assignment set-attribute", 
                                    ["pa3", "max_students", "2"])
        self.assertEquals(result.exit_code, 0)

        deadline = get_datetime_now_utc() - timedelta(hours=23)
        deadline = deadline.replace(tzinfo=None).isoformat(sep=" ")        

        result = instructors[0].run("instructor assignment add", 
                                    ["pa4", "Programming Assignment 4", deadline])
        self.assertEquals(result.exit_code, 0)

        result = instructors[0].run("instructor assignment set-attribute", 
                                    ["pa4", "max_students", "2"])
        self.assertEquals(result.exit_code, 0)

        deadline = get_datetime_now_utc() + timedelta(hours=2)
        deadline = deadline.replace(tzinfo=None).isoformat(sep=" ")        

        result = instructors[0].run("instructor assignment add", 
                                    ["pa5", "Programming Assignment 5", deadline])
        self.assertEquals(result.exit_code, 0)

        result = instructors[0].run("instructor assignment set-attribute", 
                                    ["pa5", "max_students", "2"])
        self.assertEquals(result.exit_code, 0)
        
        
        teams = [u"student1-student2", 
                 u"student3-student4",
                 u"student1-student3",
                 u"student2-student4"]        

        students_team = [ (students[0], students[1]),
                          (students[2], students[3]),
                          (students[0], students[2]),
                          (students[1], students[3])]
        

        self.register_team(students_team[0], teams[0], "pa1", course_id)
        self.register_team(students_team[1], teams[1], "pa2", course_id)
        
        team_git_paths, team_git_repos, team_commits = self.create_team_repos(admin, course_id, teams[0:2], students_team[0:2])

        self.register_team(students_team[2], teams[2], "pa3", course_id)
        self.register_team(students_team[2], teams[2], "pa4", course_id)
        self.register_team(students_team[2], teams[2], "pa5", course_id)
        self.register_team(students_team[3], teams[3], "pa3", course_id)
        self.register_team(students_team[3], teams[3], "pa4", course_id)
        self.register_team(students_team[3], teams[3], "pa5", course_id)
        
        x, y, z = self.create_team_repos(admin, course_id, teams[2:4], students_team[2:4])
        
        team_git_paths += x
        team_git_repos += y
        team_commits += z
        
        for s in students:
            result = s.run("student course show-extensions")
            self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)        
        
        # Team 0 submits with one extension to pa1
        # Student 0 and 1 now have 2 extensions left each
        result = students_team[0][0].run("student assignment submit", 
                                         ["pa1", "--yes"])        
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)
        
        s1 = course.get_student(get_user_by_username(students_team[0][0].user_id))
        s2 = course.get_student(get_user_by_username(students_team[0][1].user_id))
        t = course.get_team(teams[0])
        
        self.assertEqual(t.get_extensions_available(), 2)
        self.assertEqual(s1.get_extensions_available(), 2)
        self.assertEqual(s2.get_extensions_available(), 2)

        for s in students:
            result = s.run("student course show-extensions")
            self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)
        
        # Team 1 submits with two extensions to pa2
        # Student 2 and 3 now have 1 extension left each
        result = students_team[1][0].run("student assignment submit", 
                                         ["pa2", "--yes"])        
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        s1 = course.get_student(get_user_by_username(students_team[1][0].user_id))
        s2 = course.get_student(get_user_by_username(students_team[1][1].user_id))
        t = course.get_team(teams[1])
        
        self.assertEqual(t.get_extensions_available(), 1)
        self.assertEqual(s1.get_extensions_available(), 1)
        self.assertEqual(s2.get_extensions_available(), 1)

        for s in students:
            result = s.run("student course show-extensions")
            self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        result = students_team[0][0].run("student team show", [teams[0]])
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        result = students_team[1][0].run("student team show", [teams[1]])
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)


        # Now we have two new teams:
        #
        # Team 2 with Student 0 and 2, with 2 and 1 extensions left respectively.
        # This team can only submit to projects requiring one extension
        # 
        # Team 3 with Student 1 and 3, with 2 and 1 extensions left respectively.
        # This team can only submit to projects requiring one extension

        # Team 2 tries to submit to pa3, but they are denied because they would 
        # need two extensions to submit.
        result = students_team[2][0].run("student assignment submit", 
                                         ["pa3", "--yes"])        
        self.assertEquals(result.exit_code, CHISUBMIT_FAIL)

        s1 = course.get_student(get_user_by_username(students_team[2][0].user_id))
        s2 = course.get_student(get_user_by_username(students_team[2][1].user_id))
        t = course.get_team(teams[2])
        
        self.assertEqual(t.get_extensions_available(), 1)
        self.assertEqual(s1.get_extensions_available(), 2)
        self.assertEqual(s2.get_extensions_available(), 1)


        # Team 2 tries submitting to pa4 and it goes through because it only
        # requires one extensions
        result = students_team[2][0].run("student assignment submit", 
                                         ["pa4", "--yes"])        
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        s1 = course.get_student(get_user_by_username(students_team[2][0].user_id))
        s2 = course.get_student(get_user_by_username(students_team[2][1].user_id))
        t = course.get_team(teams[2])
        
        self.assertEqual(t.get_extensions_available(), 0)
        self.assertEqual(s1.get_extensions_available(), 1)
        self.assertEqual(s2.get_extensions_available(), 0)

        for s in students:
            result = s.run("student course show-extensions")
            self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)                        

        # Team 2 tries submitting to pa5 with zero extensions and is accepted
        result = students_team[2][0].run("student assignment submit", 
                                         ["pa5", "--yes"])        
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)
                        
        s1 = course.get_student(get_user_by_username(students_team[2][0].user_id))
        s2 = course.get_student(get_user_by_username(students_team[2][1].user_id))
        t = course.get_team(teams[2])
        
        self.assertEqual(t.get_extensions_available(), 0)
        self.assertEqual(s1.get_extensions_available(), 1)
        self.assertEqual(s2.get_extensions_available(), 0)

        for s in students:
            result = s.run("student course show-extensions")
            self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)                        

        # Team 3 tries submitting to pa5 and is accepted (doesn't require extensions)
        result = students_team[3][0].run("student assignment submit", 
                                         ["pa5", "--yes"])        
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        s1 = course.get_student(get_user_by_username(students_team[3][0].user_id))
        s2 = course.get_student(get_user_by_username(students_team[3][1].user_id))
        t = course.get_team(teams[3])
        
        self.assertEqual(t.get_extensions_available(), 1)
        self.assertEqual(s1.get_extensions_available(), 2)
        self.assertEqual(s2.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)

        for s in students:
            result = s.run("student course show-extensions")
            self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)        
Beispiel #28
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)
Beispiel #29
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"))
Beispiel #30
0
    def test_complete_with_extensions_per_student(self, runner):
        from chisubmit.backend.webapp.api.teams.models import Team
        from chisubmit.backend.webapp.api.courses.models import CoursesStudents

        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.replace(tzinfo=None).isoformat(sep=" ")        

        result = instructors[0].run("instructor assignment add", 
                                    ["pa1", "Programming Assignment 1", deadline])
        self.assertEquals(result.exit_code, 0)

        deadline = get_datetime_now_utc() - timedelta(hours=47)
        deadline = deadline.isoformat(sep=" ")

        result = instructors[0].run("instructor assignment add", 
                                    ["pa2", "Programming Assignment 2", deadline])
        self.assertEquals(result.exit_code, 0)

        deadline = get_datetime_now_utc() - timedelta(hours=47)
        deadline = deadline.isoformat(sep=" ")

        result = instructors[0].run("instructor assignment add", 
                                    ["pa3", "Programming Assignment 3", deadline])
        self.assertEquals(result.exit_code, 0)

        deadline = get_datetime_now_utc() - timedelta(hours=23)
        deadline = deadline.replace(tzinfo=None).isoformat(sep=" ")        

        result = instructors[0].run("instructor assignment add", 
                                    ["pa4", "Programming Assignment 4", deadline])
        self.assertEquals(result.exit_code, 0)

        deadline = get_datetime_now_utc() + timedelta(hours=2)
        deadline = deadline.replace(tzinfo=None).isoformat(sep=" ")        

        result = instructors[0].run("instructor assignment add", 
                                    ["pa5", "Programming Assignment 5", deadline])
        self.assertEquals(result.exit_code, 0)
        
        
        teams = [u"the-flaming-foobars", 
                 u"the-magnificent-mallocs",
                 u"the-reticent-reallocs",
                 u"the-panicked-printfs"]        

        students_team = [ (students[0], students[1]),
                          (students[2], students[3]),
                          (students[0], students[2]),
                          (students[1], students[3])]
        

        self.register_team(students_team[0], teams[0], "pa1", course_id)
        self.register_team(students_team[1], teams[1], "pa2", course_id)
        
        team_git_paths, team_git_repos, team_commits = self.create_team_repos(admin, course_id, teams[0:2], students_team[0:2])

        self.register_team(students_team[2], teams[2], "pa3", course_id)
        self.register_team(students_team[2], teams[2], "pa4", course_id)
        self.register_team(students_team[2], teams[2], "pa5", course_id)
        self.register_team(students_team[3], teams[3], "pa3", course_id)
        self.register_team(students_team[3], teams[3], "pa4", course_id)
        self.register_team(students_team[3], teams[3], "pa5", course_id)
        
        x, y, z = self.create_team_repos(admin, course_id, teams[2:4], students_team[2:4])
        
        team_git_paths += x
        team_git_repos += y
        team_commits += z
        
        # Team 0 submits with one extension to pa1
        # Student 0 and 1 now have 2 extensions left each
        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)
        
        cs1 =  CoursesStudents.from_id(course_id, students_team[0][0].user_id)
        cs2 =  CoursesStudents.from_id(course_id, students_team[0][1].user_id)
        t = Team.from_id(course_id, teams[0])
        
        self.assertEqual(t.get_extensions_available("per_student"), 2)
        self.assertEqual(cs1.get_extensions_available(), 2)
        self.assertEqual(cs2.get_extensions_available(), 2)
        
        # Team 1 submits with two extensions to pa2
        # Student 2 and 3 now have 1 extension left each
        result = students_team[1][0].run("student assignment submit", 
                                         [teams[1], "pa2", team_commits[1][0].hexsha, 
                                          "--extensions", "2",
                                          "--yes"])
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        cs1 =  CoursesStudents.from_id(course_id, students_team[1][0].user_id)
        cs2 =  CoursesStudents.from_id(course_id, students_team[1][1].user_id)
        t = Team.from_id(course_id, teams[1])
        
        self.assertEqual(t.get_extensions_available("per_student"), 1)
        self.assertEqual(cs1.get_extensions_available(), 1)
        self.assertEqual(cs2.get_extensions_available(), 1)

        result = students_team[0][0].run("student team show", [teams[0]])
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)

        result = students_team[1][0].run("student team show", [teams[1]])
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)


        # Now we have two new teams:
        #
        # Team 2 with Student 0 and 2, with 2 and 1 extensions left respectively.
        # This team can only submit to projects requiring one extension
        # 
        # Team 3 with Student 1 and 3, with 2 and 1 extensions left respectively.
        # This team can only submit to projects requiring one extension

        # Team 2 tries to submit to pa3 with one extension (one less than needed)
        # and is denied
        result = students_team[2][0].run("student assignment submit", 
                                         [teams[2], "pa3", team_commits[2][0].hexsha, 
                                          "--extensions", "1",
                                          "--yes"])
        self.assertEquals(result.exit_code, CHISUBMIT_FAIL)

        cs1 =  CoursesStudents.from_id(course_id, students_team[2][0].user_id)
        cs2 =  CoursesStudents.from_id(course_id, students_team[2][1].user_id)
        t = Team.from_id(course_id, teams[2])
        
        self.assertEqual(t.get_extensions_available("per_student"), 1)
        self.assertEqual(cs1.get_extensions_available(), 2)
        self.assertEqual(cs2.get_extensions_available(), 1)


        # Team 2 tries to submit to pa3 with two extensions (the right number,
        # but not enough because one of the students only has one extension left)
        # and is denied
        result = students_team[2][0].run("student assignment submit", 
                                         [teams[2], "pa3", team_commits[2][0].hexsha, 
                                          "--extensions", "2",
                                          "--yes"])
        self.assertEquals(result.exit_code, CHISUBMIT_FAIL)

        cs1 =  CoursesStudents.from_id(course_id, students_team[2][0].user_id)
        cs2 =  CoursesStudents.from_id(course_id, students_team[2][1].user_id)
        t = Team.from_id(course_id, teams[2])
        
        self.assertEqual(t.get_extensions_available("per_student"), 1)
        self.assertEqual(cs1.get_extensions_available(), 2)
        self.assertEqual(cs2.get_extensions_available(), 1)


        # Team 2 tries submitting to pa4 with zero extensions (one less than needed)
        # and is denied
        result = students_team[2][0].run("student assignment submit", 
                                         [teams[2], "pa4", team_commits[2][1].hexsha, 
                                          "--extensions", "0",
                                          "--yes"])
        self.assertEquals(result.exit_code, CHISUBMIT_FAIL)

        cs1 =  CoursesStudents.from_id(course_id, students_team[2][0].user_id)
        cs2 =  CoursesStudents.from_id(course_id, students_team[2][1].user_id)
        t = Team.from_id(course_id, teams[2])
        
        self.assertEqual(t.get_extensions_available("per_student"), 1)
        self.assertEqual(cs1.get_extensions_available(), 2)
        self.assertEqual(cs2.get_extensions_available(), 1)

        # Team 2 tries submitting to pa4 with one extension (the correct number)
        # and it goes through
        result = students_team[2][0].run("student assignment submit", 
                                         [teams[2], "pa4", team_commits[2][1].hexsha, 
                                          "--extensions", "1",
                                          "--yes"])
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)
                        
        cs1 =  CoursesStudents.from_id(course_id, students_team[2][0].user_id)
        cs2 =  CoursesStudents.from_id(course_id, students_team[2][1].user_id)
        t = Team.from_id(course_id, teams[2])
        
        self.assertEqual(t.get_extensions_available("per_student"), 0)
        self.assertEqual(cs1.get_extensions_available(), 1)
        self.assertEqual(cs2.get_extensions_available(), 0)


        # Team 2 tries submitting to pa5 with zero extensions and is accepted
        result = students_team[2][0].run("student assignment submit", 
                                         [teams[2], "pa5", team_commits[2][1].hexsha, 
                                          "--extensions", "0",
                                          "--yes"])
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)
                        
        cs1 =  CoursesStudents.from_id(course_id, students_team[2][0].user_id)
        cs2 =  CoursesStudents.from_id(course_id, students_team[2][1].user_id)
        t = Team.from_id(course_id, teams[2])
        
        self.assertEqual(t.get_extensions_available("per_student"), 0)
        self.assertEqual(cs1.get_extensions_available(), 1)
        self.assertEqual(cs2.get_extensions_available(), 0)


        # Team 3 tries submitting to pa5 with zero extensions and is accepted
        result = students_team[3][0].run("student assignment submit", 
                                         [teams[3], "pa5", team_commits[3][1].hexsha, 
                                          "--extensions", "0",
                                          "--yes"])
        self.assertEquals(result.exit_code, CHISUBMIT_SUCCESS)
                        
        cs1 =  CoursesStudents.from_id(course_id, students_team[3][0].user_id)
        cs2 =  CoursesStudents.from_id(course_id, students_team[3][1].user_id)
        t = Team.from_id(course_id, teams[3])
        
        self.assertEqual(t.get_extensions_available("per_student"), 1)
        self.assertEqual(cs1.get_extensions_available(), 2)
        self.assertEqual(cs2.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)
Beispiel #31
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)