diff --git a/cms/djangoapps/contentstore/features/upload.py b/cms/djangoapps/contentstore/features/upload.py index 977bad8fea..0c700956e3 100644 --- a/cms/djangoapps/contentstore/features/upload.py +++ b/cms/djangoapps/contentstore/features/upload.py @@ -9,7 +9,7 @@ import random import os TEST_ROOT = settings.COMMON_TEST_DATA_ROOT -HTTP_PREFIX = "http://localhost:8001" +HTTP_PREFIX = "http://localhost:%s" % settings.LETTUCE_SERVER_PORT @step(u'I go to the files and uploads page') diff --git a/cms/envs/acceptance.py b/cms/envs/acceptance.py index 4d1f1f2a4b..ecd22ed769 100644 --- a/cms/envs/acceptance.py +++ b/cms/envs/acceptance.py @@ -16,12 +16,18 @@ DEBUG = True # Disable warnings for acceptance tests, to make the logs readable import logging logging.disable(logging.ERROR) +import os +import random + + +def seed(): + return os.getppid() MODULESTORE_OPTIONS = { 'default_class': 'xmodule.raw_module.RawDescriptor', 'host': 'localhost', - 'db': 'test_xmodule', - 'collection': 'acceptance_modulestore', + 'db': 'acceptance_xmodule', + 'collection': 'acceptance_modulestore_%s' % seed(), 'fs_root': TEST_ROOT / "data", 'render_template': 'mitxmako.shortcuts.render_to_string', } @@ -45,7 +51,7 @@ CONTENTSTORE = { 'ENGINE': 'xmodule.contentstore.mongo.MongoContentStore', 'OPTIONS': { 'host': 'localhost', - 'db': 'acceptance_xcontent', + 'db': 'acceptance_xcontent_%s' % seed(), }, # allow for additional options that can be keyed on a name, e.g. 'trashcan' 'ADDITIONAL_OPTIONS': { @@ -61,13 +67,13 @@ CONTENTSTORE = { DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': TEST_ROOT / "db" / "test_mitx.db", - 'TEST_NAME': TEST_ROOT / "db" / "test_mitx.db", + 'NAME': TEST_ROOT / "db" / "test_mitx_%s.db" % seed(), + 'TEST_NAME': TEST_ROOT / "db" / "test_mitx_%s.db" % seed(), } } # Include the lettuce app for acceptance testing, including the 'harvest' django-admin command INSTALLED_APPS += ('lettuce.django',) LETTUCE_APPS = ('contentstore',) -LETTUCE_SERVER_PORT = 8001 +LETTUCE_SERVER_PORT = random.randint(1024, 65535) LETTUCE_BROWSER = 'chrome' diff --git a/cms/envs/acceptance_static.py b/cms/envs/acceptance_static.py new file mode 100644 index 0000000000..f7d69794fb --- /dev/null +++ b/cms/envs/acceptance_static.py @@ -0,0 +1,77 @@ +""" +This config file extends the test environment configuration +so that we can run the lettuce acceptance tests. +This is used in the django-admin call as acceptance.py +contains random seeding, causing django-admin to create a random collection +""" + +# We intentionally define lots of variables that aren't used, and +# want to import all variables from base settings files +# pylint: disable=W0401, W0614 + +from .test import * + +# You need to start the server in debug mode, +# otherwise the browser will not render the pages correctly +DEBUG = True + +# Disable warnings for acceptance tests, to make the logs readable +import logging +logging.disable(logging.ERROR) +import os +import random + +MODULESTORE_OPTIONS = { + 'default_class': 'xmodule.raw_module.RawDescriptor', + 'host': 'localhost', + 'db': 'acceptance_xmodule', + 'collection': 'acceptance_modulestore', + 'fs_root': TEST_ROOT / "data", + 'render_template': 'mitxmako.shortcuts.render_to_string', +} + +MODULESTORE = { + 'default': { + 'ENGINE': 'xmodule.modulestore.draft.DraftModuleStore', + 'OPTIONS': MODULESTORE_OPTIONS + }, + 'direct': { + 'ENGINE': 'xmodule.modulestore.mongo.MongoModuleStore', + 'OPTIONS': MODULESTORE_OPTIONS + }, + 'draft': { + 'ENGINE': 'xmodule.modulestore.draft.DraftModuleStore', + 'OPTIONS': MODULESTORE_OPTIONS + } +} + +CONTENTSTORE = { + 'ENGINE': 'xmodule.contentstore.mongo.MongoContentStore', + 'OPTIONS': { + 'host': 'localhost', + 'db': 'acceptance_xcontent', + }, + # allow for additional options that can be keyed on a name, e.g. 'trashcan' + 'ADDITIONAL_OPTIONS': { + 'trashcan': { + 'bucket': 'trash_fs' + } + } +} + +# Set this up so that rake lms[acceptance] and running the +# harvest command both use the same (test) database +# which they can flush without messing up your dev db +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': TEST_ROOT / "db" / "test_mitx.db", + 'TEST_NAME': TEST_ROOT / "db" / "test_mitx.db", + } +} + +# Include the lettuce app for acceptance testing, including the 'harvest' django-admin command +INSTALLED_APPS += ('lettuce.django',) +LETTUCE_APPS = ('contentstore',) +LETTUCE_SERVER_PORT = random.randint(1024, 65535) +LETTUCE_BROWSER = 'chrome' diff --git a/common/djangoapps/terrain/browser.py b/common/djangoapps/terrain/browser.py index d237edc4b7..0c1303ed1a 100644 --- a/common/djangoapps/terrain/browser.py +++ b/common/djangoapps/terrain/browser.py @@ -17,6 +17,9 @@ from selenium.common.exceptions import WebDriverException # These names aren't used, but do important work on import. from lms import one_time_startup # pylint: disable=W0611 from cms import one_time_startup # pylint: disable=W0611 +from pymongo import MongoClient +import xmodule.modulestore.django +from xmodule.contentstore.django import _CONTENTSTORE # There is an import issue when using django-staticfiles with lettuce # Lettuce assumes that we are using django.contrib.staticfiles, @@ -87,6 +90,22 @@ def reset_data(scenario): LOGGER.debug("Flushing the test database...") call_command('flush', interactive=False) + +@after.each_scenario +def reset_databases(scenario): + ''' + After each scenario, all databases are cleared/dropped. Contentstore data are stored in unique databases + whereas modulestore data is in unique collection names. This data is created implicitly during the scenarios. + If no data is created during the test, these lines equivilently do nothing. + ''' + mongo = MongoClient() + mongo.drop_database(settings.CONTENTSTORE['OPTIONS']['db']) + _CONTENTSTORE.clear() + modulestore = xmodule.modulestore.django.modulestore() + modulestore.collection.drop() + xmodule.modulestore.django._MODULESTORES.clear() + + # Uncomment below to trigger a screenshot on error # @after.each_scenario def screenshot_on_error(scenario): diff --git a/lms/envs/acceptance.py b/lms/envs/acceptance.py index 3b87bb4326..087c1ca85c 100644 --- a/lms/envs/acceptance.py +++ b/lms/envs/acceptance.py @@ -16,13 +16,19 @@ DEBUG = True # Disable warnings for acceptance tests, to make the logs readable import logging logging.disable(logging.ERROR) +import os +import random + + +def seed(): + return os.getppid() # Use the mongo store for acceptance tests modulestore_options = { 'default_class': 'xmodule.raw_module.RawDescriptor', 'host': 'localhost', - 'db': 'test_xmodule', - 'collection': 'acceptance_modulestore', + 'db': 'acceptance_xmodule', + 'collection': 'acceptance_modulestore_%s' % seed(), 'fs_root': TEST_ROOT / "data", 'render_template': 'mitxmako.shortcuts.render_to_string', } @@ -42,7 +48,7 @@ CONTENTSTORE = { 'ENGINE': 'xmodule.contentstore.mongo.MongoContentStore', 'OPTIONS': { 'host': 'localhost', - 'db': 'test_xmodule', + 'db': 'acceptance_xcontent_%s' % seed(), } } @@ -52,14 +58,14 @@ CONTENTSTORE = { DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': TEST_ROOT / "db" / "test_mitx.db", - 'TEST_NAME': TEST_ROOT / "db" / "test_mitx.db", + 'NAME': TEST_ROOT / "db" / "test_mitx_%s.db" % seed(), + 'TEST_NAME': TEST_ROOT / "db" / "test_mitx_%s.db" % seed(), } } # Set up XQueue information so that the lms will send # requests to a mock XQueue server running locally -XQUEUE_PORT = 8027 +XQUEUE_PORT = random.randint(1024, 65535) XQUEUE_INTERFACE = { "url": "http://127.0.0.1:%d" % XQUEUE_PORT, "django_auth": { @@ -76,4 +82,5 @@ MITX_FEATURES['STUB_VIDEO_FOR_TESTING'] = True # Include the lettuce app for acceptance testing, including the 'harvest' django-admin command INSTALLED_APPS += ('lettuce.django',) LETTUCE_APPS = ('courseware',) +LETTUCE_SERVER_PORT = random.randint(1024, 65535) LETTUCE_BROWSER = 'chrome' diff --git a/lms/envs/acceptance_static.py b/lms/envs/acceptance_static.py new file mode 100644 index 0000000000..5672ea5bf5 --- /dev/null +++ b/lms/envs/acceptance_static.py @@ -0,0 +1,81 @@ +""" +This config file extends the test environment configuration +so that we can run the lettuce acceptance tests. +""" + +# We intentionally define lots of variables that aren't used, and +# want to import all variables from base settings files +# pylint: disable=W0401, W0614 + +from .test import * + +# You need to start the server in debug mode, +# otherwise the browser will not render the pages correctly +DEBUG = True + +# Disable warnings for acceptance tests, to make the logs readable +import logging +logging.disable(logging.ERROR) +import random + +# Use the mongo store for acceptance tests +modulestore_options = { + 'default_class': 'xmodule.raw_module.RawDescriptor', + 'host': 'localhost', + 'db': 'acceptance_xmodule', + 'collection': 'acceptance_modulestore', + 'fs_root': TEST_ROOT / "data", + 'render_template': 'mitxmako.shortcuts.render_to_string', +} + +MODULESTORE = { + 'default': { + 'ENGINE': 'xmodule.modulestore.mongo.MongoModuleStore', + 'OPTIONS': modulestore_options + }, + 'direct': { + 'ENGINE': 'xmodule.modulestore.mongo.MongoModuleStore', + 'OPTIONS': modulestore_options + } +} + +CONTENTSTORE = { + 'ENGINE': 'xmodule.contentstore.mongo.MongoContentStore', + 'OPTIONS': { + 'host': 'localhost', + 'db': 'acceptance_xcontent', + } +} + +# Set this up so that rake lms[acceptance] and running the +# harvest command both use the same (test) database +# which they can flush without messing up your dev db +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': TEST_ROOT / "db" / "test_mitx.db", + 'TEST_NAME': TEST_ROOT / "db" / "test_mitx.db", + } +} + +# Set up XQueue information so that the lms will send +# requests to a mock XQueue server running locally +XQUEUE_PORT = random.randint(1024, 65535) +XQUEUE_INTERFACE = { + "url": "http://127.0.0.1:%d" % XQUEUE_PORT, + "django_auth": { + "username": "lms", + "password": "***REMOVED***" + }, + "basic_auth": ('anant', 'agarwal'), +} + +# Do not display the YouTube videos in the browser while running the +# acceptance tests. This makes them faster and more reliable +MITX_FEATURES['STUB_VIDEO_FOR_TESTING'] = True + +# Include the lettuce app for acceptance testing, including the 'harvest' django-admin command +INSTALLED_APPS += ('lettuce.django',) +LETTUCE_APPS = ('courseware',) +LETTUCE_SERVER_PORT = random.randint(1024, 65535) +LETTUCE_BROWSER = 'chrome' diff --git a/rakelib/tests.rake b/rakelib/tests.rake index ebc2b92973..7e3e672f39 100644 --- a/rakelib/tests.rake +++ b/rakelib/tests.rake @@ -80,7 +80,9 @@ TEST_TASK_DIRS = [] # Run acceptance tests desc "Run acceptance tests" - task "test_acceptance_#{system}", [:harvest_args] => [:clean_test_files, "#{system}:gather_assets:acceptance", "fasttest_acceptance_#{system}"] + #gather_assets uses its own env because acceptance contains seeds to make the information unique + #acceptance_static is acceptance without the random seeding + task "test_acceptance_#{system}", [:harvest_args] => [:clean_test_files, "#{system}:gather_assets:acceptance_static", "fasttest_acceptance_#{system}"] desc "Run acceptance tests without collectstatic" task "fasttest_acceptance_#{system}", [:harvest_args] => [report_dir, :clean_reports_dir, :predjango] do |t, args|