Skip to main content
Version: 1.0

Local Testing Guide for Django RLS

Prerequisites

  1. Docker with Compose v2 (docker compose)
  2. Poetry for Python dependencies
curl -sSL https://install.python-poetry.org | python3 -
poetry install

make test starts PostgreSQL via docker compose and runs the full suite against it:

make test

Under the hood this runs scripts/run-tests.sh, which:

  1. docker compose up -d --wait postgres
  2. Ensures rls_test_user exists
  3. Runs pytest with USE_POSTGRESQL=true against localhost:5433

Other test commands

make test-cov        # coverage report
make test-security # security regression suite
make ci-local # lint + type-check + full tests (same Postgres flow)
make test-local # pytest only — you must provide Postgres yourself

Run the script directly

./scripts/run-tests.sh
./scripts/run-tests.sh tests/security -m security -v

Docker Compose details

PostgreSQL 17 runs in Docker on host port 5433 (avoids conflicting with a local Postgres on 5432):

make docker-up      # start and wait for healthy Postgres
make docker-down # stop containers
make docker-reset # delete volume and recreate
make docker-logs # tail Postgres logs
make db-shell # psql as postgres superuser

The test user rls_test_user / testpass is created automatically via docker/postgres/init/ on first volume creation. scripts/run-tests.sh also creates the role if the volume already existed.

In-network test runner (optional)

Run pytest inside Compose, connected to the postgres service on port 5432:

docker compose --profile test run --rm test

Environment variables

Used by scripts/run-tests.sh and CI:

VariableLocal defaultCI value
USE_POSTGRESQLtruetrue
DB_HOSTlocalhostlocalhost
DB_PORT54335432
DB_NAMEpostgrespostgres
DB_USERrls_test_userrls_test_user
DB_PASSWORDtestpasstestpass

Without Docker

Install PostgreSQL locally, create the test user and database, then:

export USE_POSTGRESQL=true
export DB_HOST=localhost
export DB_PORT=5432 # or your port
export DB_USER=rls_test_user
export DB_PASSWORD=testpass
poetry run pytest

Testing best practices

  1. Always test with PostgreSQL — SQLite does not enforce RLS.
  2. Use make test before opening a PR — same real-Postgres path as CI.
  3. Use system_rls_context() in tests when switching identity (1.0.0+).
  4. Do not mock django_rls.context.connection for security tests — assert behavior via get_rls_context() on a live database.

Troubleshooting

# Containers running?
docker compose ps

# Postgres healthy?
docker compose exec postgres pg_isready -U postgres

# Stale test DB connections
docker compose restart postgres

# Nuclear reset
make docker-reset

database "test_django_rls" is being accessed by other users

Usually leftover connections from threaded tests. Restart Postgres or run:

docker compose exec postgres psql -U postgres -c \
"SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'test_django_rls';"

Continuous Integration

GitHub Actions runs the same full pytest tree against a real PostgreSQL 17 service on every PR to main:

  • Python 3.11 and 3.12
  • Django 5.1, 5.2, and 6.0
  • USE_POSTGRESQL=true, DB_PORT=5432

Local make test and CI exercise the same code paths; only the host port differs (5433 vs 5432).