28

I'm having a hard time customizing the test database setup behavior. I would like to achieve the following:

  • The test suites need to use an existing database
  • The test suite shouldn't erase or recreate the database instead load the data from a mysql dump
  • Since the db is populated from a dump, no fixtures should be loaded
  • Upon finishing tests the database shouldn't be destroyed

I'm having a hard time getting the testsuiterunner to bypass creation.

endre
  • 1,363
  • 1
  • 11
  • 22
  • In what way are you using the existing database if you are loading data from an sql dump? I would suggest loading the dump, creating fixtures, and using the conventional testing approach. – shanyu Jun 06 '11 at 10:27
  • 2
    there is a lot of data and loading from dump is faster than loading from fixtures – endre Jun 06 '11 at 10:28
  • So it is not about using the existing database. Are you 100% sure that you need to do the testing using the complete data? Can a sample be sufficient for testing? – shanyu Jun 06 '11 at 10:37
  • 1
    not "the" existing database,but "an" existing database that contains part of the data. – endre Jun 06 '11 at 10:43
  • 3
    Tests are design to build and subsequently tear down a database for a reason. They're not supposed to be interacting with data that has any persistence. I think you'll find it very difficult to change this behavior *if* it's even possible. You best bet is to use fixtures or a sqldump as the others suggested. – Chris Pratt Jun 06 '11 at 15:10
  • Disappointing that no one has an answer for this. We have 6 GB read-only database with a _ton_ of lookup tables that would need to be in place for tests to work... (Most of the data copied from elsewhere, but it would be oh so much more efficient to just use the existing db, instead of extracting the lookups or just dumping the entire thing) – Izkata Apr 03 '13 at 18:28
  • 4
    Hey, if you also got here from Google like me, see here: http://stackoverflow.com/questions/4606756/how-can-i-specify-a-database-for-django-tests-to-use-instead-of-having-it-build – Izkata Apr 03 '13 at 18:30
  • @Izkata starting a bounty will make the question more visible to other community members. – Filip Dupanović Sep 20 '13 at 14:05
  • The docs say: "If you require data for a test case, you should add it using either a test fixture, or programmatically add it during the setUp() of your test case." https://docs.djangoproject.com/en/dev/howto/initial-data/#providing-initial-sql-data – wobbily_col Feb 12 '14 at 10:20
  • possible duplicate of [How to run django unit-tests on production database?](http://stackoverflow.com/questions/1646468/how-to-run-django-unit-tests-on-production-database) – Stefano Jun 19 '14 at 16:30
  • Duplicate of both http://stackoverflow.com/questions/1646468/ and already mentioned http://stackoverflow.com/questions/4606756/ – Stefano Jun 19 '14 at 16:31

3 Answers3

14

Fast forward to 2016 and the ability to retain the database between tests has been built into django. It's available in the form of the --keep flag to manage.py

New in Django 1.8. Preserves the test database between test runs. This has the advantage of skipping both the create and destroy actions which can greatly decrease the time to run tests, especially those in a large test suite. If the test database does not exist, it will be created on the first run and then preserved for each subsequent run. Any unapplied migrations will also be applied to the test database before running the test suite.

This pretty much fullfills all the criteria you have mentioned in your questions. In fact it even goes one step further. There is no need to import the dump before each and every run.

e4c5
  • 52,766
  • 11
  • 101
  • 134
  • Above link(--keep flag) is broken now https://docs.djangoproject.com/en/3.1/ref/django-admin/#cmdoption-test-keepdb – Copperhead Apr 20 '21 at 19:27
4

This TEST_RUNNER works in Django 1.3

from django.test.simple import DjangoTestSuiteRunner as TestRunner

class DjangoTestSuiteRunner(TestRunner):
    def setup_databases(self, **kwargs):
        pass

    def teardown_databases(self, old_config, **kwargs):
        pass
Noel Pure
  • 422
  • 2
  • 13
0

You'll need to provide a custom test runner.

The bits your interested in overriding with the default django.test.runner.DiscoverRunner are the DiscoverRunner.setup_databases and DiscoverRunner.teardown_databases methods. These two methods are involved with creating and destroying test databases and are executed only once. You'll want to provide test-specific project settings that use your existing test database by default and override these so that the dump data is loaded and the test database isn't destroyed.

Depending on the size and contents of the dump, a safe bet might be to just create a subprocess that will pipe the dump to your database's SQL command-line interface, otherwise you might be able to obtain a cursor and execute queries directly.

If your looking to get rid of fixture loading completely, you can provide a custom base test case that extends Django's default django.test.testcases.TestCase with the TestCase._fixutre_setup and TestCase._fixutre_teardown methods overriden to be noop.

Caveat emptor: this runner will make it impossible to facilitate tests for anything but your application's sources. It's possible to customize the runner to create a specific alias for a connection to your existing database and load the dump, then provide a custom test case that overrides TestCase._database_names to point to it's alias.

Filip Dupanović
  • 32,650
  • 13
  • 84
  • 114