refactor: run modulestore tests in common/lib/... using Django
Does 3 things: (1) Use django for modulestore tests (2) Use normal LMS settings for modulestore tests instead of openedx/tests/settings.py (3) Simplify some TestCase subclasses by converting them to use ModuleStoreTestCase Details and rationale: (1) Currently parts of the modulestore test suite are designed to run "without django", although there is still a lot of django functionality imported at times, and many of the tests do in fact use django. But for the upcoming PR #27565 (moving split's course indexes from MongoDB to MySQL), we will need to always have Django enabled. So this commit paves the way for that change. (2) The previous tests that did use Django used a special settings file, openedx/tests/settings.py which made some debugging confusing because those tests had quite different django settings than other tests. This change deletes that file and runs the tests using the LMS test settings. (3) The test suite also contains many different ways of initializing and testing a modulestore, with significant differences in their configuration, and also a lot of repetition. I find this makes understanding, debugging and writing tests more difficult. So this commit also reduces the number of different "test case using modulestore" base classes: * Simplifies MixedWithOptionsTestCase and MixedSplitTestCase by making them simple subclasses of ModuleStoreTestCase. * Removes PureModulestoreTestCase.
This commit is contained in:
committed by
Braden MacDonald
parent
daac2f7585
commit
da09bcadc5
@@ -1,14 +1,11 @@
|
||||
"""
|
||||
Testing indexing of the courseware as it is changed
|
||||
"""
|
||||
|
||||
|
||||
import json
|
||||
import time
|
||||
from datetime import datetime
|
||||
from unittest import skip
|
||||
from unittest.mock import patch
|
||||
from uuid import uuid4
|
||||
|
||||
import ddt
|
||||
import pytest
|
||||
@@ -33,25 +30,14 @@ from openedx.core.djangoapps.models.course_details import CourseDetails
|
||||
from xmodule.library_tools import normalize_key_for_search
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import SignalHandler, modulestore
|
||||
from xmodule.modulestore.edit_info import EditInfoMixin
|
||||
from xmodule.modulestore.inheritance import InheritanceMixin
|
||||
from xmodule.modulestore.mixed import MixedModuleStore
|
||||
from xmodule.modulestore.tests.django_utils import (
|
||||
ModuleStoreTestCase,
|
||||
TEST_DATA_MONGO_MODULESTORE,
|
||||
TEST_DATA_SPLIT_MODULESTORE,
|
||||
SharedModuleStoreTestCase
|
||||
SharedModuleStoreTestCase,
|
||||
)
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, LibraryFactory
|
||||
from xmodule.modulestore.tests.mongo_connection import MONGO_HOST, MONGO_PORT_NUM
|
||||
from xmodule.modulestore.tests.utils import (
|
||||
LocationMixin,
|
||||
MixedSplitTestCase,
|
||||
MongoContentstoreBuilder,
|
||||
create_modulestore_instance
|
||||
)
|
||||
from xmodule.partitions.partitions import UserPartition
|
||||
from xmodule.tests import DATA_DIR
|
||||
from xmodule.x_module import XModuleMixin
|
||||
|
||||
COURSE_CHILD_STRUCTURE = {
|
||||
"course": "chapter",
|
||||
@@ -93,46 +79,9 @@ def create_large_course(store, load_factor):
|
||||
return course, child_count
|
||||
|
||||
|
||||
class MixedWithOptionsTestCase(MixedSplitTestCase):
|
||||
class MixedWithOptionsTestCase(ModuleStoreTestCase):
|
||||
""" Base class for test cases within this file """
|
||||
HOST = MONGO_HOST
|
||||
PORT = MONGO_PORT_NUM
|
||||
DATABASE = 'test_mongo_%s' % uuid4().hex[:5]
|
||||
COLLECTION = 'modulestore'
|
||||
ASSET_COLLECTION = 'assetstore'
|
||||
DEFAULT_CLASS = 'xmodule.hidden_module.HiddenDescriptor'
|
||||
RENDER_TEMPLATE = lambda t_n, d, ctx=None, nsp='main': ''
|
||||
modulestore_options = {
|
||||
'default_class': DEFAULT_CLASS,
|
||||
'fs_root': DATA_DIR,
|
||||
'render_template': RENDER_TEMPLATE,
|
||||
'xblock_mixins': (EditInfoMixin, InheritanceMixin, LocationMixin, XModuleMixin),
|
||||
}
|
||||
DOC_STORE_CONFIG = {
|
||||
'host': HOST,
|
||||
'port': PORT,
|
||||
'db': DATABASE,
|
||||
'collection': COLLECTION,
|
||||
'asset_collection': ASSET_COLLECTION,
|
||||
}
|
||||
OPTIONS = {
|
||||
'stores': [
|
||||
{
|
||||
'NAME': 'draft',
|
||||
'ENGINE': 'xmodule.modulestore.mongo.draft.DraftModuleStore',
|
||||
'DOC_STORE_CONFIG': DOC_STORE_CONFIG,
|
||||
'OPTIONS': modulestore_options
|
||||
},
|
||||
{
|
||||
'NAME': 'split',
|
||||
'ENGINE': 'xmodule.modulestore.split_mongo.split_draft.DraftVersioningModuleStore',
|
||||
'DOC_STORE_CONFIG': DOC_STORE_CONFIG,
|
||||
'OPTIONS': modulestore_options
|
||||
},
|
||||
],
|
||||
'xblock_mixins': modulestore_options['xblock_mixins'],
|
||||
}
|
||||
|
||||
CREATE_USER = False
|
||||
INDEX_NAME = None
|
||||
|
||||
def setup_course_base(self, store):
|
||||
@@ -155,18 +104,10 @@ class MixedWithOptionsTestCase(MixedSplitTestCase):
|
||||
|
||||
def _perform_test_using_store(self, store_type, test_to_perform):
|
||||
""" Helper method to run a test function that uses a specific store """
|
||||
with MongoContentstoreBuilder().build() as contentstore:
|
||||
store = MixedModuleStore(
|
||||
contentstore=contentstore,
|
||||
create_modulestore_instance=create_modulestore_instance,
|
||||
mappings={},
|
||||
**self.OPTIONS
|
||||
)
|
||||
self.addCleanup(store.close_all_connections)
|
||||
|
||||
with store.default_store(store_type):
|
||||
self.setup_course_base(store)
|
||||
test_to_perform(store)
|
||||
store = modulestore()
|
||||
with store.default_store(store_type):
|
||||
self.setup_course_base(store)
|
||||
test_to_perform(store)
|
||||
|
||||
def publish_item(self, store, item_location):
|
||||
""" publish the item at the given location """
|
||||
@@ -190,6 +131,7 @@ class TestCoursewareSearchIndexer(MixedWithOptionsTestCase):
|
||||
""" Tests the operation of the CoursewareSearchIndexer """
|
||||
|
||||
WORKS_WITH_STORES = (ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
|
||||
ENABLED_SIGNALS = ['course_deleted']
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
@@ -264,11 +206,8 @@ class TestCoursewareSearchIndexer(MixedWithOptionsTestCase):
|
||||
|
||||
def _test_indexing_course(self, store):
|
||||
""" indexing course tests """
|
||||
response = self.search()
|
||||
self.assertEqual(response["total"], 0)
|
||||
|
||||
# Only published modules should be in the index
|
||||
added_to_index = self.reindex_course(store)
|
||||
added_to_index = self.reindex_course(store) # This reindex may not be necessary (it may already be indexed)
|
||||
self.assertEqual(added_to_index, 3)
|
||||
response = self.search()
|
||||
self.assertEqual(response["total"], 3)
|
||||
@@ -311,17 +250,15 @@ class TestCoursewareSearchIndexer(MixedWithOptionsTestCase):
|
||||
Test that course will also be delete from search_index after course deletion.
|
||||
"""
|
||||
self.searcher = SearchEngine.get_search_engine(CourseAboutSearchIndexer.INDEX_NAME)
|
||||
response = self.search()
|
||||
self.assertEqual(response["total"], 0)
|
||||
|
||||
# index the course in search_index
|
||||
# index the course in search_index (it may already be indexed)
|
||||
self.reindex_course(store)
|
||||
response = self.search()
|
||||
self.assertEqual(response["total"], 1)
|
||||
|
||||
# delete the course and look course in search_index
|
||||
modulestore().delete_course(self.course.id, ModuleStoreEnum.UserID.test)
|
||||
self.assertIsNone(modulestore().get_course(self.course.id))
|
||||
store.delete_course(self.course.id, ModuleStoreEnum.UserID.test)
|
||||
self.assertIsNone(store.get_course(self.course.id))
|
||||
# Now, because of contentstore.signals.handlers.listen_for_course_delete, the index should already be updated:
|
||||
response = self.search()
|
||||
self.assertEqual(response["total"], 0)
|
||||
|
||||
@@ -776,6 +713,7 @@ class TestTaskExecution(SharedModuleStoreTestCase):
|
||||
self.assertFalse(mock_index.called)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@ddt.ddt
|
||||
class TestLibrarySearchIndexer(MixedWithOptionsTestCase):
|
||||
""" Tests the operation of the CoursewareSearchIndexer """
|
||||
@@ -929,7 +867,7 @@ class GroupConfigurationSearchMongo(CourseTestCase, MixedWithOptionsTestCase):
|
||||
"""
|
||||
Tests indexing of content groups on course modules using mongo modulestore.
|
||||
"""
|
||||
|
||||
CREATE_USER = True
|
||||
MODULESTORE = TEST_DATA_MONGO_MODULESTORE
|
||||
INDEX_NAME = CoursewareSearchIndexer.INDEX_NAME
|
||||
|
||||
|
||||
Reference in New Issue
Block a user