Running Tests
# All Rust tests
cargo test --workspace
# Single crate
cargo test -p justapi-core
# Python tests
pytest
# With uv
uv run pytest
# Miri (unsafe validation)
cargo +nightly miri test -p justapi-core
Writing Rust Tests
Unit tests go at the bottom of the module they test:
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_normalize_db_url() {
assert_eq!(normalize_db_url("sqlite:///foo.db"), "sqlite:foo.db");
assert_eq!(normalize_db_url("sqlite:////tmp/foo.db"), "sqlite:/tmp/foo.db");
}
}
Writing Python Tests
Use the JustAPITestClient for in-process testing:
from justapi import JustAPIApp, JustAPITestClient
def test_hello_world():
app = JustAPIApp()
@app.get("/hello")
def hello(request):
return {"message": "Hello!"}
client = JustAPITestClient(app)
response = client.get("/hello")
assert response.status == 200
assert response.json() == {"message": "Hello!"}
Testing POST Endpoints
def test_create_item():
app = JustAPIApp()
@app.post("/items")
def create(request):
data = request.json()
return {"id": 1, **data}
client = JustAPITestClient(app)
response = client.post("/items", body={"name": "Widget", "price": 9.99})
assert response.status == 200
assert response.json()["name"] == "Widget"
Testing Errors
def test_404():
app = JustAPIApp()
client = JustAPITestClient(app)
response = client.get("/nonexistent")
assert response.status == 404
Integration Testing
For integration tests that need a running server:
# tests/test_app.py
from justapi import JustAPIApp
app = JustAPIApp()
@app.get("/health")
def health(request):
return {"status": "ok"}
Then use JustAPITestClient for end-to-end flow tests.
Property-Based Testing
Use proptest for Rust property-based tests:
use proptest::prelude::*;
proptest! {
#[test]
fn test_route_roundtrip(path in ".*") {
// Property: route matching should never panic
let router = Router::new();
// ...
}
}
Test File Layout
tests/
├── test_annotations.py
├── test_middleware.py
├── test_responses.py
├── test_multipart.py
├── test_exceptions.py
├── test_db_concurrent.py
└── ...
CI Testing
Every PR runs via .github/workflows/wheels.yml:
cargo test --workspacecargo clippy -- -D warningscargo fmt --checkcargo deny check(advisories, bans, licenses, sources)cargo miri test -p justapi-core(nightly)- Build wheels for 6 targets (linux x86_64/aarch64, musl, macOS x86_64/aarch64, Windows x64)
pytestafter wheel build (Python 3.12 + free-threaded 3.14t)- Publish to PyPI via OIDC trusted publishing (on tagged releases)
On release, .github/workflows/wheels.yml builds the 9-platform wheel matrix and publishes to PyPI via OIDC trusted publishing (no token). Push a v* tag to trigger it.
See Also
- Development Setup — Get started
- Coding Standards — Code conventions
- Testing Client API —
JustAPITestClientreference