pytest-testcontainers-django 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pytest_testcontainers_django-0.2.0/.gitignore +27 -0
- pytest_testcontainers_django-0.2.0/CHANGELOG.md +62 -0
- pytest_testcontainers_django-0.2.0/LICENSE +21 -0
- pytest_testcontainers_django-0.2.0/PKG-INFO +371 -0
- pytest_testcontainers_django-0.2.0/README.md +303 -0
- pytest_testcontainers_django-0.2.0/pyproject.toml +124 -0
- pytest_testcontainers_django-0.2.0/src/pytest_testcontainers_django/__init__.py +45 -0
- pytest_testcontainers_django-0.2.0/src/pytest_testcontainers_django/_types.py +63 -0
- pytest_testcontainers_django-0.2.0/src/pytest_testcontainers_django/config.py +232 -0
- pytest_testcontainers_django-0.2.0/src/pytest_testcontainers_django/containers.py +252 -0
- pytest_testcontainers_django-0.2.0/src/pytest_testcontainers_django/errors.py +31 -0
- pytest_testcontainers_django-0.2.0/src/pytest_testcontainers_django/injection.py +98 -0
- pytest_testcontainers_django-0.2.0/src/pytest_testcontainers_django/plugin.py +273 -0
- pytest_testcontainers_django-0.2.0/tests/__init__.py +0 -0
- pytest_testcontainers_django-0.2.0/tests/conftest.py +6 -0
- pytest_testcontainers_django-0.2.0/tests/test_config.py +192 -0
- pytest_testcontainers_django-0.2.0/tests/test_injection.py +112 -0
- pytest_testcontainers_django-0.2.0/tests/test_plugin.py +461 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*.egg-info/
|
|
4
|
+
*.egg
|
|
5
|
+
build/
|
|
6
|
+
dist/
|
|
7
|
+
.eggs/
|
|
8
|
+
.pytest_cache/
|
|
9
|
+
.tox/
|
|
10
|
+
.coverage
|
|
11
|
+
.coverage.*
|
|
12
|
+
htmlcov/
|
|
13
|
+
coverage.xml
|
|
14
|
+
.mypy_cache/
|
|
15
|
+
.ruff_cache/
|
|
16
|
+
.venv/
|
|
17
|
+
venv/
|
|
18
|
+
env/
|
|
19
|
+
.envrc
|
|
20
|
+
.env
|
|
21
|
+
.env.local
|
|
22
|
+
*.swp
|
|
23
|
+
*.swo
|
|
24
|
+
.DS_Store
|
|
25
|
+
.idea/
|
|
26
|
+
.vscode/
|
|
27
|
+
*.log
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.2.0] - 2026-05-08
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- New `[redis]` install extra so `redis_enabled = true` works without a
|
|
15
|
+
separate `pip install redis` (`testcontainers.redis` imports the Python
|
|
16
|
+
redis client at module load).
|
|
17
|
+
- `ReuseStaleContainerError` and matching `pytest.UsageError` for the
|
|
18
|
+
reuse-mode edge case where a pre-existing container is in `dead` /
|
|
19
|
+
`removing` state — surfaced with the exact `docker rm -f <name>`
|
|
20
|
+
command instead of letting Docker fail the start with a 409 name
|
|
21
|
+
conflict.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- `__version__` now reads from `importlib.metadata` so it stays in sync
|
|
26
|
+
with `pyproject.toml`.
|
|
27
|
+
- README Django support matrix marks 4.2 LTS as past EOL (Apr 2026).
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- The plugin's own test suite now disables eager-start via a *root*
|
|
32
|
+
`conftest.py` rather than `tests/conftest.py`. The root file is
|
|
33
|
+
preloaded by the plugin's `tryfirst` hook; `tests/conftest.py` is not
|
|
34
|
+
— meaning the previous setup silently ran every "unit" test against
|
|
35
|
+
a real Docker daemon when one was available locally (CI was unaffected
|
|
36
|
+
because it sets the env var explicitly).
|
|
37
|
+
|
|
38
|
+
## [0.1.0] - 2026-05-08
|
|
39
|
+
|
|
40
|
+
Initial release.
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
- `pytest_load_initial_conftests(tryfirst=True)` hook that starts Postgres
|
|
45
|
+
(and optionally Redis) containers and injects connection details into
|
|
46
|
+
`os.environ` **before** pytest-django imports settings.
|
|
47
|
+
- Configuration via `[tool.pytest-testcontainers-django]` in `pyproject.toml`
|
|
48
|
+
or programmatically via `register(DjangoContainerConfig(...))` from
|
|
49
|
+
`conftest.py`.
|
|
50
|
+
- Postgres init-script mounting (`/docker-entrypoint-initdb.d/NN-name.sql`)
|
|
51
|
+
with automatic `postgres_template = postgres_database` defaulting when
|
|
52
|
+
init scripts are present (SPEC §10.6).
|
|
53
|
+
- Reuse mode via `PYTEST_TESTCONTAINERS_REUSE=1`, with a stderr warning
|
|
54
|
+
when init scripts wouldn't be replayed against a pre-existing container
|
|
55
|
+
(SPEC §10.7).
|
|
56
|
+
- pytest-xdist worker handling: workers inherit env from the controller and
|
|
57
|
+
only set the `*_SKIP_DOTENV` flag (SPEC §7).
|
|
58
|
+
- Optional integration with `django-pg-baseline` via the
|
|
59
|
+
`use_django_pg_baseline = true` flag.
|
|
60
|
+
- atexit safety net for abrupt-exit paths that skip `pytest_unconfigure`.
|
|
61
|
+
- Custom `*_SKIP_DOTENV` env-var injection so projects using django-environ
|
|
62
|
+
don't have their just-injected ports clobbered by `.env` reload (SPEC §9).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Michał Pasternak
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pytest-testcontainers-django
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Bridge between pytest-testcontainers and pytest-django: starts the DB container before Django imports settings.
|
|
5
|
+
Project-URL: Homepage, https://github.com/iplweb/pytest-testcontainers-django
|
|
6
|
+
Project-URL: Repository, https://github.com/iplweb/pytest-testcontainers-django
|
|
7
|
+
Project-URL: Issues, https://github.com/iplweb/pytest-testcontainers-django/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/iplweb/pytest-testcontainers-django/blob/main/CHANGELOG.md
|
|
9
|
+
Author-email: Michał Pasternak <michal.dtz@gmail.com>
|
|
10
|
+
License: MIT License
|
|
11
|
+
|
|
12
|
+
Copyright (c) 2026 Michał Pasternak
|
|
13
|
+
|
|
14
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
15
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
16
|
+
in the Software without restriction, including without limitation the rights
|
|
17
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
18
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
19
|
+
furnished to do so, subject to the following conditions:
|
|
20
|
+
|
|
21
|
+
The above copyright notice and this permission notice shall be included in all
|
|
22
|
+
copies or substantial portions of the Software.
|
|
23
|
+
|
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
25
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
26
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
27
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
28
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
29
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
30
|
+
SOFTWARE.
|
|
31
|
+
License-File: LICENSE
|
|
32
|
+
Keywords: django,docker,integration-testing,postgres,pytest,pytest-django,pytest-plugin,redis,testcontainers
|
|
33
|
+
Classifier: Development Status :: 4 - Beta
|
|
34
|
+
Classifier: Framework :: Django
|
|
35
|
+
Classifier: Framework :: Django :: 4.2
|
|
36
|
+
Classifier: Framework :: Django :: 5.0
|
|
37
|
+
Classifier: Framework :: Django :: 5.1
|
|
38
|
+
Classifier: Framework :: Django :: 5.2
|
|
39
|
+
Classifier: Framework :: Pytest
|
|
40
|
+
Classifier: Intended Audience :: Developers
|
|
41
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
42
|
+
Classifier: Operating System :: OS Independent
|
|
43
|
+
Classifier: Programming Language :: Python
|
|
44
|
+
Classifier: Programming Language :: Python :: 3
|
|
45
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
46
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
47
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
48
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
49
|
+
Classifier: Topic :: Software Development :: Testing
|
|
50
|
+
Requires-Python: >=3.10
|
|
51
|
+
Requires-Dist: pytest-django>=4
|
|
52
|
+
Requires-Dist: pytest-testcontainers<2,>=0.1
|
|
53
|
+
Requires-Dist: pytest<9,>=7.4
|
|
54
|
+
Requires-Dist: testcontainers<5,>=4.7
|
|
55
|
+
Requires-Dist: tomli>=2; python_version < '3.11'
|
|
56
|
+
Provides-Extra: baseline
|
|
57
|
+
Requires-Dist: django-pg-baseline; extra == 'baseline'
|
|
58
|
+
Provides-Extra: dev
|
|
59
|
+
Requires-Dist: django-environ; extra == 'dev'
|
|
60
|
+
Requires-Dist: django>=4.2; extra == 'dev'
|
|
61
|
+
Requires-Dist: pre-commit; extra == 'dev'
|
|
62
|
+
Requires-Dist: pytest-xdist; extra == 'dev'
|
|
63
|
+
Requires-Dist: redis>=4; extra == 'dev'
|
|
64
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
65
|
+
Provides-Extra: redis
|
|
66
|
+
Requires-Dist: redis>=4; extra == 'redis'
|
|
67
|
+
Description-Content-Type: text/markdown
|
|
68
|
+
|
|
69
|
+
# pytest-testcontainers-django
|
|
70
|
+
|
|
71
|
+
[](https://github.com/iplweb/pytest-testcontainers-django/actions/workflows/ci.yml)
|
|
72
|
+
[](https://pypi.org/project/pytest-testcontainers-django/)
|
|
73
|
+
[](https://pypi.org/project/pytest-testcontainers-django/)
|
|
74
|
+
[](LICENSE)
|
|
75
|
+
|
|
76
|
+
Bridge between [`pytest-testcontainers`][pt] and [`pytest-django`][pd]:
|
|
77
|
+
starts a Postgres (and optionally Redis) container **before** Django imports
|
|
78
|
+
its settings, so your tests run against a real, ephemeral DB without any
|
|
79
|
+
docker-compose orchestration — and without "Connection refused" against
|
|
80
|
+
port 5432 because Django read `os.environ` too early.
|
|
81
|
+
|
|
82
|
+
[pt]: https://github.com/iplweb/pytest-testcontainers
|
|
83
|
+
[pd]: https://github.com/pytest-dev/pytest-django
|
|
84
|
+
|
|
85
|
+
## Why this package exists
|
|
86
|
+
|
|
87
|
+
Django evaluates `DATABASES` at **module-import time**. pytest-django
|
|
88
|
+
imports settings during its `pytest_load_initial_conftests` hook. Any
|
|
89
|
+
fixture-based testcontainer setup runs *after* that — so by the time the
|
|
90
|
+
container has a port, Django has already opened a connection (or failed
|
|
91
|
+
to) against whatever your `.env` had at pytest startup.
|
|
92
|
+
|
|
93
|
+
The only correct hook for "start a container, write its port to
|
|
94
|
+
`os.environ`, before Django imports settings" is
|
|
95
|
+
`pytest_load_initial_conftests` itself, registered with
|
|
96
|
+
`@pytest.hookimpl(tryfirst=True)`. That single detail is the core IP of
|
|
97
|
+
this package; the rest is plumbing — xdist worker propagation, dotenv
|
|
98
|
+
suppression, init-script mounting, TEST TEMPLATE wiring, cleanup
|
|
99
|
+
ordering.
|
|
100
|
+
|
|
101
|
+
See [`SPEC.md`](SPEC.md) for the full design rationale (especially §6 on
|
|
102
|
+
the timing dance).
|
|
103
|
+
|
|
104
|
+
## Features
|
|
105
|
+
|
|
106
|
+
- `pytest_load_initial_conftests(tryfirst=True)` hook that runs **before**
|
|
107
|
+
pytest-django imports your `settings.py`.
|
|
108
|
+
- Zero-config defaults — works out of the box for projects whose
|
|
109
|
+
`settings.py` reads `DJANGO_DB_HOST` / `DJANGO_DB_PORT` / etc. from
|
|
110
|
+
`os.environ`.
|
|
111
|
+
- Declarative configuration in `[tool.pytest-testcontainers-django]` or
|
|
112
|
+
programmatic configuration via `register(DjangoContainerConfig(...))`
|
|
113
|
+
from `conftest.py`.
|
|
114
|
+
- Postgres init-script mounting (`/docker-entrypoint-initdb.d/`) with
|
|
115
|
+
automatic `DATABASES['TEST']['TEMPLATE']` defaulting — so
|
|
116
|
+
`pytest --create-db` finishes in seconds.
|
|
117
|
+
- Optional Redis container with the same timing-safe injection pattern.
|
|
118
|
+
- pytest-xdist support — workers inherit the controller's environment,
|
|
119
|
+
no port-fight.
|
|
120
|
+
- `--no-testcontainers` / `PYTEST_TESTCONTAINERS_DISABLE=1` to delegate
|
|
121
|
+
to docker-compose; `PYTEST_TESTCONTAINERS_REUSE=1` for fast local
|
|
122
|
+
iteration.
|
|
123
|
+
- atexit safety net for abrupt-exit paths that skip `pytest_unconfigure`.
|
|
124
|
+
- Optional integration with [`django-pg-baseline`](https://github.com/iplweb/django-pg-baseline)
|
|
125
|
+
for managed baseline SQL artifacts.
|
|
126
|
+
|
|
127
|
+
## Supported versions
|
|
128
|
+
|
|
129
|
+
### Python
|
|
130
|
+
|
|
131
|
+
| Python | 3.10 | 3.11 | 3.12 | 3.13 |
|
|
132
|
+
|--------|------|------|------|------|
|
|
133
|
+
| | ✓ | ✓ | ✓ | ✓ |
|
|
134
|
+
|
|
135
|
+
### Django
|
|
136
|
+
|
|
137
|
+
Authoritative upstream: <https://docs.djangoproject.com/en/dev/faq/install/#what-python-version-can-i-use-with-django>
|
|
138
|
+
|
|
139
|
+
| Django | 3.10 | 3.11 | 3.12 | 3.13 | Status |
|
|
140
|
+
|---------|------|------|------|------|------------------------------|
|
|
141
|
+
| 4.2 LTS | ✓ | ✓ | ✓ | — | EOL Apr 2026 (still works) |
|
|
142
|
+
| 5.2 LTS | ✓ | ✓ | ✓ | ✓ | Active LTS |
|
|
143
|
+
|
|
144
|
+
EOL Django releases (4.2, 5.0, 5.1) are not actively tested but should
|
|
145
|
+
still work — this package only consumes pytest-django's hook surface,
|
|
146
|
+
not Django internals. Open an issue if you need an LTS-only reassurance.
|
|
147
|
+
|
|
148
|
+
## Install
|
|
149
|
+
|
|
150
|
+
### Using uv (recommended)
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
uv add pytest-testcontainers-django
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Using pip
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
pip install pytest-testcontainers-django
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
You also need a working Docker daemon on the host running pytest. No
|
|
163
|
+
extra system libraries are required — the package is pure Python.
|
|
164
|
+
|
|
165
|
+
## Quick start
|
|
166
|
+
|
|
167
|
+
For most projects, configuration lives in `pyproject.toml`. Zero
|
|
168
|
+
`conftest.py` needed:
|
|
169
|
+
|
|
170
|
+
```toml
|
|
171
|
+
[tool.pytest-testcontainers-django]
|
|
172
|
+
postgres_image = "postgres:16"
|
|
173
|
+
postgres_user = "myapp"
|
|
174
|
+
postgres_password = "myapp"
|
|
175
|
+
postgres_database = "myapp"
|
|
176
|
+
|
|
177
|
+
# Env-var names this plugin writes into os.environ.
|
|
178
|
+
# These are the same names your settings.py reads.
|
|
179
|
+
db_host_env = "DJANGO_DB_HOST"
|
|
180
|
+
db_port_env = "DJANGO_DB_PORT"
|
|
181
|
+
db_name_env = "DJANGO_DB_NAME"
|
|
182
|
+
db_user_env = "DJANGO_DB_USER"
|
|
183
|
+
db_password_env = "DJANGO_DB_PASSWORD"
|
|
184
|
+
db_test_template_env = "DJANGO_DB_TEST_TEMPLATE"
|
|
185
|
+
skip_dotenv_env = "DJANGO_SKIP_DOTENV"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Your `settings.py` reads these env vars exactly as you'd expect:
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
import environ
|
|
192
|
+
import os
|
|
193
|
+
|
|
194
|
+
env = environ.Env()
|
|
195
|
+
|
|
196
|
+
# Skip .env loading when the plugin already populated os.environ —
|
|
197
|
+
# otherwise read_env(overwrite=True) would clobber our injected port.
|
|
198
|
+
if not os.environ.get("DJANGO_SKIP_DOTENV"):
|
|
199
|
+
environ.Env.read_env(".env", overwrite=True)
|
|
200
|
+
|
|
201
|
+
DATABASES = {
|
|
202
|
+
"default": {
|
|
203
|
+
"ENGINE": "django.db.backends.postgresql",
|
|
204
|
+
"NAME": env("DJANGO_DB_NAME"),
|
|
205
|
+
"USER": env("DJANGO_DB_USER"),
|
|
206
|
+
"PASSWORD": env("DJANGO_DB_PASSWORD"),
|
|
207
|
+
"HOST": env("DJANGO_DB_HOST"),
|
|
208
|
+
"PORT": env("DJANGO_DB_PORT"),
|
|
209
|
+
},
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
# Wire the TEST TEMPLATE env var (optional but recommended when you
|
|
213
|
+
# load init scripts — see "Init scripts / baseline" below).
|
|
214
|
+
_test_template = env("DJANGO_DB_TEST_TEMPLATE", default="")
|
|
215
|
+
if _test_template:
|
|
216
|
+
DATABASES["default"]["TEST"] = {"TEMPLATE": _test_template}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
That's it — `pytest` will start a Postgres container, inject the port,
|
|
220
|
+
let pytest-django import settings, and tear the container down at exit.
|
|
221
|
+
|
|
222
|
+
## Init scripts / baseline
|
|
223
|
+
|
|
224
|
+
Mount SQL files into the Postgres container's
|
|
225
|
+
`/docker-entrypoint-initdb.d/` so they're replayed once on cluster init —
|
|
226
|
+
significantly faster than running `psql -f` from the host:
|
|
227
|
+
|
|
228
|
+
```toml
|
|
229
|
+
[tool.pytest-testcontainers-django]
|
|
230
|
+
postgres_database = "myapp"
|
|
231
|
+
postgres_init_scripts = [
|
|
232
|
+
"tests/fixtures/baseline.sql",
|
|
233
|
+
"tests/fixtures/extensions.sql",
|
|
234
|
+
]
|
|
235
|
+
# postgres_template defaults to postgres_database when init_scripts is
|
|
236
|
+
# set, so the test DB will be created via fast in-server CREATE DATABASE
|
|
237
|
+
# test_<X> WITH TEMPLATE myapp instead of replaying migrations.
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Combine with the `DATABASES['default']['TEST']['TEMPLATE']` snippet
|
|
241
|
+
above to make `pytest --create-db` finish in seconds.
|
|
242
|
+
|
|
243
|
+
## Optional Redis
|
|
244
|
+
|
|
245
|
+
`testcontainers`'s `RedisContainer` imports the `redis` Python client at
|
|
246
|
+
module load, so install it alongside this package when you enable Redis:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
uv add 'pytest-testcontainers-django[redis]'
|
|
250
|
+
# or
|
|
251
|
+
pip install 'pytest-testcontainers-django[redis]'
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
```toml
|
|
255
|
+
[tool.pytest-testcontainers-django]
|
|
256
|
+
redis_enabled = true
|
|
257
|
+
redis_image = "redis:7-alpine"
|
|
258
|
+
redis_host_env = "DJANGO_REDIS_HOST"
|
|
259
|
+
redis_port_env = "DJANGO_REDIS_PORT"
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Your settings reads `DJANGO_REDIS_HOST` / `DJANGO_REDIS_PORT` and folds
|
|
263
|
+
them into a `redis://...` URL however your stack prefers.
|
|
264
|
+
|
|
265
|
+
## Programmatic configuration
|
|
266
|
+
|
|
267
|
+
For projects that need conditional configuration or want to wire in
|
|
268
|
+
[`django-pg-baseline`](https://github.com/iplweb/django-pg-baseline) for
|
|
269
|
+
baseline-managed seed data, register from `conftest.py`:
|
|
270
|
+
|
|
271
|
+
```python
|
|
272
|
+
# conftest.py at the project root
|
|
273
|
+
from pathlib import Path
|
|
274
|
+
|
|
275
|
+
from pytest_testcontainers_django import (
|
|
276
|
+
DjangoContainerConfig,
|
|
277
|
+
PostgresService,
|
|
278
|
+
RedisService,
|
|
279
|
+
register,
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
register(
|
|
283
|
+
DjangoContainerConfig(
|
|
284
|
+
postgres=PostgresService(
|
|
285
|
+
image="postgres:16",
|
|
286
|
+
user="myapp",
|
|
287
|
+
password="myapp",
|
|
288
|
+
database="myapp",
|
|
289
|
+
init_scripts=[Path("tests/fixtures/baseline.sql")],
|
|
290
|
+
template="myapp",
|
|
291
|
+
),
|
|
292
|
+
redis=RedisService(),
|
|
293
|
+
)
|
|
294
|
+
)
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
`register()` overrides any `pyproject.toml` table. This works because
|
|
298
|
+
the plugin force-imports the rootdir `conftest.py` from inside its
|
|
299
|
+
`tryfirst` hook, so top-level `register(...)` calls run before
|
|
300
|
+
configuration is read.
|
|
301
|
+
|
|
302
|
+
## Disable / reuse
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
# Delegate to docker-compose / pre-existing services:
|
|
306
|
+
pytest --no-testcontainers
|
|
307
|
+
PYTEST_TESTCONTAINERS_DISABLE=1 pytest
|
|
308
|
+
|
|
309
|
+
# Keep containers alive between runs for fast local iteration:
|
|
310
|
+
PYTEST_TESTCONTAINERS_REUSE=1 pytest
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## pytest-xdist
|
|
314
|
+
|
|
315
|
+
Workers inherit the controller's environment on fork, so they don't
|
|
316
|
+
start new containers — they only re-set the `*_SKIP_DOTENV` flag so
|
|
317
|
+
django-environ doesn't re-read `.env` on settings re-import.
|
|
318
|
+
|
|
319
|
+
## Coexistence with other testcontainers
|
|
320
|
+
|
|
321
|
+
Django projects that need additional services (Elasticsearch, MinIO,
|
|
322
|
+
Kafka, etc.) declare plain pytest fixtures using
|
|
323
|
+
`pytest-testcontainers`'s maker functions directly — no special
|
|
324
|
+
integration with this package needed:
|
|
325
|
+
|
|
326
|
+
```python
|
|
327
|
+
# conftest.py
|
|
328
|
+
import pytest
|
|
329
|
+
from pytest_testcontainers import make_container
|
|
330
|
+
|
|
331
|
+
@pytest.fixture(scope="session")
|
|
332
|
+
def minio():
|
|
333
|
+
with make_container("minio/minio:latest", ports={"9000/tcp": None}) as c:
|
|
334
|
+
yield c
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Late resolution is fine for non-DB services — their host:port is read
|
|
338
|
+
at *connection time*, not import time. Only Django's `DATABASES` has
|
|
339
|
+
the import-time-read race that this package solves.
|
|
340
|
+
|
|
341
|
+
## Configuration reference
|
|
342
|
+
|
|
343
|
+
| Pyproject key | Default | Purpose |
|
|
344
|
+
| ----------------------------- | -------------------------------- | ------------------------------------------------ |
|
|
345
|
+
| `postgres_image` | `postgres:16` | Image used for the DB container |
|
|
346
|
+
| `postgres_user` | `postgres` | `POSTGRES_USER` |
|
|
347
|
+
| `postgres_password` | `postgres` | `POSTGRES_PASSWORD` |
|
|
348
|
+
| `postgres_database` | `postgres` | `POSTGRES_DB` |
|
|
349
|
+
| `postgres_internal_port` | `5432` | Image's internal port |
|
|
350
|
+
| `postgres_template` | (= `postgres_database` when init scripts set, else unset) | Value injected as `DATABASES['TEST']['TEMPLATE']` |
|
|
351
|
+
| `postgres_init_scripts` | `[]` | Paths mounted into `/docker-entrypoint-initdb.d/`|
|
|
352
|
+
| `postgres_env` | `{}` | Image-specific env (e.g. tuning flags) |
|
|
353
|
+
| `db_host_env` | `DJANGO_DB_HOST` | Env var written with the resolved host |
|
|
354
|
+
| `db_port_env` | `DJANGO_DB_PORT` | Env var written with the resolved port |
|
|
355
|
+
| `db_name_env` | `DJANGO_DB_NAME` | Env var written with `postgres_database` |
|
|
356
|
+
| `db_user_env` | `DJANGO_DB_USER` | Env var written with `postgres_user` |
|
|
357
|
+
| `db_password_env` | `DJANGO_DB_PASSWORD` | Env var written with `postgres_password` |
|
|
358
|
+
| `db_test_template_env` | `DJANGO_DB_TEST_TEMPLATE` | Env var written with `postgres_template` |
|
|
359
|
+
| `skip_dotenv_env` | `DJANGO_SKIP_DOTENV` | Env var your settings checks before reading .env |
|
|
360
|
+
| `disable_env` | `PYTEST_TESTCONTAINERS_DISABLE` | Env var that disables the plugin |
|
|
361
|
+
| `reuse_env` | `PYTEST_TESTCONTAINERS_REUSE` | Env var that enables reuse mode |
|
|
362
|
+
| `redis_enabled` | `false` | Enable Redis |
|
|
363
|
+
| `redis_image` | `redis:7-alpine` | Image used for Redis |
|
|
364
|
+
| `redis_internal_port` | `6379` | |
|
|
365
|
+
| `redis_host_env` | `DJANGO_REDIS_HOST` | |
|
|
366
|
+
| `redis_port_env` | `DJANGO_REDIS_PORT` | |
|
|
367
|
+
| `use_django_pg_baseline` | `false` | Auto-prepend `django-pg-baseline`'s artifact |
|
|
368
|
+
|
|
369
|
+
## License
|
|
370
|
+
|
|
371
|
+
MIT — see [`LICENSE`](LICENSE).
|