9

When I run test cases by typing

python manage.py test myapp

After test cases completed, test databases deleted by default by django test runner. I don't want it to be deleted.

I can use any database!

I want to preserve my database because there are bugs in database that I wanted to see in database that created. So that I can pinpoint them!

Braiam
  • 1
  • 11
  • 47
  • 78
Bilal Basharat
  • 3,066
  • 6
  • 21
  • 20
  • 1
    Are you using SQLite? Can you switch to MySQL? – S.Lott Jan 06 '11 at 11:18
  • possible duplicate: http://stackoverflow.com/questions/4606756/how-can-i-specify-a-database-for-django-tests-to-use-instead-of-having-it-build-i/4606983 – mouad Jan 06 '11 at 11:44
  • Maybe you could elaborate on the reason why you want to preserve the database? It's always possible this isn't your real problem but for example bad test code is. – KillianDS Jan 06 '11 at 13:18
  • can MySQL solve this problem. so that my test database remains – Bilal Basharat Jan 06 '11 at 14:24

6 Answers6

16

You can prevent the test databases from being destroyed by using the test --keepdb option.

https://docs.djangoproject.com/en/dev/topics/testing/overview/#the-test-database

Majid
  • 1,673
  • 18
  • 27
Tim Babych
  • 3,356
  • 1
  • 20
  • 13
10

While passing -k to manage.py test will retain the test database, it will still delete the records that was created in your test cases. This is because Django's TestCase classes will still reset your database after every test case (django.test.TransactionTestCase will do a flush, while django.test.TestCase will wrap each of your test case in a transaction and do a rollback when the test case is done).

The only real solution to making Django retain test data is to extend the TestCase class and override the code that resets your database.

However, if you do not have the time to do this, you can also make your test case pause execution before it finishes, giving you the time to inspect your database before it gets reset. There are several ways of achieving this, but, now, THIS IS A HACK, asking for user input in your Python code will make Python pause execution and wait for user input.

from django.test import TestCase


class MyTestCase(TestCase):
    def test_something_does_something(self):
        result = do_something_with_the_database()
        self.assertTrue(result)

        # Ask for `input` so execution will pause and wait for input.
        input(
            'Execution is paused and you can now inspect the database.\n'
            'Press return/enter key to continue:')

Alternatively, you can also use pdb's set_trace function, which will also make the execution pause and wait for input, and at the same time lets you debug the environment in that point of code execution.

Just make sure that you remove the input() (or pdb.set_trace()) call before you send your code to your automated build system or else it will wait for user input and time out.

user73657
  • 599
  • 5
  • 11
8

According to the docs, you can preserve the database after running tests by:

$ python manage.py test -k

or

$ python manage.py test --keepdb
lmiguelvargasf
  • 63,191
  • 45
  • 217
  • 228
7

To preserve whole database state after test execution (not only tables structure)

  1. Make sure your test class is based on django.test.SimpleTestCase (not TestCase or TransactionTestCase)
  2. Take one of your tests for which you want to preserve database state
  3. Add the following code to your test class to prevent database tables cleaning after the test execution
    def tearDown(self) -> None:
        pass

    @classmethod
    def tearDownClass(cls):
        pass
  1. Run the test with --keepdb parameter, like ./manage.py test app.test --keepdb - to prevent whole DB cleaning after test execution
  2. Wait for the test to finish
  3. Profit! Take snapshot/discover your test_database [do not forget that Django by default will add prefix test_ to your default database name]

Example of command for test test_copy

./manage.py test --noinput --keepdb api.tests.SomeTests.test_copy

class SomeTests(SimpleTestCase):
    allow_database_queries = True

    def setUp(self):
        super(SomeTests, self).setUp()
        self.huge_set_up_operations()

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.huge_init_database()

    def tearDown(self):
        pass

    @classmethod
    def tearDownClass(cls):
        pass

    def test_copy(self):
        SubscriptionFactory()
pymen
  • 5,737
  • 44
  • 35
  • 1
    Another note, you also may need to add `allow_database_queries = True` attribute to the `SomeTests` class if there are any queries. – David Merritt Jun 02 '21 at 16:07
  • Using `allow_database_queries = True` is deprecated since django 2.2 use `databases = "__all__"` instead! see also https://stackoverflow.com/a/64487965/5804947 – Henhuy Nov 11 '22 at 10:14
0

For anyone in a Pytest environment I use the following pytest.ini for testing

[pytest]
DJANGO_SETTINGS_MODULE=myapp.settings.test
python_files = tests.py test_*.py *_tests.py
addopts =
    --ds=myapp.settings.test
    --reuse-db
    --nomigrations

note the "--resuse-db" command argument/addpots

Cuyler Quint
  • 186
  • 2
  • 6
-5

According to docs:

Regardless of whether the tests pass or fail, the test databases are destroyed when all the tests have been executed.

Although, fixtures might be a help in your situation. Just create initial data, you want to be there when test starts, as texture, and make test load it.

Braiam
  • 1
  • 11
  • 47
  • 78
Silver Light
  • 44,202
  • 36
  • 123
  • 164