a new test runner for blazing-fast tests

This commit is contained in:
Jeff Balogh 2010-02-01 11:24:26 -08:00
Родитель 8a7f5b7fd1
Коммит 0e86644055
4 изменённых файлов: 79 добавлений и 3 удалений

Просмотреть файл

@ -45,9 +45,17 @@ for the full set, but some common ones are:
Our continuous integration server adds some additional flags for other features
(for example, coverage statistics). To see what those commands are check out
the build script at ``/scripts/build.sh``.
the build script at :src:`scripts/build.sh`.
.. Would be nice to link to the actual script at some point.
Database Setup
~~~~~~~~~~~~~~
Our test runner will try as hard as it can to skip creating a fresh database
every time. If you really want to make a new database (e.g. when models have
changed), set the environment variable ``FORCE_DB``. ::
FORCE_DB=true python manage.py test
Writing Tests

67
lib/test_utils/runner.py Normal file
Просмотреть файл

@ -0,0 +1,67 @@
"""
This is a test runner that monkeypatches connection.creation to skip database
creation if it appears that the db already exists. Your tests will run much
faster.
To force the normal database creation, define the environment variable
"FORCE_DB". It doesn't really matter what the value is, we just check to see
if it's there.
"""
import os
from django.db import connections
from django.db.backends.creation import TEST_DATABASE_PREFIX
from django.db.backends.mysql import creation as mysql
import django_nose
# XXX: hard-coded to mysql.
class SkipDatabaseCreation(mysql.DatabaseCreation):
def _create_test_db(self, verbosity, autoclobber):
### Oh yes, let's copy from django/db/backends/creation.py
suffix = self.sql_table_creation_suffix()
if self.connection.settings_dict['TEST_NAME']:
test_database_name = self.connection.settings_dict['TEST_NAME']
else:
test_database_name = TEST_DATABASE_PREFIX + self.connection.settings_dict['NAME']
qn = self.connection.ops.quote_name
# Create the test database and connect to it. We need to autocommit
# if the database supports it because PostgreSQL doesn't allow
# CREATE/DROP DATABASE statements within transactions.
cursor = self.connection.cursor()
self.set_autocommit()
### That's enough copying.
# If we couldn't create the test db, assume it already exists.
try:
cursor.execute("CREATE DATABASE %s %s" %
(qn(test_database_name), suffix))
except Exception, e:
print '...Skipping setup of %s!' % test_database_name
print '...Try FORCE_DB=true if you need fresh databases.'
return test_database_name
# Drop the db we just created, then do the normal setup.
cursor.execute("DROP DATABASE %s %s" %
(qn(test_database_name), suffix))
return super(SkipDatabaseCreation, self)._create_test_db(
verbosity, autoclobber)
class RadicalTestSuiteRunner(django_nose.NoseTestSuiteRunner):
def setup_databases(self):
if not os.getenv('FORCE_DB'):
for alias in connections:
connection = connections[alias]
connection.creation.__class__ = SkipDatabaseCreation
return super(RadicalTestSuiteRunner, self).setup_databases()
def teardown_databases(self, old_config):
if os.getenv('FORCE_DB'):
super(RadicalTestSuiteRunner, self).teardown_databases(old_config)

Просмотреть файл

@ -23,6 +23,7 @@ ROOT_URLCONF = 'workspace.urls'
SETTINGS
echo "Starting tests..."
export FORCE_DB='yes sir'
coverage run manage.py test --noinput --logging-clear-handlers --with-xunit
coverage xml $(find apps lib -name '*.py')

Просмотреть файл

@ -184,7 +184,7 @@ DEV_APPS = (
'django_nose',
)
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
TEST_RUNNER = 'test_utils.runner.RadicalTestSuiteRunner'
LOG_LEVEL = logging.DEBUG