Skip to main content

django-baseshift-brancher

Run your Django test suite against an already-migrated PostgreSQL clone, so tests don't need to run CREATE DATABASE or migrations on every run.

On a large Django project, a lot of test time goes to building the test database and replaying every migration. django-baseshift-brancher skips both steps. It uses brancher by Baseshift to create one ready-to-use PostgreSQL clone per test worker, already migrated to the schema of your current git checkout. Then it points pytest or Django's test runner at those clones.

  • Works with pytest / pytest-django (pytest -n N) and Django's manage.py test (--parallel N)
  • No changes to settings.py
  • Migrated snapshots are cached per migration commit and shared across branches

This package does not include the brancher binary. Install that first. On macOS the curl command uses Homebrew; on Linux it downloads the binary.

curl -fsSL https://dl.baseshift.com/brancher/install.sh | bash
brew install baseshift/tap/brancher

Requirements

Requirement Version
Python 3.8 – 3.13
Django 3.2, 4.2, 5.0 – 6.0
Database PostgreSQL
brancher by Baseshift The brancher binary on your PATH (baseshift.com/brancher)
Git Your project must be a git repository

Install

pip install django-baseshift-brancher

# If pytest-django isn't installed yet:
pip install "django-baseshift-brancher[pytest]"

Quick start

Run these from your Django project root (the directory that contains manage.py).

1. Create the clones

export DJANGO_SETTINGS_MODULE=yourproject.settings
unset BASESHIFT_BRANCHES_FILE DATABASE_URL PGHOST PGPORT

django-baseshift-brancher clone --count 4

clone creates the brancher root on the first run, then builds the snapshots and starts the clones. That is enough.

Initializing the root yourself is optional. Do it when you want to choose the snap key and the PostgreSQL bin directory (the directory that contains initdb). brancher keygen prints a 64-character hex key. Leave that key in the environment so clone can open the root:

export BRANCHER_SNAP_KEY="$(brancher keygen)"
brancher init --pg-bin /usr/lib/postgresql/16/bin

django-baseshift-brancher clone --count 4

A key file works the same way. Pass it to both commands: brancher init --pg-bin /usr/lib/postgresql/16/bin --key-file snap.key, then django-baseshift-brancher clone --count 4 --key-file snap.key.

--count is the number of databases to create. You need one per test worker.

The command writes the clone details to .brancher/clones.json, prints them as JSON, and prints the export line you need next (on stderr).

2. Run the tests

pytest

export BASESHIFT_BRANCHES_FILE="$PWD/.brancher/clones.json"
pytest -n 4

Django test runner

export BASESHIFT_BRANCHES_FILE="$PWD/.brancher/clones.json"
python manage.py test --testrunner django_baseshift_brancher.DiscoverRunner --parallel 4

3. Clean up

brancher stop --all

How it works

Snapshots follow your migration history

clone reads your git history. Every commit that changes migration files gets its own migrated snapshot.

  • Adding migration files builds on the previous snapshot. Branches that split off from the same migration commit share it.
  • Changing or deleting existing migration files starts over from an empty snapshot, because the new schema can't be built on top of the old one.
  • Rebasing creates new commits, so the rebased checkout gets a new snapshot on top of its new parent. Branches that split off before the rebase keep their own chain.

Snapshots don't have names and you never manage them yourself. Parent snapshots are picked automatically.

Test workers map to clones

Runner Worker ID Clone used
pytest-xdist gw0, gw1, … (0-based) gw0 → 1st clone
Django --parallel "1", "2", … (1-based) "1" → 1st clone

pytest -n 4 and --parallel 4 each need --count 4 (or more).

What happens to your DATABASES setting

  • USER and PASSWORD are kept as you configured them.
  • HOST, PORT and NAME are replaced with the clone's values.
  • Test migrations are turned off (the clone is already migrated).

pytest plugin

The plugin loads automatically. It assigns each worker to a clone and forces --reuse-db and --no-migrations. Don't pass --create-db.


Configuration

Environment variable Required Purpose
DJANGO_SETTINGS_MODULE Yes Your Django settings module
BASESHIFT_BRANCHES_FILE Yes, when running tests Absolute path to .brancher/clones.json. Tests only read the clones from this variable. A clones.json in the current directory is not picked up automatically.
BASESHIFT_INIT_SQL No SQL that runs on each new snapshot before migrate. Use it for anything your migrations assume already exists, such as extensions.

Example:

export BASESHIFT_INIT_SQL="CREATE EXTENSION IF NOT EXISTS pg_trgm"

Other setup commands: once the clones are running, run any extra project setup yourself against their connection strings (for example, a management command like ensure_celery_broker_schema).


Troubleshooting

Symptom Likely cause Fix
Tests connect to your normal dev/CI database BASESHIFT_BRANCHES_FILE isn't set in the shell running the tests export BASESHIFT_BRANCHES_FILE="$PWD/.brancher/clones.json"
Some workers fail or no clone is found for them Fewer clones than workers Re-run clone with --count ≥ -n / --parallel
Tests try to create the database --create-db was passed Remove --create-db
A migration fails with a missing extension The extension has to exist before migrations run Set BASESHIFT_INIT_SQL and re-run clone
brancher: command not found brancher isn't installed Run the curl or Homebrew command at the top of this page

For AI coding agents

Use this exact sequence from the Django project root. Replace N with the number of parallel test workers.

export DJANGO_SETTINGS_MODULE=<project>.settings
unset BASESHIFT_BRANCHES_FILE DATABASE_URL PGHOST PGPORT
django-baseshift-brancher clone --count N
export BASESHIFT_BRANCHES_FILE="$PWD/.brancher/clones.json"
pytest -n N                     # or: python manage.py test --testrunner django_baseshift_brancher.DiscoverRunner --parallel N
brancher stop --all

Rules:

  • clone creates the root. brancher init beforehand is optional; see Quick start.
  • Don't edit settings.py.
  • Don't pass --create-db.
  • Re-run clone after checking out a commit with different migrations.
  • BASESHIFT_BRANCHES_FILE must be exported in the same shell that runs the tests.
  • Always run brancher stop --all when you're done.

About Baseshift

Baseshift gives every developer, coding agent and pull request its own isolated, writable, masked clone of your real database, running in your cloud and ready in seconds. It supports PostgreSQL, MySQL, MongoDB and MariaDB. It also adds guardrails for database changes, such as schema change detection and query risk checks, so issues are caught before they reach production.

This package is the Django integration for brancher by Baseshift.

License

Proprietary. See baseshift.com for terms.

Metadata

Release files for django-baseshift-brancher 1.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-baseshift-brancher 1.5.0
File Size Uploaded
django_baseshift_brancher-1.5.0.tar.gz 56.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-baseshift-brancher 1.5.0
File Interpreter ABI Platform
django_baseshift_brancher-1.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 99.0 kB

Release files / django_baseshift_brancher-1.5.0.tar.gz

Download URL django_baseshift_brancher-1.5.0.tar.gz
Size 56.2 kB
Tags Source
SHA-256 checksum
How to use checksums
c87f10d667119830bce2f46d3e104b8251a15af73487a935b7de55c9ae4d510d
BLAKE2b-256 checksum
How to use checksums
26ea5b408af304d64e46ceaeee751233816c3fca59f52cf468a296a79f468612
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / django_baseshift_brancher-1.5.0-py3-none-any.whl

Download URL django_baseshift_brancher-1.5.0-py3-none-any.whl
Size 42.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
caef553cecfafbcf3746c9114d4f71f3e5d0a6c5aa1c1298755e4225be7af891
BLAKE2b-256 checksum
How to use checksums
cc4d3036553720cf81adbc1beb2e6c760f5ba0cbbd1f5cc9d622305def8c1e85
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

1.5.0 This release

2 release files

1.4.0

2 release files

1.3.2

2 release files

0.13.0

2 release files

0.12.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page