diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000000000000000000000000000000..72ec77d0e2fe3500a744426881989b1566b57b9f --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "askbot"] + path = askbot + url = git@github.com:MITx/askbot-devel.git diff --git a/askbot b/askbot new file mode 160000 index 0000000000000000000000000000000000000000..1c3381046c78e055439ba1c78e0df48410fcc13e --- /dev/null +++ b/askbot @@ -0,0 +1 @@ +Subproject commit 1c3381046c78e055439ba1c78e0df48410fcc13e diff --git a/lms/djangoapps/courseware/tests/tests.py b/lms/djangoapps/courseware/tests/tests.py index 24cc9eac00a0b924d8ad4fbf3c6ce8356fef566e..8e9d13f8d5ad24d2d598df19b2345b968f3430cb 100644 --- a/lms/djangoapps/courseware/tests/tests.py +++ b/lms/djangoapps/courseware/tests/tests.py @@ -1,4 +1,9 @@ +import copy import json +import os + +from pprint import pprint + from django.test import TestCase from django.test.client import Client from mock import patch, Mock @@ -14,7 +19,6 @@ from xmodule.modulestore.django import modulestore import xmodule.modulestore.django from xmodule.modulestore import Location from xmodule.modulestore.xml_importer import import_from_xml -import copy def parse_json(response): @@ -32,14 +36,32 @@ def registration(email): return Registration.objects.get(user__email=email) -TEST_DATA_MODULESTORE = copy.deepcopy(settings.MODULESTORE) -# TODO (vshnayder): test the real courses -TEST_DATA_DIR = 'common/test/data' -TEST_DATA_MODULESTORE['default']['OPTIONS']['fs_root'] = path(TEST_DATA_DIR) +# A bit of a hack--want mongo modulestore for these tests, until +# jump_to works with the xmlmodulestore or we have an even better solution +# NOTE: this means this test requires mongo to be running. -@override_settings(MODULESTORE=TEST_DATA_MODULESTORE) -class IntegrationTestCase(TestCase): - '''Check that all objects in all accessible courses will load properly''' +def mongo_store_config(data_dir): + return { + 'default': { + 'ENGINE': 'xmodule.modulestore.mongo.MongoModuleStore', + 'OPTIONS': { + 'default_class': 'xmodule.raw_module.RawDescriptor', + 'host': 'localhost', + 'db': 'xmodule', + 'collection': 'modulestore', + 'fs_root': data_dir, + } + } +} + +TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT +TEST_DATA_MODULESTORE = mongo_store_config(TEST_DATA_DIR) + +REAL_DATA_DIR = settings.GITHUB_REPO_ROOT +REAL_DATA_MODULESTORE = mongo_store_config(REAL_DATA_DIR) + +class ActivateLoginTestCase(TestCase): + '''Check that we can activate and log in''' def setUp(self): email = 'view@test.com' @@ -47,9 +69,6 @@ class IntegrationTestCase(TestCase): self.create_account('viewtest', email, password) self.activate_user(email) self.login(email, password) - xmodule.modulestore.django._MODULESTORES = {} - xmodule.modulestore.django.modulestore().collection.drop() - # ============ User creation and login ============== @@ -107,15 +126,22 @@ class IntegrationTestCase(TestCase): # Now make sure that the user is now actually activated self.assertTrue(user(email).is_active) - # ============ Page loading ============== + def test_activate_login(self): + '''The setup function does all the work''' + pass + - def check_pages_load(self, test_course_name): - import_from_xml(modulestore(), TEST_DATA_DIR, [test_course_name]) +class PageLoader(ActivateLoginTestCase): + ''' Base class that adds a function to load all pages in a modulestore ''' + + def check_pages_load(self, course_name, data_dir, modstore): + print "Checking course {0} in {1}".format(course_name, data_dir) + import_from_xml(modstore, data_dir, [course_name]) n = 0 num_bad = 0 all_ok = True - for descriptor in modulestore().get_items( + for descriptor in modstore.get_items( Location(None, None, None, None, None)): n += 1 print "Checking ", descriptor.location.url() @@ -129,16 +155,54 @@ class IntegrationTestCase(TestCase): all_ok = False num_bad += 1 print msg - self.assertTrue(all_ok) + self.assertTrue(all_ok) # fail fast print "{0}/{1} good".format(n - num_bad, n) + self.assertTrue(all_ok) + +@override_settings(MODULESTORE=TEST_DATA_MODULESTORE) +class TestCoursesLoadTestCase(PageLoader): + '''Check that all pages in test courses load properly''' + + def setUp(self): + ActivateLoginTestCase.setUp(self) + xmodule.modulestore.django._MODULESTORES = {} + xmodule.modulestore.django.modulestore().collection.drop() def test_toy_course_loads(self): - self.check_pages_load('toy') + self.check_pages_load('toy', TEST_DATA_DIR, modulestore()) def test_full_course_loads(self): - self.check_pages_load('full') + self.check_pages_load('full', TEST_DATA_DIR, modulestore()) + + + # ========= TODO: check ajax interaction here too? + + +@override_settings(MODULESTORE=REAL_DATA_MODULESTORE) +class RealCoursesLoadTestCase(PageLoader): + '''Check that all pages in real courses load properly''' + + def setUp(self): + ActivateLoginTestCase.setUp(self) + xmodule.modulestore.django._MODULESTORES = {} + xmodule.modulestore.django.modulestore().collection.drop() + + # TODO: Disabled test for now.. Fix once things are cleaned up. + def Xtest_real_courses_loads(self): + '''See if any real courses are available at the REAL_DATA_DIR. + If they are, check them.''' + + # TODO: adjust staticfiles_dirs + if not os.path.isdir(REAL_DATA_DIR): + # No data present. Just pass. + return + + courses = [course_dir for course_dir in os.listdir(REAL_DATA_DIR) + if os.path.isdir(REAL_DATA_DIR / course_dir)] + for course in courses: + self.check_pages_load(course, REAL_DATA_DIR, modulestore()) # ========= TODO: check ajax interaction here too? diff --git a/lms/envs/common.py b/lms/envs/common.py index c9b44bca4038ab78799d85334b66585fad79215b..c071e61bb47734defad2f76d614f5129ba275baa 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -61,7 +61,7 @@ PROJECT_ROOT = path(__file__).abspath().dirname().dirname() # /mitx/lms REPO_ROOT = PROJECT_ROOT.dirname() COMMON_ROOT = REPO_ROOT / "common" ENV_ROOT = REPO_ROOT.dirname() # virtualenv dir /mitx is in -ASKBOT_ROOT = ENV_ROOT / "askbot-devel" +ASKBOT_ROOT = REPO_ROOT / "askbot" COURSES_ROOT = ENV_ROOT / "data" # FIXME: To support multiple courses, we should walk the courses dir at startup diff --git a/lms/envs/test.py b/lms/envs/test.py index ef63063b51feacf38c5b0aeeb5d6e21320e69a64..e6fedcb373ab272d059f8d81e305ea7c7697f098 100644 --- a/lms/envs/test.py +++ b/lms/envs/test.py @@ -12,15 +12,18 @@ from .logsettings import get_logger_config import os from path import path -INSTALLED_APPS = [ - app - for app - in INSTALLED_APPS - if not app.startswith('askbot') -] +# can't test start dates with this True, but on the other hand, +# can test everything else :) +MITX_FEATURES['DISABLE_START_DATES'] = True + +# Need wiki for courseware views to work. TODO (vshnayder): shouldn't need it. +WIKI_ENABLED = True + +# Makes the tests run much faster... +SOUTH_TESTS_MIGRATE = False # To disable migrations and use syncdb instead # Nose Test Runner -INSTALLED_APPS += ['django_nose'] +INSTALLED_APPS += ('django_nose',) NOSE_ARGS = ['--cover-erase', '--with-xunit', '--with-xcoverage', '--cover-html', '--cover-inclusive', '--cover-html-dir', os.environ.get('NOSE_COVER_HTML_DIR', 'cover_html')] @@ -35,12 +38,6 @@ STATIC_ROOT = TEST_ROOT / "staticfiles" COURSES_ROOT = TEST_ROOT / "data" DATA_DIR = COURSES_ROOT -MAKO_TEMPLATES['course'] = [DATA_DIR] -MAKO_TEMPLATES['sections'] = [DATA_DIR / 'sections'] -MAKO_TEMPLATES['custom_tags'] = [DATA_DIR / 'custom_tags'] -MAKO_TEMPLATES['main'] = [PROJECT_ROOT / 'templates', - DATA_DIR / 'info', - DATA_DIR / 'problems'] LOGGING = get_logger_config(TEST_ROOT / "log", logging_env="dev", @@ -48,6 +45,9 @@ LOGGING = get_logger_config(TEST_ROOT / "log", debug=True) COMMON_TEST_DATA_ROOT = COMMON_ROOT / "test" / "data" +# Where the content data is checked out. This may not exist on jenkins. +GITHUB_REPO_ROOT = ENV_ROOT / "data" + # TODO (cpennington): We need to figure out how envs/test.py can inject things # into common.py so that we don't have to repeat this sort of thing diff --git a/lms/envs/test_mongo.py b/lms/envs/test_mongo.py deleted file mode 100644 index cbf9209c9666296119a04451285e925b33890a36..0000000000000000000000000000000000000000 --- a/lms/envs/test_mongo.py +++ /dev/null @@ -1,113 +0,0 @@ -""" -This config file runs the test environment, but with mongo as the datastore -""" -from .common import * - -from .logsettings import get_logger_config -import os -from path import path - -# can't testing start dates with this True, but on the other hand, -# can test everything else :) -MITX_FEATURES['DISABLE_START_DATES'] = True - -WIKI_ENABLED = True - -GITHUB_REPO_ROOT = ENV_ROOT / "data" - -MODULESTORE = { - 'default': { - 'ENGINE': 'xmodule.modulestore.mongo.MongoModuleStore', - 'OPTIONS': { - 'default_class': 'xmodule.raw_module.RawDescriptor', - 'host': 'localhost', - 'db': 'xmodule', - 'collection': 'modulestore', - 'fs_root': GITHUB_REPO_ROOT, - } - } -} - - -# Nose Test Runner -INSTALLED_APPS += ('django_nose',) -NOSE_ARGS = ['--cover-erase', '--with-xunit', '--with-xcoverage', '--cover-html', - '--cover-inclusive', '--cover-html-dir', - os.environ.get('NOSE_COVER_HTML_DIR', 'cover_html')] -for app in os.listdir(PROJECT_ROOT / 'djangoapps'): - NOSE_ARGS += ['--cover-package', app] -TEST_RUNNER = 'django_nose.NoseTestSuiteRunner' - - -TEST_ROOT = path("test_root") -# Want static files in the same dir for running on jenkins. -STATIC_ROOT = TEST_ROOT / "staticfiles" - - - -LOGGING = get_logger_config(TEST_ROOT / "log", - logging_env="dev", - tracking_filename="tracking.log", - debug=True) - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': PROJECT_ROOT / "db" / "mitx.db", - } -} - -CACHES = { - # This is the cache used for most things. Askbot will not work without a - # functioning cache -- it relies on caching to load its settings in places. - # In staging/prod envs, the sessions also live here. - 'default': { - 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', - 'LOCATION': 'mitx_loc_mem_cache', - 'KEY_FUNCTION': 'util.memcache.safe_key', - }, - - # The general cache is what you get if you use our util.cache. It's used for - # things like caching the course.xml file for different A/B test groups. - # We set it to be a DummyCache to force reloading of course.xml in dev. - # In staging environments, we would grab VERSION from data uploaded by the - # push process. - 'general': { - 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', - 'KEY_PREFIX': 'general', - 'VERSION': 4, - 'KEY_FUNCTION': 'util.memcache.safe_key', - } -} - -# Dummy secret key for dev -SECRET_KEY = '85920908f28904ed733fe576320db18cabd7b6cd' - -# Makes the tests run much faster... -SOUTH_TESTS_MIGRATE = False # To disable migrations and use syncdb instead - -############################ FILE UPLOADS (ASKBOT) ############################# -DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' -MEDIA_ROOT = TEST_ROOT / "uploads" -MEDIA_URL = "/static/uploads/" -STATICFILES_DIRS.append(("uploads", MEDIA_ROOT)) - -new_staticfiles_dirs = [] -# Strip out any static files that aren't in the repository root -# so that the tests can run with only the mitx directory checked out -for static_dir in STATICFILES_DIRS: - # Handle both tuples and non-tuple directory definitions - try: - _, data_dir = static_dir - except ValueError: - data_dir = static_dir - - if data_dir.startswith(REPO_ROOT): - new_staticfiles_dirs.append(static_dir) -STATICFILES_DIRS = new_staticfiles_dirs - -FILE_UPLOAD_TEMP_DIR = PROJECT_ROOT / "uploads" -FILE_UPLOAD_HANDLERS = ( - 'django.core.files.uploadhandler.MemoryFileUploadHandler', - 'django.core.files.uploadhandler.TemporaryFileUploadHandler', -)