Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lms/envs/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -669,3 +669,6 @@
"LOGO_URL": "https://courses.example.com/yourmfe-logo.png",
},
}

############## Settings for survey report ##############
SURVEY_REPORT_EXTRA_DATA = {}
9 changes: 4 additions & 5 deletions openedx/features/survey_report/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.'))
Original file line number Diff line number Diff line change
Expand Up @@ -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'}
2 changes: 2 additions & 0 deletions openedx/features/survey_report/queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
114 changes: 114 additions & 0 deletions openedx/features/survey_report/tests/test_query_methods.py
Original file line number Diff line number Diff line change
@@ -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