From ef023d66e8586685b92261c0f2c3687ccd83e531 Mon Sep 17 00:00:00 2001 From: henrrypg Date: Tue, 25 Oct 2022 15:13:27 -0500 Subject: [PATCH] feat: add tests to queries and survey_report command --- lms/envs/test.py | 3 + openedx/features/survey_report/application.py | 9 +- .../management/commands/generate_report.py | 2 +- .../commands/tests/test_generate_report.py | 35 +++++- openedx/features/survey_report/queries.py | 2 + .../survey_report/tests/test_query_methods.py | 114 ++++++++++++++++++ 6 files changed, 156 insertions(+), 9 deletions(-) create mode 100644 openedx/features/survey_report/tests/test_query_methods.py diff --git a/lms/envs/test.py b/lms/envs/test.py index ad9372e09be1..717ee1d4c458 100644 --- a/lms/envs/test.py +++ b/lms/envs/test.py @@ -669,3 +669,6 @@ "LOGO_URL": "https://courses.example.com/yourmfe-logo.png", }, } + +############## Settings for survey report ############## +SURVEY_REPORT_EXTRA_DATA = {} diff --git a/openedx/features/survey_report/application.py b/openedx/features/survey_report/application.py index 89ee9a2ef2b6..776433d8ce98 100644 --- a/openedx/features/survey_report/application.py +++ b/openedx/features/survey_report/application.py @@ -4,16 +4,15 @@ from django.conf import settings +from openedx.features.survey_report.models import SurveyReport from openedx.features.survey_report.queries import ( - get_unique_courses_offered, + get_course_enrollments, get_currently_learners, - get_learners_registered, get_generated_certificates, - get_course_enrollments, + get_learners_registered, + get_unique_courses_offered ) -from openedx.features.survey_report.models import SurveyReport - def generate_report() -> None: """ Generate a report with relevant data.""" diff --git a/openedx/features/survey_report/management/commands/generate_report.py b/openedx/features/survey_report/management/commands/generate_report.py index 3c6c031eac13..475469dbfe37 100644 --- a/openedx/features/survey_report/management/commands/generate_report.py +++ b/openedx/features/survey_report/management/commands/generate_report.py @@ -23,6 +23,6 @@ def handle(self, *_args, **_options): try: generate_report() except Exception as error: - raise CommandError('An error has occurred while report was generating.') from error + raise CommandError(f'An error has occurred while report was generating. {error}') from error self.stdout.write(self.style.SUCCESS('Survey report has been generated successfully.')) diff --git a/openedx/features/survey_report/management/commands/tests/test_generate_report.py b/openedx/features/survey_report/management/commands/tests/test_generate_report.py index 0bcfa9301424..45f0d553c86d 100644 --- a/openedx/features/survey_report/management/commands/tests/test_generate_report.py +++ b/openedx/features/survey_report/management/commands/tests/test_generate_report.py @@ -3,13 +3,42 @@ """ from io import StringIO +from unittest import mock from django.core.management import call_command -from django.test import TestCase +from django.test import TestCase, override_settings + +from openedx.features.survey_report.models import SurveyReport class GenerateReportTest(TestCase): - def test_command_output(self): + """ + Test for generate_report command. + """ + @override_settings(SURVEY_REPORT_EXTRA_DATA={'extra_data': 'extra_data'}) + @mock.patch('openedx.features.survey_report.queries.get_course_enrollments') + @mock.patch('openedx.features.survey_report.queries.get_generated_certificates') + @mock.patch('openedx.features.survey_report.queries.get_learners_registered') + @mock.patch('openedx.features.survey_report.queries.get_currently_learners') + @mock.patch('openedx.features.survey_report.queries.get_unique_courses_offered') + def test_generate_report(self, mock_get_unique_courses_offered, mock_get_currently_learners, + mock_get_learners_registered, mock_get_generated_certificates, + mock_get_course_enrollments): + """ + Test that generate_report command creates a survey report. + """ + mock_get_unique_courses_offered.return_value = 1 + mock_get_currently_learners.return_value = 2 + mock_get_learners_registered.return_value = 3 + mock_get_generated_certificates.return_value = 4 + mock_get_course_enrollments.return_value = 5 out = StringIO() call_command('generate_report', stdout=out) - self.assertIn('Survey report has been generated successfully.', out.getvalue()) + + survey_report = SurveyReport.objects.last() + assert survey_report.courses_offered == 1 + assert survey_report.learners == 2 + assert survey_report.registered_learners == 3 + assert survey_report.generated_certificates == 4 + assert survey_report.enrollments == 5 + assert survey_report.extra_data == {'extra_data': 'extra_data'} diff --git a/openedx/features/survey_report/queries.py b/openedx/features/survey_report/queries.py index 589dfad127f3..d2e179482cb8 100644 --- a/openedx/features/survey_report/queries.py +++ b/openedx/features/survey_report/queries.py @@ -11,6 +11,7 @@ from lms.djangoapps.grades.models import PersistentCourseGrade from openedx.core.djangoapps.content.course_overviews.models import CourseOverview + def get_unique_courses_offered() -> int: """ Get total number of unique courses offered. @@ -49,6 +50,7 @@ def get_generated_certificates() -> int: """ return PersistentCourseGrade.objects.filter(passed_timestamp__isnull=False).count() + def get_course_enrollments() -> int: """ Get total number of enrollments from users that aren't staff. diff --git a/openedx/features/survey_report/tests/test_query_methods.py b/openedx/features/survey_report/tests/test_query_methods.py new file mode 100644 index 000000000000..e426a38886f9 --- /dev/null +++ b/openedx/features/survey_report/tests/test_query_methods.py @@ -0,0 +1,114 @@ +""" +Test for survey report commands. +""" + +from datetime import datetime, timedelta +from unittest.mock import patch + +from common.djangoapps.student.tests.factories import CourseEnrollmentFactory, UserFactory +from lms.djangoapps.grades.models import PersistentCourseGrade +from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory +from openedx.features.survey_report.queries import ( + get_course_enrollments, + get_currently_learners, + get_generated_certificates, + get_learners_registered, + get_unique_courses_offered +) +from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable=wrong-import-order +from xmodule.modulestore.django import modulestore +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.factories import CourseFactory # lint-amnesty, pylint: disable=wrong-import-order + + +class TestSurveyReportCommands(ModuleStoreTestCase): + """ + Test for survey report query methods. + """ + + def setUp(self): + """ + Setup for users and courses. + """ + super().setUp() + self.store = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.mongo) # lint-amnesty, pylint: disable=protected-access + self.first_course = CourseFactory.create( + org="test", course="course1", display_name="run1", default_store=ModuleStoreEnum.Type.mongo + ) + self.user = UserFactory.create(username='test_user', email='test@example.com', password='password') + self.user1 = UserFactory.create(username='test_user1', email='test1@example.com', password='password') + self.user2 = UserFactory.create(username='test_user2', email='test2@example.com', password='password') + self.user3 = UserFactory.create(username='test_user3', email='test3@example.com', password='password') + self.user4 = UserFactory.create(username='test_user4', email='test4@example.com', password='password') + self.user5 = UserFactory.create(username='test_user5', email='test5@example.com', password='password') + + def test_get_unique_courses_offered(self): + """ + Test that get_unique_courses_offered returns the correct number of courses. + """ + course_overview = CourseOverviewFactory.create(id=self.first_course.id, start="2019-01-01", end="2024-01-01") + CourseEnrollmentFactory.create(user=self.user, course_id=course_overview.id) + CourseEnrollmentFactory.create(user=self.user1, course_id=course_overview.id) + CourseEnrollmentFactory.create(user=self.user2, course_id=course_overview.id) + CourseEnrollmentFactory.create(user=self.user3, course_id=course_overview.id) + CourseEnrollmentFactory.create(user=self.user4, course_id=course_overview.id) + CourseEnrollmentFactory.create(user=self.user5, course_id=course_overview.id) + with patch('openedx.features.survey_report.queries.datetime') as mock_datetime: + mock_datetime.now.return_value = datetime.now() + assert get_unique_courses_offered() == 1 + + def test_get_currently_learners(self): + """ + Test that get_currently_learners returns the correct number of learners. + """ + self.user.last_login = datetime.now() - timedelta(days=1) + self.user.save() + self.user1.last_login = datetime.now() - timedelta(weeks=2) + self.user1.save() + self.user2.last_login = datetime.now() - timedelta(weeks=4) + self.user2.save() + with patch('openedx.features.survey_report.queries.datetime') as mock_datetime: + mock_datetime.now.return_value = datetime.now() + assert get_currently_learners() == 2 + + def test_get_learners_registered(self): + """ + Test that get_learners_registered returns the correct number of learners. + """ + assert get_learners_registered() == 7 + + def test_get_generated_certificates(self): + """ + Test that get_generated_certificates returns the correct number of certificates. + """ + course_grade_params = { + "user_id": self.user.id, + "course_id": self.first_course.id, + "percent_grade": 77.7, + "letter_grade": "pass", + "passed": True, + "passed_timestamp": datetime.now(), + } + PersistentCourseGrade.update_or_create(**course_grade_params) + + with patch('openedx.features.survey_report.queries.datetime') as mock_datetime: + mock_datetime.now.return_value = datetime.now() + assert get_generated_certificates() == 1 + + def test_get_course_enrollments(self): + """ + Test that get_course_enrollments returns the correct number of enrollments. + """ + self.user.is_superuser = True + self.user.save() + self.user1.is_staff = True + self.user1.save() + course_overview = CourseOverviewFactory.create(id=self.first_course.id, start="2019-01-01", end="2024-01-01") + CourseEnrollmentFactory.create(user=self.user, course_id=course_overview.id) + CourseEnrollmentFactory.create(user=self.user1, course_id=course_overview.id) + CourseEnrollmentFactory.create(user=self.user2, course_id=course_overview.id) + CourseEnrollmentFactory.create(user=self.user3, course_id=course_overview.id) + CourseEnrollmentFactory.create(user=self.user4, course_id=course_overview.id) + with patch('openedx.features.survey_report.queries.datetime') as mock_datetime: + mock_datetime.now.return_value = datetime.now() + assert get_course_enrollments() == 3