Setup a Testing Environment with Docker and Pytest-Django: PostreSQL schema issue

Mangabo Kolawole - Jun 16 '22 - - Dev Community

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

Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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,
    }
Enter fullscreen mode Exit fullscreen mode

And we are done. Running the tests now will pass.

docker-compose -f docker-compose.dev.yml exec -T web pytest -s -v --traceconfig
Enter fullscreen mode Exit fullscreen mode

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.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player