11

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!

4
  • 1
    Are you using SQLite? Can you switch to MySQL? Commented Jan 6, 2011 at 11:18
  • possible duplicate: stackoverflow.com/questions/4606756/… Commented Jan 6, 2011 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. Commented Jan 6, 2011 at 13:18
  • can MySQL solve this problem. so that my test database remains Commented Jan 6, 2011 at 14:24

6 Answers 6

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

Sign up to request clarification or add additional context in comments.

Comments

12

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.

Comments

9

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

$ python manage.py test -k

or

$ python manage.py test --keepdb

Comments

8

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()

2 Comments

Another note, you also may need to add allow_database_queries = True attribute to the SomeTests class if there are any queries.
Using allow_database_queries = True is deprecated since django 2.2 use databases = "__all__" instead! see also stackoverflow.com/a/64487965/5804947
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

Comments

-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.

1 Comment

This answer is outdated. Please update it with new and relevant information.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.