Config for integration tests
* move askbot repo into mitx as a submodule * set settings as in 85865f7221 * remove test_mongo env. * Refactor tests to use new config structure. * Add real integration tests--not working due to bugs in course xml. Turned off.
This commit is contained in:
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "askbot"]
|
||||
path = askbot
|
||||
url = git@github.com:MITx/askbot-devel.git
|
||||
1
askbot
Submodule
1
askbot
Submodule
Submodule askbot added at 1c3381046c
@@ -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?
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
)
|
||||
Reference in New Issue
Block a user