I am working on a fintech project where there are a lot of products. The whole project is built on Django, and products are just applications with their own logic, but all rely on a core application.
This core application actually handles stuff like authentication, organization creation, and wallet transactions because the same logic is repeated on the other application. This actually pushed me to mirror the same structure on the database by using schema.
Each application on the project has its own schema.
But things are a little tricky when it comes to testing with pytest.
Also, note that I am using Docker and running the tests using Docker.
The issue
It isn't straightforward to create the schema in the testing database using Pytest. As I am using the same database container for the dev environment and testing, a testing database is created; naturally, it's great.
As I already have a schema created for the dev database, and there is no way to generate a schema for a precise database using SQL statements in Postgres, my tests have constantly been failing.
return self.cursor.execute(sql, params)
E django.db.utils.ProgrammingError: relation "core.user" does not exist
E LINE 1: INSERT INTO "core"."user" ("password", "last_login", "public...
Not really interesting, right? Here's my solution.
Solution
A simple solution is adding a testing database container to my docker-compose.dev.yaml
file.
db_test:
container_name: test_optimus_db
image: postgres:14.3-alpine
environment:
DATABASE_NAME: test_optimusdb
DATABASE_USER: test_optimus
DATABASE_PASSWORD: Qinsjhgvv45LJSD
DATABASE_HOST: test_optimus_db
DATABASE_PORT: 5432
POSTGRES_USER: test_optimus
POSTGRES_PASSWORD: Qinsjhgvv45LJSD
POSTGRES_DB: test_optimusdb
volumes:
- postgres_data_test:/var/lib/postgresql/data/
- ./db/db_test_init.sql:/docker-entrypoint-initdb.d/1-init.sql
The db_test_init.sql
file looks like this.
GRANT ALL PRIVILEGES ON DATABASE test_optimusdb TO test_optimus;
CREATE SCHEMA IF NOT EXISTS core AUTHORIZATION test_optimus;
CREATE SCHEMA IF NOT EXISTS optimus AUTHORIZATION test_optimus;
With the init SQL script ready, we just need to add this function to the conftest.py
file configuration.
import pytest
from django.conf import settings
@pytest.fixture(scope="session")
def django_db_setup():
settings.DATABASES["default"] = {
"ENGINE": "django.db.backends.postgresql",
"HOST": "test_optimus_db",
"NAME": "test_optimusdb",
"PASSWORD": "Qinsjhgvv45LJSD",
"USER": "test_optimus",
"PORT": 5432,
}
And we are done. Running the tests now will pass.
docker-compose -f docker-compose.dev.yml exec -T web pytest -s -v --traceconfig
And voilà. Even if this solution works and gives much control over the testing environment, I am still looking for automated solutions. So feel free to add comments if you have already faced this issue, and let's discuss it.