pytest-airflow-in-a-box
pytest-airflow-in-a-box is a pytest plugin for testing Apache Airflow DAGs without a live
Airflow deployment. It targets Airflow 3 and provides the package and plugin foundation for a
small, typed testing surface.
The package auto-registers with pytest, creates an isolated metadata database, and provides typed fixtures for persisted Dags, DagRuns, task instances, sessions, and Dag bags.
Contents
Quickstart
uv add --dev pytest-airflow-in-a-box
pip install pytest-airflow-in-a-box
from airflow.sdk import task
def test_dag(dag_maker):
with dag_maker():
@task
def produce():
return 21
@task
def consume(value):
return value * 2
consume(produce())
result = dag_maker.run()
assert result.success
assert result.xcoms == {"produce": 21, "consume": 42}
assert result.order == ["produce", "consume"]
pytest
dag_maker.run() executes every task in dependency order and returns an inert
DagRunResult snapshot: states, xcoms, errors, order, and per-task access via
result["task_id"]. Single tasks run with dag_maker.run_ti("produce"), and
pytest_airflow_in_a_box.matchers supports one-expression bulk assertions like
assert result == {"produce": succeeded(21), "consume": succeeded(42)}.
The pytest11 entry point registers the plugin automatically -- no pytest_plugins
declaration needed. See the documentation site
for the full dag_maker/run/run_ti surface, sessions, DB-free task execution, deferrable
operators, the REST API fixture, and bundled smoke checks.
Why not...
dag.test()-- Airflow's own built-in helper runs one Dag end to end, but it is not a pytest plugin: no fixtures, no isolated metadata database, noxdistparallelism, no REST API testing- upstream
tests_common-- the harness Airflow's own core test suite runs on; it targets testing Airflow itself, not published as a package for testing DAG-author code - Flowminder
pytest-airflow-- an inverse concept (runs pytest suites under Airflow, rather than testing DAGs under pytest) and unmaintained airflow-pytest-plugin-- generates JUnit-XML dashboards from DAG runs; not aimed at isolated, fixture-driven unit testing
Requirements
- CPython 3.10 through 3.14
- pytest 8 or newer
- Apache Airflow 3.1 or newer, below 4
- Linux or macOS for Airflow-backed tests
Apache Airflow does not support native Windows installations. Windows development should use WSL2 or the included devcontainer; platform-independent package checks alone do not imply full Windows Airflow support.
The released compatibility matrix is exercised against Airflow 3.1.0, 3.1.1, 3.1.2, 3.1.3, 3.1.5, 3.1.6, 3.1.7, 3.1.8, 3.2.0, 3.2.1, 3.2.2, and 3.3.0 across CPython 3.10 through 3.14 using Airflow's published constraints files.
Installation
uv add --dev pytest-airflow-in-a-box
pip install pytest-airflow-in-a-box
The pytest11 entry point loads the plugin automatically. Consumer projects do not need to add a
pytest_plugins declaration.
The bundled pytest plugins are intentional runtime dependencies. pytest-xdist is part of the
supported execution model: controller bootstrap state and worker-scoped artifacts are coordinated
for parallel runs. pytest-timeout backs up Airflow's per-file Dag parse watchdog with a
corpus-scaled deadline on every bundled smoke item, so whichever worker produces the shared corpus
cannot wedge the test session outside the per-file parser boundary.
The plugin is inert on runs without Airflow-facing tests: session startup only prepares a
disposable run directory and AIRFLOW__* environment variables. Airflow itself is imported and
the metadata database migrated lazily, on the first test that carries a db_test/api_test
marker or uses a database-backed plugin fixture. A pytest -k unrelated run in a shared venv
never pays the Airflow import or migration cost. Tests that touch the metadata database directly
(their own create_session calls, for example) without a plugin fixture must carry db_test to
trigger initialization.
To disable the plugin entirely for a run:
pytest -p no:pytest_airflow_in_a_box
Documentation
Task execution, deferrable operators, DB-free execution, Variable/Connection seeding, structlog capture, Dag collection, configuration overrides, smoke tests, database backends and cleanup, the live REST API, markers, and diagnostics are all covered on the documentation site.
Development
uv sync
uv run prek install
make all
Run the GitHub Actions workflow locally on Linux with act:
act pull_request
act cannot reproduce native macOS or Windows behavior. See
CONTRIBUTING.md for the full contribution workflow and the
issue tracker for open work.
License
Apache License 2.0. See LICENSE, NOTICE, and PROVENANCE.md.
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_airflow_in_a_box-0.4.0.tar.gz.
File metadata
- Download URL: pytest_airflow_in_a_box-0.4.0.tar.gz
- Upload date:
- Size: 105.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eb9d8f43b98a43b3c2ff40bdc02a0b8e0347d5eb66fb72d80c31fa9f87f8b5cd
|
|
| MD5 |
1d58be0bec64c1338c915778f6af69c3
|
|
| BLAKE2b-256 |
49fd156cba8bc53fe3d04244c4aad16e2ac77e5456dd49944ff549ff429b7814
|
Provenance
The following attestation bundles were made for pytest_airflow_in_a_box-0.4.0.tar.gz:
Publisher:
release.yml on nredd/pytest-airflow-in-a-box
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytest_airflow_in_a_box-0.4.0.tar.gz -
Subject digest:
eb9d8f43b98a43b3c2ff40bdc02a0b8e0347d5eb66fb72d80c31fa9f87f8b5cd - Sigstore transparency entry: 2443889465
- Sigstore integration time:
-
Permalink:
nredd/pytest-airflow-in-a-box@69e4921bcafa8238ba645395ebae34ef6006e647 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/nredd
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@69e4921bcafa8238ba645395ebae34ef6006e647 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pytest_airflow_in_a_box-0.4.0-py3-none-any.whl.
File metadata
- Download URL: pytest_airflow_in_a_box-0.4.0-py3-none-any.whl
- Upload date:
- Size: 130.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8f787f28783c6da150bee5bc212a3e5834af1fee6ea2906c2af5261476a55b90
|
|
| MD5 |
9a2714c155033d32bffe468f9090f454
|
|
| BLAKE2b-256 |
d42c4142898cd8c9baedb279c7e6d1722cdb3cb08f3b7bbf1ae2498c946fdfb4
|
Provenance
The following attestation bundles were made for pytest_airflow_in_a_box-0.4.0-py3-none-any.whl:
Publisher:
release.yml on nredd/pytest-airflow-in-a-box
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytest_airflow_in_a_box-0.4.0-py3-none-any.whl -
Subject digest:
8f787f28783c6da150bee5bc212a3e5834af1fee6ea2906c2af5261476a55b90 - Sigstore transparency entry: 2443890055
- Sigstore integration time:
-
Permalink:
nredd/pytest-airflow-in-a-box@69e4921bcafa8238ba645395ebae34ef6006e647 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/nredd
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@69e4921bcafa8238ba645395ebae34ef6006e647 -
Trigger Event:
release
-
Statement type: