'Using different database with pytest

I am using to run tests for my django application pytest with pytest-django plugin. I use MySQL database as a default one for django. Is there possiblity to specify just for pytest to use different database for tests, SQLite?

I am looking for different option if any, than creating special test_seetings.py for py.test --ds=test_settings.



Solution 1:[1]

If you need to run tests under a "real" database but don't want to use your main database for it because it's too slow, you can use sqlite for the particular test.

import tempfile
from django.db import models, connections
from django.db.backends.sqlite3.base import DatabaseWrapper as SqliteConnection


@pytest.fixture(scope="function")
def sqlite_db(django_db_blocker):
    """
    Runs tests inside a sqlite3, making it slightly faster.
    When using this, avoid using the `@pytest.mark.django_db` and put the name `sqlite_db` as your
    first function parameter.

    Example:

        def test_something(sqlite_db):
            # This test will run inside a unique and isolated sqlite db

            with connection.cursor() as c, connection.schema_editor() as editor:
                editor.create_model(User)  # c.execute('CREATE TABLE ...')
                user = User.objects.create(username='test')  # c.execute('INSERT INTO ...')
                assert user.username == 'test'
                editor.delete_model(User)  # c.execute('DROP TABLE ...')
            
    """
    # Tells pytest-django that it's ok to use the db
    django_db_blocker.unblock()

    # Create a backup of the current db connection
    original_connection = connections['default']

    with tempfile.NamedTemporaryFile() as f:
        db_settings = {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': f.name,
            'TIME_ZONE': None,
            'CONN_MAX_AGE': 0,
            'OPTIONS': {},
            'AUTOCOMMIT': True,
        }
        # Override the `default` connection with the sqlite one
        connections['default'] = SqliteConnection(db_settings)

        # Call your test
        yield

        # Clean up
        connections['default'].close()
        # Put back the connection
        connections['default'] = original_connection

    # Tell pytest-django to restore the db lock
    django_db_blocker.restore()

Note: the lack of @pytest.mark.django_db decorator on the example test (docstring).

Note: this will give you a brand new db with NOTHING inside, you need to create your models and populate it if you want to use it. See editor = connections['default'].schema_editor(); editor.create_model(User) and don't forget to clean up after yourself: editor.delete_model(User)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Javier Buzzi