A pytest plugin that cleans your database up after every test.
Project description
pytest-clean-database
A pytest plugin that provides a clear and concise way to help you keep your test database clean between tests, maintaining a proper test isolation.
Installation
pytest-clean-database requires Python >=3.8 and pytest >=7.0.
There is support for two databases, PostgreSQL and MySQL.
To install with support for PostgreSQL (using Psycopg3):
pip install pytest-clean-database[psql]
To install with support for MySQL (using PyMySQL):
pip install pytest-clean-database[mysql]
Or both:
pip install pytest-clean-database[psql,mysql]
Usage
In your conftest.py сreate a new fixture called clean_db_urls and make it return a
sequence of database connection strings (in other words, DSNs) for every PostgreSQL/MySQL
test database you're using during the test run.
Use postgresql:// scheme for PostgreSQL and mysql:// scheme for MySQL.
IMPORTANT! Make sure that clean_db_urls requires the fixture responsible for
creating your test database and running migrations on it. See Mode of operation for an
explanation.
Example:
# conftest.py
@pytest.fixture()
def test_db():
create_database()
run_migrations()
yield
drop_database()
@pytest.fixture(scope="session")
def clean_db_urls(test_db): # Require test_db fixture.
return [
"postgresql://username:password@localhost:5432/test",
"mysql://username:password@localhost:3306/test"
]
PostgreSQL note: by default, public schema will be used. To change the schema,
you can pass it via --clean-db-pg-schema argument to pytest.
There's an example project that showcases the usage of the package.
Mode of operation
Simply put, the approach for this package is to keep track of changes made to tables using database triggers and an internal table, and truncate only the dirty ones. This way we do not waste time truncating every table.
There are two steps to the machinery, implemented as session-scoped autouse fixtures.
- Set up all database objects that we need - executed only once at the start of the
test session.
- Create an internal table that keeps track of user tables and their dirtyness.
- Create a function that sets the dirty state for a given table.
- Create a function that iterates over dirty tables and truncates them, then resets the dirty state.
- For every user table, create an INSERT trigger that will execute the function that marks this table as dirty.
- Clean database tables - executed after every test.
For this to work properly it's important to execute the setup step only after the user tables have been created - otherwise, we won't be able to track their dirtyness. This also implies that if you create a table inside a test - it won't be tracked either. Luckily, pytest fixtures have this incredible feature, where one fixture can request another one, forming a dependency graph.
When you expose your DSNs via clean_db_urls fixture, pytest-clean-database's
setup fixture requests this fixture. This way you get to decide when the setup happens.
And this is why you must ensure that your clean_db_urls fixture requests the fixture
that sets up your test database. If you set up your test database in some way other than
pytest fixtures, it still should be possible to create a fixture that blocks until your
test database is ready.
Rationale
When you develop an application that makes use of a database, most likely you will end up having at least a few test cases that somehow operate on your test database, creating side effects (like inserting and updating rows). That means, to keep your tests properly isolated from each other you have to undo the side effects made during the previous test, and start your next test with a blank slate.
Some frameworks provide users with means to do that: for example, Django takes care of keeping your test database fresh and clean, so you don't have to worry about it. But if you're using, say, FastAPI and SQLAlchemy, or even Blacksheep and asyncpg (a database driver), you are on your own to create the solution to this problem.
The solution might be as simple as recreating the test database for every test, but
as the size of the test suite grows, this will become slower. TRUNCATE TABLE ...
improves the performance a bit, but if you have tens and hundreds of tables, truncating
every one of them on every test still will be unacceptably slow.
Hence, this plugin.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pytest_clean_database-1.0.0.tar.gz.
File metadata
- Download URL: pytest_clean_database-1.0.0.tar.gz
- Upload date:
- Size: 6.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.1 CPython/3.12.3 Linux/6.8.0-1021-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a61b9aaedc07084e32dc2793b641d3f34a1a21371fa09610e28bbbd3ce4b8db2
|
|
| MD5 |
a97ae6a06dbd87efc597807c3ec9be77
|
|
| BLAKE2b-256 |
58791ce7f9f7635dd234de7ee2673b42f84a6fa8b2588a30099521ac9760f9f3
|
File details
Details for the file pytest_clean_database-1.0.0-py3-none-any.whl.
File metadata
- Download URL: pytest_clean_database-1.0.0-py3-none-any.whl
- Upload date:
- Size: 8.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.1 CPython/3.12.3 Linux/6.8.0-1021-azure
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6ba8e00fd4eb4ed060bfb2dd62346103dfccedc2b35672d32999a58611145893
|
|
| MD5 |
dfaffc958ef134d8c20f2ee27d8e7645
|
|
| BLAKE2b-256 |
f3df14f79d32a75b7e14b56115b14d762732012348259a24a95af904e8efff1b
|