Testing Guide
Running Tests
Section titled “Running Tests”# All Rust testscargo test --workspace
# Single cratecargo test -p justapi-core
# Python testspytest
# With uvuv run pytest
# Miri (unsafe validation)cargo +nightly miri test -p justapi-coreWriting Rust Tests
Section titled “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
Section titled “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
Section titled “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
Section titled “Testing Errors”def test_404(): app = JustAPIApp() client = JustAPITestClient(app) response = client.get("/nonexistent") assert response.status == 404Integration Testing
Section titled “Integration Testing”For integration tests that need a running server:
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
Section titled “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
Section titled “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
Section titled “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/publish.yml handles the standalone publish matrix.
See Also
Section titled “See Also”- Development Setup — Get started
- Coding Standards — Code conventions
- Testing Client API —
JustAPITestClientreference