From 09dc884c38b0cc94add17397f7fff8c9ed57efe8 Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Wed, 4 May 2016 14:33:42 -0400 Subject: [PATCH] Isolate databases between test processes --- cms/envs/test.py | 4 ++++ lms/envs/test.py | 6 ++++-- openedx/core/djangolib/testing/utils.py | 20 ++++++++++++++++++++ scripts/generic-ci-tests.sh | 11 ++++++----- 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/cms/envs/test.py b/cms/envs/test.py index 18bf787368..ce5f618b2e 100644 --- a/cms/envs/test.py +++ b/cms/envs/test.py @@ -57,6 +57,10 @@ NOSE_ARGS = [ '--xunit-file', _REPORT_DIR / 'nosetests.xml', ] +NOSE_PLUGINS = [ + 'openedx.core.djangolib.testing.utils.NoseDatabaseIsolation' +] + TEST_ROOT = path('test_root') # Want static files in the same dir for running on jenkins. diff --git a/lms/envs/test.py b/lms/envs/test.py index 344a9ddc47..cda9f23b46 100644 --- a/lms/envs/test.py +++ b/lms/envs/test.py @@ -99,6 +99,10 @@ NOSE_ARGS = [ '--xunit-file', _REPORT_DIR / 'nosetests.xml', ] +NOSE_PLUGINS = [ + 'openedx.core.djangolib.testing.utils.NoseDatabaseIsolation' +] + # Local Directories TEST_ROOT = path("test_root") # Want static files in the same dir for running on jenkins. @@ -181,12 +185,10 @@ CONTENTSTORE = { DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': TEST_ROOT / 'db' / 'edx.db', 'ATOMIC_REQUESTS': True, }, 'student_module_history': { 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': TEST_ROOT / 'db' / 'student_module_history.db' }, } diff --git a/openedx/core/djangolib/testing/utils.py b/openedx/core/djangolib/testing/utils.py index 5a6efbfaa0..512beec7d9 100644 --- a/openedx/core/djangolib/testing/utils.py +++ b/openedx/core/djangolib/testing/utils.py @@ -10,11 +10,14 @@ Utility classes for testing django applications. import copy +from django import db from django.core.cache import caches from django.test import TestCase, override_settings from django.conf import settings from django.contrib import sites +from nose.plugins import Plugin + from request_cache.middleware import RequestCache @@ -138,3 +141,20 @@ class CacheIsolationTestCase(CacheIsolationMixin, TestCase): self.clear_caches() self.addCleanup(self.clear_caches) + + +class NoseDatabaseIsolation(Plugin): + """ + nosetest plugin that resets django databases before any tests begin. + + Used to make sure that tests running in multi processes aren't sharing + a database connection. + """ + name = "database-isolation" + + def begin(self): + """ + Before any tests start, reset all django database connections. + """ + for db_ in db.connections.all(): + db_.close() diff --git a/scripts/generic-ci-tests.sh b/scripts/generic-ci-tests.sh index 64bb98f011..df155dfcd8 100755 --- a/scripts/generic-ci-tests.sh +++ b/scripts/generic-ci-tests.sh @@ -97,21 +97,22 @@ case "$TEST_SUITE" in ;; "lms-unit") + LMS_ARGS="--with-flaky" case "$SHARD" in "all") - paver test_system -s lms --extra_args="--with-flaky" --cov_args="-p" + paver test_system -s lms --extra_args="$LMS_ARGS" --cov_args="-p" -v ;; "1") - paver test_system -s lms --extra_args="--attr='shard_1' --with-flaky" --cov_args="-p" -v + paver test_system -s lms --extra_args="--attr='shard_1' $LMS_ARGS" --cov_args="-p" -v ;; "2") - paver test_system -s lms --extra_args="--attr='shard_2' --with-flaky" --cov_args="-p" -v + paver test_system -s lms --extra_args="--attr='shard_2' $LMS_ARGS" --cov_args="-p" -v ;; "3") - paver test_system -s lms --extra_args="--attr='shard_3' --with-flaky" --cov_args="-p" -v + paver test_system -s lms --extra_args="--attr='shard_3' $LMS_ARGS" --cov_args="-p" -v ;; "4") - paver test_system -s lms --extra_args="--attr='shard_1=False,shard_2=False,shard_3=False' --with-flaky" --cov_args="-p" -v + paver test_system -s lms --extra_args="--attr='shard_1=False,shard_2=False,shard_3=False' $LMS_ARGS" --cov_args="-p" -v ;; *) # If no shard is specified, rather than running all tests, create an empty xunit file. This is a