Skip to content

Commit d4560e6

Browse files
Implement testcontainers for pytest-managed container lifecycle
Tests now automatically start MySQL and MinIO containers via testcontainers. No manual `docker-compose up` required - just run `pytest tests/`. Changes: - conftest.py: Add mysql_container and minio_container fixtures that auto-start containers when tests run and stop them afterward - pyproject.toml: Add testcontainers[mysql,minio] dependency, update pixi tasks, remove pytest-env (no longer needed) - docker-compose.yaml: Update docs to clarify it's optional for tests - README.md: Comprehensive developer guide with clear instructions for running tests, pre-commit hooks, and PR submission checklist Usage: - Default: `pytest tests/` - testcontainers manages containers - External: `DJ_USE_EXTERNAL_CONTAINERS=1 pytest` - use docker-compose Benefits: - Zero setup for developers - just `pip install -e ".[test]" && pytest` - Dynamic ports (no conflicts with other services) - Automatic cleanup after tests - Simpler CI configuration Version bump to 2.0.0a7 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 11e492b commit d4560e6

File tree

5 files changed

+289
-149
lines changed

5 files changed

+289
-149
lines changed

README.md

Lines changed: 66 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -146,30 +146,57 @@ DataJoint (<https://datajoint.com>).
146146

147147
### Prerequisites
148148

149-
- [Docker](https://docs.docker.com/get-docker/) for MySQL and MinIO services
149+
- [Docker](https://docs.docker.com/get-docker/) (Docker daemon must be running)
150150
- Python 3.10+
151151

152-
### Running Tests
153-
154-
Tests are organized into `unit/` (no external services) and `integration/` (requires MySQL + MinIO):
152+
### Quick Start
155153

156154
```bash
157-
# Install dependencies
155+
# Clone and install
156+
git clone https://github.com/datajoint/datajoint-python.git
157+
cd datajoint-python
158158
pip install -e ".[test]"
159159
160-
# Run unit tests only (fast, no Docker needed)
161-
pytest tests/unit/
160+
# Run all tests (containers start automatically via testcontainers)
161+
pytest tests/
162162
163-
# Start MySQL and MinIO for integration tests
164-
docker compose up -d db minio
163+
# Install and run pre-commit hooks
164+
pip install pre-commit
165+
pre-commit install
166+
pre-commit run --all-files
167+
```
165168

166-
# Run all tests
169+
### Running Tests
170+
171+
Tests use [testcontainers](https://testcontainers.com/) to automatically manage MySQL and MinIO containers.
172+
**No manual `docker-compose up` required** - containers start when tests run and stop afterward.
173+
174+
```bash
175+
# Run all tests (recommended)
167176
pytest tests/
168177
178+
# Run with coverage report
179+
pytest --cov-report term-missing --cov=datajoint tests/
180+
169181
# Run specific test file
170182
pytest tests/integration/test_blob.py -v
171183
172-
# Stop services when done
184+
# Run only unit tests (no containers needed)
185+
pytest tests/unit/
186+
```
187+
188+
### Alternative: External Containers
189+
190+
For development/debugging, you may prefer persistent containers that survive test runs:
191+
192+
```bash
193+
# Start containers manually
194+
docker compose up -d db minio
195+
196+
# Run tests using external containers
197+
DJ_USE_EXTERNAL_CONTAINERS=1 pytest tests/
198+
199+
# Stop containers when done
173200
docker compose down
174201
```
175202

@@ -183,24 +210,46 @@ docker compose --profile test up djtest --build
183210

184211
### Alternative: Using pixi
185212

186-
[pixi](https://pixi.sh) users can run tests with automatic service management:
213+
[pixi](https://pixi.sh) users can run tests with:
187214

188215
```bash
189216
pixi install # First time setup
190-
pixi run test # Starts services and runs tests
191-
pixi run services-down # Stop services
217+
pixi run test # Runs tests (testcontainers manages containers)
192218
```
193219

194220
### Pre-commit Hooks
195221

222+
Pre-commit hooks run automatically on `git commit` to check code quality.
223+
**All hooks must pass before committing.**
224+
196225
```bash
197-
pre-commit install # Install hooks (first time)
198-
pre-commit run --all-files # Run all checks
226+
# Install hooks (first time only)
227+
pip install pre-commit
228+
pre-commit install
229+
230+
# Run all checks manually
231+
pre-commit run --all-files
232+
233+
# Run specific hook
234+
pre-commit run ruff --all-files
235+
pre-commit run codespell --all-files
199236
```
200237

238+
Hooks include:
239+
- **ruff**: Python linting and formatting
240+
- **codespell**: Spell checking
241+
- **YAML/JSON/TOML validation**
242+
- **Large file detection**
243+
244+
### Before Submitting a PR
245+
246+
1. **Run all tests**: `pytest tests/`
247+
2. **Run pre-commit**: `pre-commit run --all-files`
248+
3. **Check coverage**: `pytest --cov-report term-missing --cov=datajoint tests/`
249+
201250
### Environment Variables
202251

203-
Tests use these defaults (configured in `pyproject.toml`):
252+
For external container mode (`DJ_USE_EXTERNAL_CONTAINERS=1`):
204253

205254
| Variable | Default | Description |
206255
|----------|---------|-------------|

docker-compose.yaml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
# Development environment with MySQL and MinIO services
22
#
3-
# Quick start:
4-
# docker compose up -d db minio # Start services
5-
# pytest tests/ # Run tests (uses localhost defaults)
3+
# NOTE: docker-compose is OPTIONAL for running tests.
4+
# Tests use testcontainers to automatically manage containers.
5+
# Just run: pytest tests/
66
#
7-
# Full Docker testing:
7+
# Use docker-compose for development/debugging when you want
8+
# persistent containers that survive test runs:
9+
# docker compose up -d db minio # Start services manually
10+
# pytest tests/ # Tests will use these containers
11+
#
12+
# Full Docker testing (CI):
813
# docker compose --profile test up djtest --build
914
services:
1015
db:

pyproject.toml

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ datajoint = "datajoint.cli:cli"
8484
test = [
8585
"pytest",
8686
"pytest-cov",
87-
"pytest-env",
8887
"requests",
8988
"graphviz",
89+
"testcontainers[mysql,minio]>=4.0",
9090
]
9191

9292
[project.optional-dependencies]
@@ -96,9 +96,9 @@ azure = ["adlfs>=2023.1.0"]
9696
test = [
9797
"pytest",
9898
"pytest-cov",
99-
"pytest-env",
10099
"requests",
101100
"s3fs>=2023.1.0",
101+
"testcontainers[mysql,minio]>=4.0",
102102
]
103103
dev = [
104104
"pre-commit",
@@ -158,20 +158,7 @@ skip = ".git,*.pdf,*.svg,*.csv,*.ipynb,*.drawio"
158158
# astroid -- Python library name (not "asteroid")
159159
ignore-words-list = "rever,numer,astroid"
160160

161-
[tool.pytest_env]
162-
# Default environment variables for tests (D: prefix = only set if not defined)
163-
# These defaults work for local development with `docker compose up -d db minio`
164-
# For devcontainer/docker: override DJ_HOST=db and S3_ENDPOINT=minio:9000
165-
"D:DJ_HOST" = "localhost"
166-
"D:DJ_PORT" = "3306"
167-
"D:DJ_USER" = "root"
168-
"D:DJ_PASS" = "password"
169-
"D:DJ_TEST_USER" = "datajoint"
170-
"D:DJ_TEST_PASSWORD" = "datajoint"
171-
"D:S3_ENDPOINT" = "localhost:9000"
172-
"D:S3_ACCESS_KEY" = "datajoint"
173-
"D:S3_SECRET_KEY" = "datajoint"
174-
"D:S3_BUCKET" = "datajoint.test"
161+
# pytest-env removed - testcontainers handles container lifecycle automatically
175162

176163

177164
[tool.pixi.workspace]
@@ -187,12 +174,13 @@ dev = { features = ["dev"], solve-group = "default" }
187174
test = { features = ["test"], solve-group = "default" }
188175

189176
[tool.pixi.tasks]
190-
# Start required services (MySQL and MinIO)
177+
# Tests use testcontainers - no manual setup required
178+
test = "pytest tests/"
179+
test-cov = "pytest --cov-report term-missing --cov=datajoint tests/"
180+
# Optional: use external containers (docker-compose) instead of testcontainers
191181
services-up = "docker compose up -d db minio"
192182
services-down = "docker compose down"
193-
# Run tests (requires services to be running, uses localhost defaults from pytest_env)
194-
test = { cmd = "pytest tests/", depends-on = ["services-up"] }
195-
test-cov = { cmd = "pytest --cov-report term-missing --cov=datajoint tests/", depends-on = ["services-up"] }
183+
test-external = { cmd = "DJ_USE_EXTERNAL_CONTAINERS=1 pytest tests/", depends-on = ["services-up"] }
196184

197185
[tool.pixi.dependencies]
198186
python = ">=3.10,<3.14"

src/datajoint/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# version bump auto managed by Github Actions:
22
# label_prs.yaml(prep), release.yaml(bump), post_release.yaml(edit)
33
# manually set this version will be eventually overwritten by the above actions
4-
__version__ = "2.0.0a6"
4+
__version__ = "2.0.0a7"

0 commit comments

Comments
 (0)