def test_mix_of_curriculums_with_and_without_programs(self): course_a = self._create_course_and_runs('a') course_b = self._create_course_and_runs('b') course_c = self._create_course_and_runs('c') program_1 = factories.ProgramFactory(title='program_1') program_2 = factories.ProgramFactory(title='program_2') curriculum_1 = factories.CurriculumFactory(program=program_1) curriculum_2 = factories.CurriculumFactory(program=program_2) curriculum_3 = factories.CurriculumFactory(program=None) curriculum_4 = factories.CurriculumFactory(program=None) self._add_courses_to_curriculum(curriculum_1, course_a, course_b) self._add_courses_to_curriculum(curriculum_2, course_a, course_b) self._add_courses_to_curriculum(curriculum_3, course_a, course_b, course_c) self._add_courses_to_curriculum(curriculum_4, course_a, course_b, course_c) course_run = course_a.course_runs.first() course_run_ca = CourseRun.objects.get(external_key='ext-key-course-ca') message = _duplicate_external_key_message([course_run_ca]) with self.assertNumQueries(FuzzyInt(6, 1)): # 3 Selects with self.assertRaisesRegex(ValidationError, escape(message)): course_run.external_key = course_run_ca.external_key course_run.save() with self.assertNumQueries(FuzzyInt(36, 1)): course_run.external_key = 'some-safe-key' course_run.save()
def test_retrieve_without_course_runs(self, django_assert_num_queries): """ Verify the endpoint returns data for a program even if the program's courses have no course runs. """ course = CourseFactory(partner=self.partner) program = ProgramFactory(courses=[course], partner=self.partner) with django_assert_num_queries(FuzzyInt(27, 2)): response = self.assert_retrieve_success(program) assert response.data == self.serialize_program(program)
def test_nondraft_does_not_collide_with_draft(self): with self.assertNumQueries(FuzzyInt(75, 1)): factories.CourseRunFactory( course=self.course_1, draft=False, external_key='external-key-drafttest', end=datetime.datetime(2014, 1, 1, tzinfo=UTC), enrollment_end=datetime.datetime(2014, 1, 1, tzinfo=UTC), )
def test_collision_does_not_include_drafts(self): with self.assertNumQueries(FuzzyInt(75, 1)): course_run = factories.CourseRunFactory( course=self.course_1, draft=False, external_key='external-key-drafttest', end=datetime.datetime(2014, 1, 1, tzinfo=UTC), enrollment_end=datetime.datetime(2014, 1, 1, tzinfo=UTC), ) message = _duplicate_external_key_message([course_run]) # Not draft_course_run_1 with self.assertNumQueries(FuzzyInt(11, 1)): with self.assertRaisesRegex(ValidationError, escape(message)): factories.CourseRunFactory( course=self.course_1, draft=False, external_key='external-key-drafttest', end=datetime.datetime(2014, 1, 1, tzinfo=UTC), enrollment_end=datetime.datetime(2014, 1, 1, tzinfo=UTC), )
def test_fuzzy_int_equality(): fuzzy_int = FuzzyInt(10, 4) for i in range(0, 6): assert i != fuzzy_int for i in range(6, 15): assert i == fuzzy_int for i in range(15, 20): assert i != fuzzy_int
def test_retrieve_basic_curriculum(self, django_assert_num_queries): program = self.create_program(courses=[]) self.create_curriculum(program) # Notes on this query count: # 36 queries to get program without a curriculum and no courses # +2 for curriculum details (related courses, related programs) # +8 for course details on 1 or more courses across all sibling curricula with django_assert_num_queries(FuzzyInt(46, 2)): response = self.assert_retrieve_success(program) assert response.data == self.serialize_program(program)
def test_retrieve(self, django_assert_num_queries): """ Verify the endpoint returns the details for a single program. """ program = self.create_program() with django_assert_num_queries(FuzzyInt(61, 2)): response = self.assert_retrieve_success(program) # property does not have the right values while being indexed del program._course_run_weeks_to_complete assert response.data == self.serialize_program(program) # Verify that requests including querystring parameters are cached separately. response = self.assert_retrieve_success(program, querystring={'use_full_course_serializer': 1}) assert response.data == self.serialize_program(program, extra_context={'use_full_course_serializer': 1})
def test_queryset_method_returns_eligible_programs(self): """ Verify that one click purchase eligible programs pass the filter. """ verified_seat_type = factories.SeatTypeFactory.verified() program_type = factories.ProgramTypeFactory(applicable_seat_types=[verified_seat_type]) program_filter = ProgramEligibilityFilter(None, {self.parameter_name: 1}, None, None) course_run = factories.CourseRunFactory(end=None, enrollment_end=None,) factories.SeatFactory(course_run=course_run, type=verified_seat_type, upgrade_deadline=None) one_click_purchase_eligible_program = factories.ProgramFactory( type=program_type, courses=[course_run.course], one_click_purchase_enabled=True, ) with self.assertNumQueries(FuzzyInt(11, 2)): assert list(program_filter.queryset({}, Program.objects.all())) == [one_click_purchase_eligible_program]
def test_retrieve_curriculum_with_child_programs( self, django_assert_num_queries): parent_program = self.create_program(courses=[]) curriculum = self.create_curriculum(parent_program) child_program1 = self.create_program() child_program2 = self.create_program() CurriculumProgramMembershipFactory(program=child_program1, curriculum=curriculum) CurriculumProgramMembershipFactory(program=child_program2, curriculum=curriculum) with django_assert_num_queries(FuzzyInt(63, 2)): response = self.assert_retrieve_success(parent_program) assert response.data == self.serialize_program(parent_program)
def test_retrieve_with_sorting_flag(self, order_courses_by_start_date, django_assert_num_queries): """ Verify the number of queries is the same with sorting flag set to true. """ course_list = CourseFactory.create_batch(3, partner=self.partner) for course in course_list: CourseRunFactory(course=course) program = ProgramFactory( courses=course_list, order_courses_by_start_date=order_courses_by_start_date, partner=self.partner) # property does not have the right values while being indexed del program._course_run_weeks_to_complete with django_assert_num_queries(FuzzyInt(45, 2)): response = self.assert_retrieve_success(program) assert response.data == self.serialize_program(program) assert course_list == list(program.courses.all()) # pylint: disable=no-member
def assert_list_results(self, url, expected, expected_query_count, extra_context=None): """ Asserts the results serialized/returned at the URL matches those that are expected. Args: url (str): URL from which data should be retrieved expected (list[Program]): Expected programs Notes: The API usually returns items in reverse order of creation (e.g. newest first). You may need to reverse the values of `expected` if you encounter issues. This method will NOT do that reversal for you. Returns: None """ with self.django_assert_num_queries(FuzzyInt(expected_query_count, 2)): response = self.client.get(url) assert response.data['results'] == self.serialize_program(expected, many=True, extra_context=extra_context)
def test_courses(self, state): """ Verify the endpoint returns the list of available courses contained in the catalog, and that courses appearing in the response always have at least one serialized run. """ url = reverse('api:v1:catalog-courses', kwargs={'id': self.catalog.id}) Course.objects.all().delete() course_run = CourseRunFactory(course__title='ABC Test Course') for function in state: function(course_run) course_run.save() if state in AVAILABLE_STATES: course = course_run.course # This run has no seats, but we still expect its parent course # to be included. filtered_course_run = CourseRunFactory(course=course) with self.assertNumQueries(FuzzyInt(23, 2)): response = self.client.get(url) assert response.status_code == 200 # Emulate prefetching behavior. filtered_course_run.delete() assert response.data['results'] == self.serialize_catalog_course([course], many=True) # Any course appearing in the response must have at least one serialized run. assert len(response.data['results'][0]['course_runs']) > 0 else: response = self.client.get(url) assert response.status_code == 200 assert response.data['results'] == []
def test_retrieve_curriculum_with_child_programs(self, django_assert_num_queries): parent_program = self.create_program(courses=[]) curriculum = self.create_curriculum(parent_program) child_program1 = self.create_program() child_program2 = self.create_program() CurriculumProgramMembershipFactory( program=child_program1, curriculum=curriculum ) CurriculumProgramMembershipFactory( program=child_program2, curriculum=curriculum ) # Notes on query count: # 46 queries to get program with single curriculum (test_retrieve_basic_curriculum) # +6 for first child program # +1 for additional child program # +8 for 1 or more first child program courses # +3 for 1 or more additional child program courses with django_assert_num_queries(FuzzyInt(64, 2)): response = self.assert_retrieve_success(parent_program) assert response.data == self.serialize_program(parent_program)