Esempio n. 1
0
    def add_course(self, num_students=5, num_assignments=1, num_groups=0, num_answers='#', with_draft_student=False, with_comparisons=False):
        self.course = CourseFactory()
        self.instructor = UserFactory(system_role=SystemRole.instructor)
        self.enrol_user(self.instructor, self.course, CourseRole.instructor)
        self.ta = UserFactory(system_role=SystemRole.student)
        self.dropped_instructor = UserFactory(system_role=SystemRole.instructor)
        self.enrol_user(self.dropped_instructor, self.course, CourseRole.dropped)
        self.enrol_user(self.ta, self.course, CourseRole.teaching_assistant)

        self.add_students(num_students, num_groups)

        self.add_assignments(num_assignments)
        # create a shortcut for first assignment as it is frequently used
        self.assignment = self.assignments[0]

        self.add_answers(num_answers)

        if with_comparisons:
            self.add_comparisons()

        if with_draft_student:
            self.add_students(1)
            self.draft_student = self.students[-1]
            self.add_draft_answers([self.draft_student])

        for assignment in self.course.assignments:
            assignment.calculate_grades()
        self.course.calculate_grades()

        return self
Esempio n. 2
0
    def add_course(self,
                   num_students=5,
                   num_assignments=1,
                   num_additional_criteria=0,
                   num_groups=0,
                   num_answers='#',
                   with_comments=False,
                   with_draft_student=False,
                   with_comparisons=False,
                   with_self_eval=False):
        self.course = CourseFactory()
        self.instructor = UserFactory(system_role=SystemRole.instructor)
        self.enrol_user(self.instructor, self.course, CourseRole.instructor)
        self.ta = UserFactory(system_role=SystemRole.student)
        self.dropped_instructor = UserFactory(
            system_role=SystemRole.instructor)
        self.enrol_user(self.dropped_instructor, self.course,
                        CourseRole.dropped)
        self.enrol_user(self.ta, self.course, CourseRole.teaching_assistant)

        self.add_students(num_students, num_groups)

        self.add_assignments(num_assignments,
                             num_additional_criteria=num_additional_criteria,
                             with_self_eval=with_self_eval)
        # create a shortcut for first assignment as it is frequently used
        self.assignment = self.assignments[0]

        self.add_answers(num_answers, with_comments=with_comments)

        if with_comparisons:
            self.add_comparisons(with_comments=with_comments,
                                 with_self_eval=with_self_eval)

        if with_draft_student:
            self.add_students(1)
            self.draft_student = self.students[-1]
            self.add_draft_answers([self.draft_student])

        for assignment in self.course.assignments:
            assignment.calculate_grades()
        self.course.calculate_grades()

        return self
Esempio n. 3
0
class TestFixture:
    def __init__(self):
        self.default_criterion = Criterion.query.get(1)
        self.course = self.assignment = None
        self.instructor = self.ta = None
        self.students = []
        self.dropped_students = []
        self.assignments = []
        self.comparison_examples = []
        self.answers = []
        self.dropped_answers = []
        self.draft_answers = []
        self.groups = []
        self.unauthorized_instructor = UserFactory(system_role=SystemRole.instructor)
        self.unauthorized_student = UserFactory(system_role=SystemRole.student)
        self.dropped_instructor = UserFactory(system_role=SystemRole.instructor)
        self.draft_student = None
        db.session.commit()

    def add_course(self, num_students=5, num_assignments=1, num_groups=0, num_answers='#', with_draft_student=False, with_comparisons=False):
        self.course = CourseFactory()
        self.instructor = UserFactory(system_role=SystemRole.instructor)
        self.enrol_user(self.instructor, self.course, CourseRole.instructor)
        self.ta = UserFactory(system_role=SystemRole.student)
        self.dropped_instructor = UserFactory(system_role=SystemRole.instructor)
        self.enrol_user(self.dropped_instructor, self.course, CourseRole.dropped)
        self.enrol_user(self.ta, self.course, CourseRole.teaching_assistant)

        self.add_students(num_students, num_groups)

        self.add_assignments(num_assignments)
        # create a shortcut for first assignment as it is frequently used
        self.assignment = self.assignments[0]

        self.add_answers(num_answers)

        if with_comparisons:
            self.add_comparisons()

        if with_draft_student:
            self.add_students(1)
            self.draft_student = self.students[-1]
            self.add_draft_answers([self.draft_student])

        for assignment in self.course.assignments:
            assignment.calculate_grades()
        self.course.calculate_grades()

        return self

    def add_answers(self, num_answers):
        if num_answers == '#':
            num_answers = len(self.students) * len(self.assignments)
        if len(self.students) * len(self.assignments) < num_answers:
            raise ValueError(
                "Number of answers({}) must be equal or smaller than number of students({}) "
                "multiple by number of assignments({})".format(num_answers, len(self.students), len(self.assignments))
            )
        for assignment in self.assignments:
            for i in range(num_answers):
                answer = AnswerFactory(
                    assignment=assignment,
                    user=self.students[i % len(self.students)]
                )
                # half of the answers have scores
                if i < num_answers/2:
                    ScoreFactory(
                        assignment=assignment,
                        answer=answer,
                        criterion=assignment.criteria[0],
                        score=random.random() * 5
                    )
                self.answers.append(answer)

            for dropped_student in self.dropped_students:
                answer = AnswerFactory(
                    assignment=assignment,
                    user=dropped_student
                )
                self.dropped_answers.append(answer)
        db.session.commit()

        return self

    def add_comparisons(self):
        for assignment in self.assignments:
            for student in self.students:
                for i in range(assignment.total_comparisons_required):
                    comparisons = Comparison.create_new_comparison_set(assignment.id, student.id, False)
                    for comparison in comparisons:
                        comparison.completed = True
                        comparison.winner_id = min([comparisons[0].answer1_id, comparisons[0].answer2_id])
                        db.session.add(comparison)
        db.session.commit()

        return self

    def add_answer(self, assignment, user):
        answer = AnswerFactory(
            assignment=assignment,
            user=user
        )
        db.session.commit()
        self.answers.append(answer)
        return self

    def add_draft_answers(self, students):
        for student in students:
            for assignment in self.assignments:
                answer = AnswerFactory(
                    assignment=assignment,
                    user=student,
                    draft=True
                )
                db.session.commit()
                self.draft_answers.append(answer)

        return self

    def add_assignments(self, num_assignments=1, is_answer_period_end=False):
        for _ in range(num_assignments):
            answer_end = datetime.datetime.now() - datetime.timedelta(
                days=2) if is_answer_period_end else datetime.datetime.now() + datetime.timedelta(days=7)
            assignment = AssignmentFactory(course=self.course, answer_end=answer_end)
            AssignmentCriterionFactory(criterion=DefaultFixture.DEFAULT_CRITERION, assignment=assignment)
            disabled_criterion = CriterionFactory(user=self.instructor, default=False, active=False)
            AssignmentCriterionFactory(criterion=disabled_criterion, assignment=assignment, active=False)
            self.assignments.append(assignment)
        db.session.commit()

        return self

    def add_comparison_example(self, assignment, user):
        self.add_answer(assignment, user)
        self.add_answer(assignment, user)

        comparison_example = ComparisonExampleFactory(
            assignment=assignment,
            answer1=self.answers[-2],
            answer2=self.answers[-1]
        )
        self.comparison_examples.append(comparison_example)
        db.session.commit()
        return self

    def add_students(self, num_students, num_groups=0):
        students = []
        for _ in range(num_students):
            student = UserFactory(system_role=SystemRole.student)
            students.append(student)
        self.students += students

        if num_groups > 0:
            student_per_group = int(len(self.students) / num_groups) if num_groups is not 0 else 0
            for idx in range(num_groups):
                group_name = "Group" + str(idx)
                self.groups.append(group_name)
                # slice student list and enroll them into groups
                group_students = self.students[idx * student_per_group:min((idx + 1) * student_per_group, len(self.students))]
                for student in group_students:
                    self.enrol_user(student, self.course, CourseRole.student, group_name)
        else:
            for student in students:
                self.enrol_user(student, self.course, CourseRole.student)

        # add dropped student in group
        dropped_student = UserFactory(system_role=SystemRole.student)
        self.enrol_user(dropped_student, self.course, CourseRole.dropped, "Group Dropped")
        self.dropped_students.append(dropped_student)

        return self

    def enrol_user(self, user, course, type, group_name=None):
        user_courses = UserCourseFactory(course=course, user=user,
                                            course_role=type, group_name=group_name)
        db.session.commit()
        return user_courses

    def add_file(self, user, **kwargs):
        db_file = FileFactory(user=user, **kwargs)
        db.session.commit()
        return db_file
Esempio n. 4
0
    def add_course(self, num_students=5, num_assignments=1, num_group_assignments=0,
            num_additional_criteria=0, num_groups=0, num_answers='#', num_group_answers='#',
            with_comments=False, with_draft_student=False, with_comparisons=False, with_self_eval=False,
            num_non_comparable_ans=1):
        self.course = CourseFactory()
        self.instructor = UserFactory(system_role=SystemRole.instructor)
        self.enrol_user(self.instructor, self.course, CourseRole.instructor)
        self.ta = UserFactory(system_role=SystemRole.student)
        self.dropped_instructor = UserFactory(system_role=SystemRole.instructor)
        self.enrol_user(self.dropped_instructor, self.course, CourseRole.dropped)
        self.enrol_user(self.ta, self.course, CourseRole.teaching_assistant)

        self.add_students(num_students, num_groups)

        if num_assignments:
            self.add_assignments(
                num_assignments,
                num_additional_criteria=num_additional_criteria,
                with_self_eval=with_self_eval
            )

        if num_group_assignments:
            self.add_assignments(
                num_group_assignments,
                num_additional_criteria=num_additional_criteria,
                with_self_eval=with_self_eval,
                with_group_answers=True
            )

        # create a shortcut for first assignment as it is frequently used
        self.assignment = self.assignments[0]

        self.add_answers(num_answers, num_group_answers, with_comments=with_comments)
        self.add_non_comparable_answers(num_non_comparable_ans)

        if with_comparisons:
            self.add_comparisons(with_comments=with_comments, with_self_eval=with_self_eval)

        if with_draft_student:
            self.draft_student = UserFactory(system_role=SystemRole.student)
            db.session.add(self.draft_student)
            db.session.commit()
            self.draft_group = self.add_group(self.course)
            self.students.append(self.draft_student)
            self.enrol_user(self.draft_student, self.course, CourseRole.student, self.draft_group)
            for assignment in self.assignments:
                answer = AnswerFactory(
                    assignment=assignment,
                    draft=True,
                    submission_date=None
                )
                if assignment.enable_group_answers:
                    answer.group = self.draft_group
                    answer.user = None
                else:
                    answer.user = self.draft_student
                    answer.group = None
                self.draft_answers.append(answer)
            db.session.add_all(self.draft_answers)
            db.session.commit()

        for assignment in self.assignments:
            assignment.calculate_grades()
        self.course.calculate_grades()

        return self
Esempio n. 5
0
class TestFixture:
    def __init__(self):
        self.root_user = DefaultFixture.ROOT_USER
        self.default_criterion = DefaultFixture.DEFAULT_CRITERION
        self.course = self.assignment = None
        self.instructor = self.ta = None
        self.students = []
        self.dropped_students = []
        self.assignments = []
        self.comparison_examples = []
        self.answers = []
        self.dropped_answers = []
        self.removed_answers = []
        self.draft_answers = []
        self.non_comparable_answers =[]
        self.groups = []
        self.unauthorized_instructor = UserFactory(system_role=SystemRole.instructor)
        self.unauthorized_student = UserFactory(system_role=SystemRole.student)
        self.dropped_instructor = UserFactory(system_role=SystemRole.instructor)
        self.draft_student = None
        self.draft_group = None
        self.answer_comments = []
        self.comparisons = []
        self.self_evaluations = []
        db.session.commit()

    def add_course(self, num_students=5, num_assignments=1, num_group_assignments=0,
            num_additional_criteria=0, num_groups=0, num_answers='#', num_group_answers='#',
            with_comments=False, with_draft_student=False, with_comparisons=False, with_self_eval=False,
            num_non_comparable_ans=1):
        self.course = CourseFactory()
        self.instructor = UserFactory(system_role=SystemRole.instructor)
        self.enrol_user(self.instructor, self.course, CourseRole.instructor)
        self.ta = UserFactory(system_role=SystemRole.student)
        self.dropped_instructor = UserFactory(system_role=SystemRole.instructor)
        self.enrol_user(self.dropped_instructor, self.course, CourseRole.dropped)
        self.enrol_user(self.ta, self.course, CourseRole.teaching_assistant)

        self.add_students(num_students, num_groups)

        if num_assignments:
            self.add_assignments(
                num_assignments,
                num_additional_criteria=num_additional_criteria,
                with_self_eval=with_self_eval
            )

        if num_group_assignments:
            self.add_assignments(
                num_group_assignments,
                num_additional_criteria=num_additional_criteria,
                with_self_eval=with_self_eval,
                with_group_answers=True
            )

        # create a shortcut for first assignment as it is frequently used
        self.assignment = self.assignments[0]

        self.add_answers(num_answers, num_group_answers, with_comments=with_comments)
        self.add_non_comparable_answers(num_non_comparable_ans)

        if with_comparisons:
            self.add_comparisons(with_comments=with_comments, with_self_eval=with_self_eval)

        if with_draft_student:
            self.draft_student = UserFactory(system_role=SystemRole.student)
            db.session.add(self.draft_student)
            db.session.commit()
            self.draft_group = self.add_group(self.course)
            self.students.append(self.draft_student)
            self.enrol_user(self.draft_student, self.course, CourseRole.student, self.draft_group)
            for assignment in self.assignments:
                answer = AnswerFactory(
                    assignment=assignment,
                    draft=True,
                    submission_date=None
                )
                if assignment.enable_group_answers:
                    answer.group = self.draft_group
                    answer.user = None
                else:
                    answer.user = self.draft_student
                    answer.group = None
                self.draft_answers.append(answer)
            db.session.add_all(self.draft_answers)
            db.session.commit()

        for assignment in self.assignments:
            assignment.calculate_grades()
        self.course.calculate_grades()

        return self

    def add_answers(self, num_answers='#', num_group_answers='#', with_scores=True, with_comments=False):
        if num_answers == '#':
            num_answers = len(self.students)
        if num_group_answers == '#':
            num_group_answers = len(self.groups)

        for assignment in self.assignments:
            if not assignment.active:
                continue

            if assignment.enable_group_answers:
                # add a scored removed answer for every group
                # make sure system handles this properly
                for group in self.groups:
                    if not group.active:
                        continue

                    answer = AnswerFactory(
                        assignment=assignment,
                        group=group,
                        user=None,
                        active=False
                    )
                    AnswerScoreFactory(
                        assignment=assignment,
                        answer=answer,
                        score=random.random() * 5
                    )
                    for criterion in assignment.criteria:
                        AnswerCriterionScoreFactory(
                            assignment=assignment,
                            answer=answer,
                            criterion=criterion,
                            score=random.random() * 5
                        )
                    self.removed_answers.append(answer)

                for i in range(num_group_answers):
                    group = self.groups[i % len(self.groups)]
                    answer = AnswerFactory(
                        assignment=assignment,
                        group=group,
                        user=None,
                    )
                    # half of the answers have scores if with_scores is enabled
                    if with_scores and i < num_group_answers/2:
                        AnswerScoreFactory(
                            assignment=assignment,
                            answer=answer,
                            score=random.random() * 5
                        )
                        for criterion in assignment.criteria:
                            AnswerCriterionScoreFactory(
                                assignment=assignment,
                                answer=answer,
                                criterion=criterion,
                                score=random.random() * 5
                            )

                    if with_comments:
                        user_courses = UserCourse.query \
                            .filter_by(course_id=assignment.course_id, group_id=group.id) \
                            .all()
                        group_user_ids = [user_course.user_id for user_course in user_courses]
                        other_group_students = [s for s in self.students if not s.id in group_user_ids]
                        # half of the answers have a public comment
                        if i < num_group_answers/2:
                            random.shuffle(other_group_students)
                            answer_comment = AnswerCommentFactory(
                                user=other_group_students[0],
                                answer=answer,
                                comment_type=AnswerCommentType.public
                            )
                            self.answer_comments.append(answer_comment)

                        # half of the answers have a private comment
                        # (middle half so there is partial overlap with public comments)
                        if num_group_answers/4 < i and i < (num_group_answers * 3)/4:
                            random.shuffle(other_group_students)
                            answer_comment = AnswerCommentFactory(
                                user=other_group_students[0],
                                answer=answer,
                                comment_type=AnswerCommentType.private
                            )
                            self.answer_comments.append(answer_comment)

                    self.answers.append(answer)

                for dropped_student in self.dropped_students:
                    answer = AnswerFactory(
                        assignment=assignment,
                        user=dropped_student,
                        group=None,
                    )
                    self.dropped_answers.append(answer)
            else:
                # add a scored removed answer for every student
                # make sure system handles this properly
                for student in self.students:
                    answer = AnswerFactory(
                        assignment=assignment,
                        user=student,
                        group=None,
                        active=False,
                    )
                    AnswerScoreFactory(
                        assignment=assignment,
                        answer=answer,
                        score=random.random() * 5
                    )
                    for criterion in assignment.criteria:
                        AnswerCriterionScoreFactory(
                            assignment=assignment,
                            answer=answer,
                            criterion=criterion,
                            score=random.random() * 5
                        )
                    self.removed_answers.append(answer)

                for i in range(num_answers):
                    student = self.students[i % len(self.students)]
                    answer = AnswerFactory(
                        assignment=assignment,
                        user=student,
                        group=None
                    )
                    # half of the answers have scores if with_scores is enabled
                    if with_scores and i < num_answers/2:
                        AnswerScoreFactory(
                            assignment=assignment,
                            answer=answer,
                            score=random.random() * 5
                        )
                        for criterion in assignment.criteria:
                            AnswerCriterionScoreFactory(
                                assignment=assignment,
                                answer=answer,
                                criterion=criterion,
                                score=random.random() * 5
                            )

                    if with_comments:
                        other_students = [s for s in self.students if s.id != student.id]
                        # half of the answers has a public comment
                        if i < num_answers/2:
                            random.shuffle(other_students)
                            answer_comment = AnswerCommentFactory(
                                user=other_students[0],
                                answer=answer,
                                comment_type=AnswerCommentType.public
                            )
                            self.answer_comments.append(answer_comment)

                        # half of the answers has a private comment
                        # (middle half so there is partial overlap with public comments)
                        if num_answers/4 < i and i < (num_answers * 3)/4:
                            random.shuffle(other_students)
                            answer_comment = AnswerCommentFactory(
                                user=other_students[0],
                                answer=answer,
                                comment_type=AnswerCommentType.private
                            )
                            self.answer_comments.append(answer_comment)

                    self.answers.append(answer)

                for dropped_student in self.dropped_students:
                    answer = AnswerFactory(
                        assignment=assignment,
                        user=dropped_student,
                        group=None
                    )
                    self.dropped_answers.append(answer)

        db.session.commit()

        return self

    def add_non_comparable_answers(self, num_non_comparable_ans):
        for assignment in self.assignments:
            for i in range(num_non_comparable_ans):
                answer = AnswerFactory(
                    assignment=assignment,
                    user=self.instructor,
                    group=None,
                    comparable=False)
                self.answers.append(answer)
                self.non_comparable_answers.append(answer)
        db.session.commit()

    def add_comparisons(self, with_comments=False, with_self_eval=False):
        for assignment in self.assignments:
            for student in self.students:
                self.add_comparisons_for_user(assignment, student, with_comments=with_comments, with_self_eval=with_self_eval)
        return self

    def add_comparisons_for_user(self, assignment, student, with_comments=False, with_self_eval=False):
        answers = set()
        for i in range(assignment.total_comparisons_required):
            comparison = Comparison.create_new_comparison(assignment.id, student.id, False)
            comparison.completed = True
            comparison.winner = WinningAnswer.answer1 if comparison.answer1_id < comparison.answer2_id else WinningAnswer.answer2
            for comparison_criterion in comparison.comparison_criteria:
                comparison_criterion.winner = comparison.winner
            db.session.add(comparison)
            db.session.commit()
            self.comparisons.append(comparison)

        if with_comments:
            for answer in answers:
                answer_comment = AnswerCommentFactory(
                    user=student,
                    answer=answer,
                    comment_type=AnswerCommentType.evaluation
                )
                self.answer_comments.append(answer_comment)
            db.session.commit()

        if with_self_eval:
            student_answer = next(
                answer for answer in self.answers if answer.user_id == student.id and answer.assignment_id == assignment.id
            )
            if student_answer:
                self_evaluation = AnswerCommentFactory(
                    user=student,
                    answer=student_answer,
                    comment_type=AnswerCommentType.self_evaluation
                )
                self.self_evaluations.append(self_evaluation)
                db.session.commit()

        return self

    def add_answer(self, assignment, user, draft=False):
        answer = AnswerFactory(
            assignment=assignment,
            user=user,
            group=None,
            draft=draft
        )
        if (draft):
            answer.submission_date=None

        db.session.commit()
        self.answers.append(answer)
        return self

    def add_group_answer(self, assignment, group, draft=False):
        answer = AnswerFactory(
            assignment=assignment,
            group=group,
            user=None,
            draft=draft
        )
        if (draft):
            answer.submission_date=None

        db.session.commit()
        self.answers.append(answer)
        return self

    def add_assignments(self, num_assignments=1, num_group_assignments=0, num_additional_criteria=0,
                        is_answer_period_end=False,  with_self_eval=False, with_group_answers=False):
        for _ in range(num_assignments):
            answer_end = datetime.datetime.now() - datetime.timedelta(
                days=2) if is_answer_period_end else datetime.datetime.now() + datetime.timedelta(days=7)
            assignment = AssignmentFactory(course=self.course, answer_end=answer_end)

            if with_self_eval:
                assignment.enable_self_evaluation = True

            if with_group_answers:
                assignment.enable_group_answers = True

            # default criterion
            AssignmentCriterionFactory(criterion=DefaultFixture.DEFAULT_CRITERION, assignment=assignment, position=0)

            # disabled criterion
            disabled_criterion = CriterionFactory(user=self.instructor, default=False, active=False)
            AssignmentCriterionFactory(criterion=disabled_criterion, assignment=assignment, active=False, position=1)

            # additional criterion
            for i in range(num_additional_criteria):
                criterion = CriterionFactory(user=self.instructor, default=False)
                AssignmentCriterionFactory(criterion=criterion, assignment=assignment, position=i+2)

            db.session.commit()

            # need to reorder after update
            assignment.assignment_criteria.reorder()

            self.assignments.append(assignment)
        db.session.commit()

        return self

    def add_comparison_example(self, assignment, user):
        self.add_answer(assignment, user)
        self.add_answer(assignment, user)

        comparison_example = ComparisonExampleFactory(
            assignment=assignment,
            answer1=self.answers[-2],
            answer2=self.answers[-1]
        )
        self.comparison_examples.append(comparison_example)
        db.session.commit()
        return self

    def add_students(self, num_students, num_groups=0):
        students = []
        for _ in range(num_students):
            student = UserFactory(system_role=SystemRole.student)
            students.append(student)
        self.students += students

        if num_groups > 0:
            student_per_group = int(len(self.students) / num_groups) if num_groups is not 0 else 0
            for idx in range(num_groups):
                group = self.add_group(self.course)
                # slice student list and enroll them into groups
                group_students = students[idx * student_per_group:min((idx + 1) * student_per_group, len(students))]
                for student in group_students:
                    self.enrol_user(student, self.course, CourseRole.student, group)
        else:
            for student in students:
                self.enrol_user(student, self.course, CourseRole.student)

        # add dropped student in group
        dropped_student = UserFactory(system_role=SystemRole.student)
        dropped_group = self.add_group(self.course)
        self.enrol_user(dropped_student, self.course, CourseRole.dropped, dropped_group)
        self.dropped_students.append(dropped_student)

        return self

    def enrol_user(self, user, course, course_role, group=None):
        user_course = UserCourseFactory(
            course=course, user=user,
            course_role=course_role, group=group)
        db.session.commit()
        return user_course

    def change_user_group(self, course, user, group):
        user_course = UserCourse.query \
            .filter_by(
                course_id=course.id,
                user_id=user.id
            ) \
            .one()
        user_course.group = group
        db.session.commit()

        return user_course

    def add_file(self, user, **kwargs):
        db_file = FileFactory(user=user, **kwargs)
        db.session.commit()
        return db_file

    def add_group(self, course, **kwargs):
        group = GroupFactory(course=course, **kwargs)
        self.groups.append(group)
        db.session.commit()
        return group

    def _get_assignment_group_member_answers(self, assignment, group):
        user_ids = [uc.user_id for uc in group.user_courses if uc.course_role != CourseRole.dropped]
        return [a for a in self.answers if a.user_id in user_ids and a.assignment_id == assignment.id and a.active]

    def _get_assignment_group_answers(self, assignment, group):
        return [a for a in self.answers if a.group_id == group.id and a.assignment_id == assignment.id and a.active]

    def get_assignment_answers_for_group(self, assignment, group):
        return self._get_assignment_group_answers(assignment, group) + \
            self._get_assignment_group_member_answers(assignment, group)
Esempio n. 6
0
    def add_course(self,
                   num_students=5,
                   num_assignments=1,
                   num_group_assignments=0,
                   num_additional_criteria=0,
                   num_groups=0,
                   num_answers='#',
                   num_group_answers='#',
                   with_comments=False,
                   with_draft_student=False,
                   with_comparisons=False,
                   with_self_eval=False,
                   num_non_comparable_ans=1):
        self.course = CourseFactory()
        self.instructor = UserFactory(system_role=SystemRole.instructor)
        self.enrol_user(self.instructor, self.course, CourseRole.instructor)
        self.ta = UserFactory(system_role=SystemRole.student)
        self.dropped_instructor = UserFactory(
            system_role=SystemRole.instructor)
        self.enrol_user(self.dropped_instructor, self.course,
                        CourseRole.dropped)
        self.enrol_user(self.ta, self.course, CourseRole.teaching_assistant)

        self.add_students(num_students, num_groups)

        if num_assignments:
            self.add_assignments(
                num_assignments,
                num_additional_criteria=num_additional_criteria,
                with_self_eval=with_self_eval)

        if num_group_assignments:
            self.add_assignments(
                num_group_assignments,
                num_additional_criteria=num_additional_criteria,
                with_self_eval=with_self_eval,
                with_group_answers=True)

        # create a shortcut for first assignment as it is frequently used
        self.assignment = self.assignments[0]

        self.add_answers(num_answers,
                         num_group_answers,
                         with_comments=with_comments)
        self.add_non_comparable_answers(num_non_comparable_ans)

        if with_comparisons:
            self.add_comparisons(with_comments=with_comments,
                                 with_self_eval=with_self_eval)

        if with_draft_student:
            self.draft_student = UserFactory(system_role=SystemRole.student)
            db.session.add(self.draft_student)
            db.session.commit()
            self.draft_group = self.add_group(self.course)
            self.students.append(self.draft_student)
            self.enrol_user(self.draft_student, self.course,
                            CourseRole.student, self.draft_group)
            for assignment in self.assignments:
                answer = AnswerFactory(assignment=assignment,
                                       draft=True,
                                       submission_date=None)
                if assignment.enable_group_answers:
                    answer.group = self.draft_group
                    answer.user = None
                else:
                    answer.user = self.draft_student
                    answer.group = None
                self.draft_answers.append(answer)
            db.session.add_all(self.draft_answers)
            db.session.commit()

        for assignment in self.assignments:
            assignment.calculate_grades()
        self.course.calculate_grades()

        return self
Esempio n. 7
0
class TestFixture:
    def __init__(self):
        self.root_user = DefaultFixture.ROOT_USER
        self.default_criterion = DefaultFixture.DEFAULT_CRITERION
        self.course = self.assignment = None
        self.instructor = self.ta = None
        self.students = []
        self.dropped_students = []
        self.assignments = []
        self.comparison_examples = []
        self.answers = []
        self.dropped_answers = []
        self.removed_answers = []
        self.draft_answers = []
        self.non_comparable_answers = []
        self.groups = []
        self.unauthorized_instructor = UserFactory(
            system_role=SystemRole.instructor)
        self.unauthorized_student = UserFactory(system_role=SystemRole.student)
        self.dropped_instructor = UserFactory(
            system_role=SystemRole.instructor)
        self.draft_student = None
        self.draft_group = None
        self.answer_comments = []
        self.comparisons = []
        self.self_evaluations = []
        db.session.commit()

    def add_course(self,
                   num_students=5,
                   num_assignments=1,
                   num_group_assignments=0,
                   num_additional_criteria=0,
                   num_groups=0,
                   num_answers='#',
                   num_group_answers='#',
                   with_comments=False,
                   with_draft_student=False,
                   with_comparisons=False,
                   with_self_eval=False,
                   num_non_comparable_ans=1):
        self.course = CourseFactory()
        self.instructor = UserFactory(system_role=SystemRole.instructor)
        self.enrol_user(self.instructor, self.course, CourseRole.instructor)
        self.ta = UserFactory(system_role=SystemRole.student)
        self.dropped_instructor = UserFactory(
            system_role=SystemRole.instructor)
        self.enrol_user(self.dropped_instructor, self.course,
                        CourseRole.dropped)
        self.enrol_user(self.ta, self.course, CourseRole.teaching_assistant)

        self.add_students(num_students, num_groups)

        if num_assignments:
            self.add_assignments(
                num_assignments,
                num_additional_criteria=num_additional_criteria,
                with_self_eval=with_self_eval)

        if num_group_assignments:
            self.add_assignments(
                num_group_assignments,
                num_additional_criteria=num_additional_criteria,
                with_self_eval=with_self_eval,
                with_group_answers=True)

        # create a shortcut for first assignment as it is frequently used
        self.assignment = self.assignments[0]

        self.add_answers(num_answers,
                         num_group_answers,
                         with_comments=with_comments)
        self.add_non_comparable_answers(num_non_comparable_ans)

        if with_comparisons:
            self.add_comparisons(with_comments=with_comments,
                                 with_self_eval=with_self_eval)

        if with_draft_student:
            self.draft_student = UserFactory(system_role=SystemRole.student)
            db.session.add(self.draft_student)
            db.session.commit()
            self.draft_group = self.add_group(self.course)
            self.students.append(self.draft_student)
            self.enrol_user(self.draft_student, self.course,
                            CourseRole.student, self.draft_group)
            for assignment in self.assignments:
                answer = AnswerFactory(assignment=assignment,
                                       draft=True,
                                       submission_date=None)
                if assignment.enable_group_answers:
                    answer.group = self.draft_group
                    answer.user = None
                else:
                    answer.user = self.draft_student
                    answer.group = None
                self.draft_answers.append(answer)
            db.session.add_all(self.draft_answers)
            db.session.commit()

        for assignment in self.assignments:
            assignment.calculate_grades()
        self.course.calculate_grades()

        return self

    def add_answers(self,
                    num_answers='#',
                    num_group_answers='#',
                    with_scores=True,
                    with_comments=False):
        if num_answers == '#':
            num_answers = len(self.students)
        if num_group_answers == '#':
            num_group_answers = len(self.groups)

        for assignment in self.assignments:
            if not assignment.active:
                continue

            if assignment.enable_group_answers:
                # add a scored removed answer for every group
                # make sure system handles this properly
                for group in self.groups:
                    if not group.active:
                        continue

                    answer = AnswerFactory(assignment=assignment,
                                           group=group,
                                           user=None,
                                           active=False)
                    AnswerScoreFactory(assignment=assignment,
                                       answer=answer,
                                       score=random.random() * 5)
                    for criterion in assignment.criteria:
                        AnswerCriterionScoreFactory(assignment=assignment,
                                                    answer=answer,
                                                    criterion=criterion,
                                                    score=random.random() * 5)
                    self.removed_answers.append(answer)

                for i in range(num_group_answers):
                    group = self.groups[i % len(self.groups)]
                    answer = AnswerFactory(
                        assignment=assignment,
                        group=group,
                        user=None,
                    )
                    # half of the answers have scores if with_scores is enabled
                    if with_scores and i < num_group_answers / 2:
                        AnswerScoreFactory(assignment=assignment,
                                           answer=answer,
                                           score=random.random() * 5)
                        for criterion in assignment.criteria:
                            AnswerCriterionScoreFactory(assignment=assignment,
                                                        answer=answer,
                                                        criterion=criterion,
                                                        score=random.random() *
                                                        5)

                    if with_comments:
                        user_courses = UserCourse.query \
                            .filter_by(course_id=assignment.course_id, group_id=group.id) \
                            .all()
                        group_user_ids = [
                            user_course.user_id for user_course in user_courses
                        ]
                        other_group_students = [
                            s for s in self.students
                            if not s.id in group_user_ids
                        ]
                        # half of the answers have a public comment
                        if i < num_group_answers / 2:
                            random.shuffle(other_group_students)
                            answer_comment = AnswerCommentFactory(
                                user=other_group_students[0],
                                answer=answer,
                                comment_type=AnswerCommentType.public)
                            self.answer_comments.append(answer_comment)

                        # half of the answers have a private comment
                        # (middle half so there is partial overlap with public comments)
                        if num_group_answers / 4 < i and i < (
                                num_group_answers * 3) / 4:
                            random.shuffle(other_group_students)
                            answer_comment = AnswerCommentFactory(
                                user=other_group_students[0],
                                answer=answer,
                                comment_type=AnswerCommentType.private)
                            self.answer_comments.append(answer_comment)

                    self.answers.append(answer)

                for dropped_student in self.dropped_students:
                    answer = AnswerFactory(
                        assignment=assignment,
                        user=dropped_student,
                        group=None,
                    )
                    self.dropped_answers.append(answer)
            else:
                # add a scored removed answer for every student
                # make sure system handles this properly
                for student in self.students:
                    answer = AnswerFactory(
                        assignment=assignment,
                        user=student,
                        group=None,
                        active=False,
                    )
                    AnswerScoreFactory(assignment=assignment,
                                       answer=answer,
                                       score=random.random() * 5)
                    for criterion in assignment.criteria:
                        AnswerCriterionScoreFactory(assignment=assignment,
                                                    answer=answer,
                                                    criterion=criterion,
                                                    score=random.random() * 5)
                    self.removed_answers.append(answer)

                for i in range(num_answers):
                    student = self.students[i % len(self.students)]
                    answer = AnswerFactory(assignment=assignment,
                                           user=student,
                                           group=None)
                    # half of the answers have scores if with_scores is enabled
                    if with_scores and i < num_answers / 2:
                        AnswerScoreFactory(assignment=assignment,
                                           answer=answer,
                                           score=random.random() * 5)
                        for criterion in assignment.criteria:
                            AnswerCriterionScoreFactory(assignment=assignment,
                                                        answer=answer,
                                                        criterion=criterion,
                                                        score=random.random() *
                                                        5)

                    if with_comments:
                        other_students = [
                            s for s in self.students if s.id != student.id
                        ]
                        # half of the answers has a public comment
                        if i < num_answers / 2:
                            random.shuffle(other_students)
                            answer_comment = AnswerCommentFactory(
                                user=other_students[0],
                                answer=answer,
                                comment_type=AnswerCommentType.public)
                            self.answer_comments.append(answer_comment)

                        # half of the answers has a private comment
                        # (middle half so there is partial overlap with public comments)
                        if num_answers / 4 < i and i < (num_answers * 3) / 4:
                            random.shuffle(other_students)
                            answer_comment = AnswerCommentFactory(
                                user=other_students[0],
                                answer=answer,
                                comment_type=AnswerCommentType.private)
                            self.answer_comments.append(answer_comment)

                    self.answers.append(answer)

                for dropped_student in self.dropped_students:
                    answer = AnswerFactory(assignment=assignment,
                                           user=dropped_student,
                                           group=None)
                    self.dropped_answers.append(answer)

        db.session.commit()

        return self

    def add_non_comparable_answers(self, num_non_comparable_ans):
        for assignment in self.assignments:
            for i in range(num_non_comparable_ans):
                answer = AnswerFactory(assignment=assignment,
                                       user=self.instructor,
                                       group=None,
                                       comparable=False)
                self.answers.append(answer)
                self.non_comparable_answers.append(answer)
        db.session.commit()

    def add_comparisons(self, with_comments=False, with_self_eval=False):
        for assignment in self.assignments:
            for student in self.students:
                self.add_comparisons_for_user(assignment,
                                              student,
                                              with_comments=with_comments,
                                              with_self_eval=with_self_eval)
        return self

    def add_comparisons_for_user(self,
                                 assignment,
                                 student,
                                 with_comments=False,
                                 with_self_eval=False):
        answers = set()
        for i in range(assignment.total_comparisons_required):
            comparison = Comparison.create_new_comparison(
                assignment.id, student.id, False)
            comparison.completed = True
            comparison.winner = WinningAnswer.answer1 if comparison.answer1_id < comparison.answer2_id else WinningAnswer.answer2
            for comparison_criterion in comparison.comparison_criteria:
                comparison_criterion.winner = comparison.winner
            db.session.add(comparison)
            db.session.commit()
            self.comparisons.append(comparison)

        if with_comments:
            for answer in answers:
                answer_comment = AnswerCommentFactory(
                    user=student,
                    answer=answer,
                    comment_type=AnswerCommentType.evaluation)
                self.answer_comments.append(answer_comment)
            db.session.commit()

        if with_self_eval:
            student_answer = next(answer for answer in self.answers
                                  if answer.user_id == student.id
                                  and answer.assignment_id == assignment.id)
            if student_answer:
                self_evaluation = AnswerCommentFactory(
                    user=student,
                    answer=student_answer,
                    comment_type=AnswerCommentType.self_evaluation)
                self.self_evaluations.append(self_evaluation)
                db.session.commit()

        return self

    def add_answer(self, assignment, user, draft=False):
        answer = AnswerFactory(assignment=assignment,
                               user=user,
                               group=None,
                               draft=draft)
        if (draft):
            answer.submission_date = None

        db.session.commit()
        self.answers.append(answer)
        return self

    def add_group_answer(self, assignment, group, draft=False):
        answer = AnswerFactory(assignment=assignment,
                               group=group,
                               user=None,
                               draft=draft)
        if (draft):
            answer.submission_date = None

        db.session.commit()
        self.answers.append(answer)
        return self

    def add_assignments(self,
                        num_assignments=1,
                        num_group_assignments=0,
                        num_additional_criteria=0,
                        is_answer_period_end=False,
                        with_self_eval=False,
                        with_group_answers=False):
        for _ in range(num_assignments):
            answer_end = datetime.datetime.now() - datetime.timedelta(
                days=2) if is_answer_period_end else datetime.datetime.now(
                ) + datetime.timedelta(days=7)
            assignment = AssignmentFactory(course=self.course,
                                           answer_end=answer_end)

            if with_self_eval:
                assignment.enable_self_evaluation = True

            if with_group_answers:
                assignment.enable_group_answers = True

            # default criterion
            AssignmentCriterionFactory(
                criterion=DefaultFixture.DEFAULT_CRITERION,
                assignment=assignment,
                position=0)

            # disabled criterion
            disabled_criterion = CriterionFactory(user=self.instructor,
                                                  default=False,
                                                  active=False)
            AssignmentCriterionFactory(criterion=disabled_criterion,
                                       assignment=assignment,
                                       active=False,
                                       position=1)

            # additional criterion
            for i in range(num_additional_criteria):
                criterion = CriterionFactory(user=self.instructor,
                                             default=False)
                AssignmentCriterionFactory(criterion=criterion,
                                           assignment=assignment,
                                           position=i + 2)

            db.session.commit()

            # need to reorder after update
            assignment.assignment_criteria.reorder()

            self.assignments.append(assignment)
        db.session.commit()

        return self

    def add_comparison_example(self, assignment, user):
        self.add_answer(assignment, user)
        self.add_answer(assignment, user)

        comparison_example = ComparisonExampleFactory(assignment=assignment,
                                                      answer1=self.answers[-2],
                                                      answer2=self.answers[-1])
        self.comparison_examples.append(comparison_example)
        db.session.commit()
        return self

    def add_students(self, num_students, num_groups=0):
        students = []
        for _ in range(num_students):
            student = UserFactory(system_role=SystemRole.student)
            students.append(student)
        self.students += students

        if num_groups > 0:
            student_per_group = int(len(self.students) /
                                    num_groups) if num_groups is not 0 else 0
            for idx in range(num_groups):
                group = self.add_group(self.course)
                # slice student list and enroll them into groups
                group_students = students[idx * student_per_group:min(
                    (idx + 1) * student_per_group, len(students))]
                for student in group_students:
                    self.enrol_user(student, self.course, CourseRole.student,
                                    group)
        else:
            for student in students:
                self.enrol_user(student, self.course, CourseRole.student)

        # add dropped student in group
        dropped_student = UserFactory(system_role=SystemRole.student)
        dropped_group = self.add_group(self.course)
        self.enrol_user(dropped_student, self.course, CourseRole.dropped,
                        dropped_group)
        self.dropped_students.append(dropped_student)

        return self

    def enrol_user(self, user, course, course_role, group=None):
        user_course = UserCourseFactory(course=course,
                                        user=user,
                                        course_role=course_role,
                                        group=group)
        db.session.commit()
        return user_course

    def change_user_group(self, course, user, group):
        user_course = UserCourse.query \
            .filter_by(
                course_id=course.id,
                user_id=user.id
            ) \
            .one()
        user_course.group = group
        db.session.commit()

        return user_course

    def add_file(self, user, **kwargs):
        db_file = FileFactory(user=user, **kwargs)
        db.session.commit()
        return db_file

    def add_group(self, course, **kwargs):
        group = GroupFactory(course=course, **kwargs)
        self.groups.append(group)
        db.session.commit()
        return group

    def _get_assignment_group_member_answers(self, assignment, group):
        user_ids = [
            uc.user_id for uc in group.user_courses
            if uc.course_role != CourseRole.dropped
        ]
        return [
            a for a in self.answers if a.user_id in user_ids
            and a.assignment_id == assignment.id and a.active
        ]

    def _get_assignment_group_answers(self, assignment, group):
        return [
            a for a in self.answers if a.group_id == group.id
            and a.assignment_id == assignment.id and a.active
        ]

    def get_assignment_answers_for_group(self, assignment, group):
        return self._get_assignment_group_answers(assignment, group) + \
            self._get_assignment_group_member_answers(assignment, group)
Esempio n. 8
0
 def create_course(self):
     course = CourseFactory()
     db.session.commit()
     return course
Esempio n. 9
0
class TestFixture:
    def __init__(self):
        self.default_criterion = Criterion.query.get(1)
        self.course = self.assignment = None
        self.instructor = self.ta = None
        self.students = []
        self.dropped_students = []
        self.assignments = []
        self.comparison_examples = []
        self.answers = []
        self.dropped_answers = []
        self.removed_answers = []
        self.draft_answers = []
        self.groups = []
        self.unauthorized_instructor = UserFactory(
            system_role=SystemRole.instructor)
        self.unauthorized_student = UserFactory(system_role=SystemRole.student)
        self.dropped_instructor = UserFactory(
            system_role=SystemRole.instructor)
        self.draft_student = None
        self.answer_comments = []
        self.comparisons = []
        self.self_evaluations = []
        db.session.commit()

    def add_course(self,
                   num_students=5,
                   num_assignments=1,
                   num_additional_criteria=0,
                   num_groups=0,
                   num_answers='#',
                   with_comments=False,
                   with_draft_student=False,
                   with_comparisons=False,
                   with_self_eval=False):
        self.course = CourseFactory()
        self.instructor = UserFactory(system_role=SystemRole.instructor)
        self.enrol_user(self.instructor, self.course, CourseRole.instructor)
        self.ta = UserFactory(system_role=SystemRole.student)
        self.dropped_instructor = UserFactory(
            system_role=SystemRole.instructor)
        self.enrol_user(self.dropped_instructor, self.course,
                        CourseRole.dropped)
        self.enrol_user(self.ta, self.course, CourseRole.teaching_assistant)

        self.add_students(num_students, num_groups)

        self.add_assignments(num_assignments,
                             num_additional_criteria=num_additional_criteria,
                             with_self_eval=with_self_eval)
        # create a shortcut for first assignment as it is frequently used
        self.assignment = self.assignments[0]

        self.add_answers(num_answers, with_comments=with_comments)

        if with_comparisons:
            self.add_comparisons(with_comments=with_comments,
                                 with_self_eval=with_self_eval)

        if with_draft_student:
            self.add_students(1)
            self.draft_student = self.students[-1]
            self.add_draft_answers([self.draft_student])

        for assignment in self.course.assignments:
            assignment.calculate_grades()
        self.course.calculate_grades()

        return self

    def add_answers(self, num_answers, with_comments=False):
        if num_answers == '#':
            num_answers = len(self.students) * len(self.assignments)
        if len(self.students) * len(self.assignments) < num_answers:
            raise ValueError(
                "Number of answers({}) must be equal or smaller than number of students({}) "
                "multiple by number of assignments({})".format(
                    num_answers, len(self.students), len(self.assignments)))
        for assignment in self.assignments:
            # add a scored removed answer for every student
            # make sure system handles this properly
            for student in self.students:
                answer = AnswerFactory(assignment=assignment,
                                       user=student,
                                       active=False)
                AnswerScoreFactory(assignment=assignment,
                                   answer=answer,
                                   score=random.random() * 5)
                for criterion in assignment.criteria:
                    AnswerCriterionScoreFactory(assignment=assignment,
                                                answer=answer,
                                                criterion=criterion,
                                                score=random.random() * 5)
                self.removed_answers.append(answer)

            for i in range(num_answers):
                student = self.students[i % len(self.students)]
                answer = AnswerFactory(assignment=assignment, user=student)
                # half of the answers have scores
                if i < num_answers / 2:

                    AnswerScoreFactory(assignment=assignment,
                                       answer=answer,
                                       score=random.random() * 5)
                    for criterion in assignment.criteria:
                        AnswerCriterionScoreFactory(assignment=assignment,
                                                    answer=answer,
                                                    criterion=criterion,
                                                    score=random.random() * 5)

                if with_comments:
                    other_students = [
                        s for s in self.students if s.id != student.id
                    ]
                    # half of the answers has a public comment
                    if i < num_answers / 2:
                        random.shuffle(other_students)
                        answer_comment = AnswerCommentFactory(
                            user=other_students[0],
                            answer=answer,
                            comment_type=AnswerCommentType.public)
                        self.answer_comments.append(answer_comment)

                    # half of the answers has a private comment
                    # (middle half so there is partial overlap with public comments)
                    if num_answers / 4 < i and i < (num_answers * 3) / 4:
                        random.shuffle(other_students)
                        answer_comment = AnswerCommentFactory(
                            user=other_students[0],
                            answer=answer,
                            comment_type=AnswerCommentType.private)
                        self.answer_comments.append(answer_comment)

                self.answers.append(answer)

            for dropped_student in self.dropped_students:
                answer = AnswerFactory(assignment=assignment,
                                       user=dropped_student)
                self.dropped_answers.append(answer)
        db.session.commit()

        return self

    def add_comparisons(self, with_comments=False, with_self_eval=False):
        for assignment in self.assignments:
            for student in self.students:
                self.add_comparisons_for_user(assignment,
                                              student,
                                              with_comments=with_comments,
                                              with_self_eval=with_self_eval)
        return self

    def add_comparisons_for_user(self,
                                 assignment,
                                 student,
                                 with_comments=False,
                                 with_self_eval=False):
        answers = set()
        for i in range(assignment.total_comparisons_required):
            comparison = Comparison.create_new_comparison(
                assignment.id, student.id, False)
            comparison.completed = True
            comparison.winner = WinningAnswer.answer1 if comparison.answer1_id < comparison.answer2_id else WinningAnswer.answer2
            for comparison_criterion in comparison.comparison_criteria:
                comparison_criterion.winner = comparison.winner
            db.session.add(comparison)
            db.session.commit()
            self.comparisons.append(comparison)

        if with_comments:
            for answer in answers:
                answer_comment = AnswerCommentFactory(
                    user=student,
                    answer=answer,
                    comment_type=AnswerCommentType.evaluation)
                self.answer_comments.append(answer_comment)
            db.session.commit()

        if with_self_eval:
            student_answer = next(answer for answer in self.answers
                                  if answer.user_id == student.id
                                  and answer.assignment_id == assignment.id)
            if student_answer:
                self_evaluation = AnswerCommentFactory(
                    user=student,
                    answer=student_answer,
                    comment_type=AnswerCommentType.self_evaluation)
                self.self_evaluations.append(self_evaluation)
                db.session.commit()

        return self

    def add_answer(self, assignment, user):
        answer = AnswerFactory(assignment=assignment, user=user)
        db.session.commit()
        self.answers.append(answer)
        return self

    def add_draft_answers(self, students):
        for student in students:
            for assignment in self.assignments:
                answer = AnswerFactory(assignment=assignment,
                                       user=student,
                                       draft=True)
                db.session.commit()
                self.draft_answers.append(answer)

        return self

    def add_assignments(self,
                        num_assignments=1,
                        num_additional_criteria=0,
                        is_answer_period_end=False,
                        with_self_eval=False):
        for _ in range(num_assignments):
            answer_end = datetime.datetime.now() - datetime.timedelta(
                days=2) if is_answer_period_end else datetime.datetime.now(
                ) + datetime.timedelta(days=7)
            assignment = AssignmentFactory(course=self.course,
                                           answer_end=answer_end)

            if with_self_eval:
                assignment.self_evaluation_enabled = True

            # default criterion
            AssignmentCriterionFactory(
                criterion=DefaultFixture.DEFAULT_CRITERION,
                assignment=assignment,
                position=0)

            # disabled criterion
            disabled_criterion = CriterionFactory(user=self.instructor,
                                                  default=False,
                                                  active=False)
            AssignmentCriterionFactory(criterion=disabled_criterion,
                                       assignment=assignment,
                                       active=False,
                                       position=1)

            # additional criterion
            for i in range(num_additional_criteria):
                criterion = CriterionFactory(user=self.instructor,
                                             default=False)
                AssignmentCriterionFactory(criterion=criterion,
                                           assignment=assignment,
                                           position=i + 2)

            db.session.commit()

            # need to reorder after update
            assignment.assignment_criteria.reorder()

            self.assignments.append(assignment)
        db.session.commit()

        return self

    def add_comparison_example(self, assignment, user):
        self.add_answer(assignment, user)
        self.add_answer(assignment, user)

        comparison_example = ComparisonExampleFactory(assignment=assignment,
                                                      answer1=self.answers[-2],
                                                      answer2=self.answers[-1])
        self.comparison_examples.append(comparison_example)
        db.session.commit()
        return self

    def add_students(self, num_students, num_groups=0):
        students = []
        for _ in range(num_students):
            student = UserFactory(system_role=SystemRole.student)
            students.append(student)
        self.students += students

        if num_groups > 0:
            student_per_group = int(len(self.students) /
                                    num_groups) if num_groups is not 0 else 0
            for idx in range(num_groups):
                group_name = "Group" + str(idx)
                self.groups.append(group_name)
                # slice student list and enroll them into groups
                group_students = self.students[idx * student_per_group:min(
                    (idx + 1) * student_per_group, len(self.students))]
                for student in group_students:
                    self.enrol_user(student, self.course, CourseRole.student,
                                    group_name)
        else:
            for student in students:
                self.enrol_user(student, self.course, CourseRole.student)

        # add dropped student in group
        dropped_student = UserFactory(system_role=SystemRole.student)
        self.enrol_user(dropped_student, self.course, CourseRole.dropped,
                        "Group Dropped")
        self.dropped_students.append(dropped_student)

        return self

    def enrol_user(self, user, course, type, group_name=None):
        user_courses = UserCourseFactory(course=course,
                                         user=user,
                                         course_role=type,
                                         group_name=group_name)
        db.session.commit()
        return user_courses

    def add_file(self, user, **kwargs):
        db_file = FileFactory(user=user, **kwargs)
        db.session.commit()
        return db_file