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_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
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
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
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)
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
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)
def create_course(self): course = CourseFactory() db.session.commit() return course
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