Permalink
Browse files

refactoring, updated docs and version bumped to 0.3

  • Loading branch information...
Martin Rusev
Martin Rusev committed Jun 30, 2011
1 parent eea0e72 commit 7379eb0651fcd9f687446341f03d8ce9ef859aea
View
@@ -1,4 +1,4 @@
-Copyright (c) 2010, Martin Rusev
+Copyright (c) 2010-2011, Martin Rusev
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -25,4 +25,4 @@ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
View
@@ -1,83 +0,0 @@
-# django-better-tests
-
-
-This is a collection of commands for your django projects, that separates
-test database creation from the actual test run
-
-
-The advantages of using this over 'manage.py test' is that you control both
-the database creation and the test run
-
-
-## Installation
-
-
-1. Either download the tarball and run ``python setup.py install``,
-
-2. Add ``django_better_tests`` to your INSTALLED_APPS in settings.py:
-
-
- INSTALLED_APPS = ('django_better_tests')
-
-
-
-3. Add test database details in settings.py
-
-
- DATABASES = {
- 'default':{
- 'ENGINE':''},
- 'test':{
- 'ENGINE': '',
- 'NAME': 'test_database',
- }
- }
-
-
-4. Then set TEST_RUNNER in settings.py:
-
- TEST_RUNNER = 'django_better_tests.NoseTestSuiteRunner'
-
-
-
-## Usage
-
-
-Once installed, using the new test suite runner replacement is easy. Create your test database with::
-
- python manage.py create_test_db
-
-After that run your tests with
-
- python manage.py quick_test
-
-
-And finally if you want destroy the test database with
-
- python manage.py destroy_test_db
-
-
-
-## Alternative usage
-
-
-You can use just the quick_test command and manualy update the database only when needed.
-
-Manual commands
-
- python manage.py syncdb --database=test
- python manage.py migrate --database=test
-
-and after that only
-
- python manage.py quick_test
-
-
-
-## Requirements
-
-
-Django 1.2+
-
-nose
-
View
@@ -0,0 +1,114 @@
+=================
+django-quick-test
+=================
+
+Django quick test is a custom nose based test runner that
+separates testing and test related database manipulations.
+
+
+Usualy running this command instead of the default ``manage.py test``
+will give you 10-15 times speed boost. So you will be able to run
+your test suite in seconds instead of minutes.
+
+===============
+ Installation
+===============
+
+
+1. Download the tarball and run ``python setup.py install``
+
+2. Add ``quick_test`` to your INSTALLED_APPS list in settings.py
+
+
+::
+
+ INSTALLED_APPS = ('quick_test')
+
+
+
+3. Add your test database details in settings.py
+
+::
+ DATABASES = {
+ 'default':{
+ 'ENGINE':''},
+ 'test':{
+ 'ENGINE': '',
+ 'NAME': 'test_database',
+ }
+ }
+
+
+4. And finally replace the default Django test runner with this one. Again in settings.py:
+
+::
+
+ TEST_RUNNER = 'quick_test.NoseTestSuiteRunner'
+
+
+=========
+ Usage
+=========
+
+django-quick-test assumes that you have created your test database manualy and
+you have loaded the required test data(fixtures)
+
+
+
+Commands you have to run before using the command
+
+::
+ python manage.py syncdb --database=test
+ python manage.py migrate --database=test
+
+
+and finaly run your tests with
+
+::
+ python manage.py quick_test
+
+
+==================
+ Additional notes
+==================
+
+
+If you are using the default Django TestCase class
+you have to ovewrite the ``_pre_setup`` method which is executed
+automatically when you call the class. If you don't overwrite it
+the ``quick_test`` command will still work, but your test data
+will be lost. Even if you don't have any fixtures in the database
+overwriting this method will give you additional speed boost.
+
+::
+
+ from django.test import TestCase
+
+ class SimpleTest(TestCase)
+
+ def _pre_setup(self):
+ # this method flushes the database and installs
+ # the fixtures defined in the fixtures=[] list
+ # we are doing everything manually, so we don't
+ # really need it
+
+ # these are the results I get with 1 test before
+ and after ovewriting the method
+ # Before -> Ran 1 test in 2.336s
+ # After -> Ran 1 test in 0.004s
+ pass
+
+ def test_basic_addition(self):
+ self.assertEqual(1 + 1, 2)
+
+
+
+===============
+ Requirements
+===============
+
+
+Django 1.2+
+
+nose
+
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -15,14 +15,13 @@ class Command(BaseCommand):
requires_model_validation = False
def handle(self, *test_labels, **options):
- from django.conf import settings
verbosity = int(options.get('verbosity', 1))
interactive = options.get('interactive', True)
failfast = options.get('failfast', False)
- test_module = __import__('django_better_tests.testrunner', {}, {}, 'NoseTestSuiteRunner')
+ test_module = __import__('quick_test.testrunner', {}, {}, 'NoseTestSuiteRunner')
TestRunner = getattr(test_module, 'NoseTestSuiteRunner')
if hasattr(TestRunner, 'func_name'):
@@ -0,0 +1,99 @@
+import os
+import sys
+from django.conf import settings
+from django.core.management.base import BaseCommand
+from django.test.simple import DjangoTestSuiteRunner
+from django.db import connection
+import nose.core
+from plugin import ResultPlugin
+
+try:
+ any
+except NameError:
+ def any(iterable):
+ for element in iterable:
+ if element:
+ return True
+ return False
+
+# This is a table of Django's "manage.py test" options which
+# correspond to nosetests options with a different name:
+OPTION_TRANSLATION = {'--failfast': '-x'}
+
+
+class NoseTestSuiteRunner(DjangoTestSuiteRunner):
+
+ def run_suite(self, nose_argv):
+ result_plugin = ResultPlugin()
+ nose.core.TestProgram(argv=nose_argv, exit=False,
+ addplugins=[result_plugin])
+ return result_plugin.result
+
+ def run_tests(self, test_labels, extra_tests=None):
+ """
+ Run the unit tests for all the test names in the provided list.
+
+ Test names specified may be file or module names, and may optionally
+ indicate the test case to run by separating the module or file name
+ from the test case name with a colon. Filenames may be relative or
+ absolute. Examples:
+
+ runner.run_tests('test.module')
+ runner.run_tests('another.test:TestCase.test_method')
+ runner.run_tests('a.test:TestCase')
+ runner.run_tests('/path/to/test/file.py:test_function')
+
+ Returns the number of tests that failed.
+ """
+
+ settings.DEBUG = False
+
+ self.setup_test_environment()
+
+ try:
+ settings.DATABASES['default']['SUPPORTS_TRANSACTIONS'] = connection.creation._rollback_works()
+ settings.DATABASES['test']['SUPPORTS_TRANSACTIONS'] = connection.creation._rollback_works()
+ except:
+ # the database engine doesn't support transactions
+ pass
+
+ nose_argv = ['nosetests', '--verbosity', str(self.verbosity)]
+
+ if hasattr(settings, 'NOSE_ARGS'):
+ nose_argv.extend(settings.NOSE_ARGS)
+
+ # Skip over 'manage.py test' and any arguments handled by django.
+ django_opts = ['--noinput']
+ for opt in BaseCommand.option_list:
+ django_opts.extend(opt._long_opts)
+ django_opts.extend(opt._short_opts)
+
+ nose_argv.extend(OPTION_TRANSLATION.get(opt, opt)
+ for opt in sys.argv[2:]
+ if not any(opt.startswith(d) for d in django_opts))
+
+ if self.verbosity >= 1:
+ print ' '.join(nose_argv)
+
+
+ result = self.run_suite(nose_argv)
+
+ self.teardown_test_environment()
+ # suite_result expects the suite as the first argument. Fake it.
+ return self.suite_result({}, result)
+
+
+def _get_options():
+ """Return all nose options that don't conflict with django options."""
+ cfg_files = nose.core.all_config_files()
+ manager = nose.core.DefaultPluginManager()
+ config = nose.core.Config(env=os.environ, files=cfg_files, plugins=manager)
+ options = config.getParser().option_list
+ django_opts = [opt.dest for opt in BaseCommand.option_list] + ['version']
+ return tuple(o for o in options if o.dest not in django_opts and
+ o.action != 'help')
+
+
+# Replace the builtin command options with the merged django/nose options.
+NoseTestSuiteRunner.options = _get_options()
+NoseTestSuiteRunner.__test__ = False
Binary file not shown.
@@ -1,18 +0,0 @@
-from django.core.management.base import BaseCommand
-from optparse import make_option
-import sys
-from django.db import connection
-from django.conf import settings
-from django.core.management import call_command
-
-class Command(BaseCommand):
- help = 'Creates the test db'
-
- def handle(self, *args, **options):
- connection.creation.create_test_db(verbosity = 1, autoclobber=False)
- call_command('migrate', database='test', app=None,
- target=None, skip=False, merge=False, backwards=False, fake=False, db_dry_run=False, show_list=False)
-
- connection.close()
-
-
@@ -1,25 +0,0 @@
-from django.core.management.base import BaseCommand
-from django.db import connections, connection
-from django.conf import settings
-import time
-
-
-TEST_DATABASE_NAME = settings.DATABASES['test']['NAME']
-
-class Command(BaseCommand):
- help = 'Destroys the test db'
-
- def handle(self, *args, **options):
-
- connection.close()
- if settings.DATABASES['default'] != "sqlite3":
-
- cursor = connections['default'].cursor() #connect to the real database to avoid 'cannot drop the currently open database'
- try:
- cursor.execute('commit')
- except AttributeError:
- pass
- else:
- time.sleep(2) # To avoid "database is being accessed by other users" errors.
- cursor.execute("DROP DATABASE %s" % TEST_DATABASE_NAME)
-
Oops, something went wrong.

0 comments on commit 7379eb0

Please sign in to comment.