A C/S architecture test runner for heavy AI projects.
Project description
Sprintest
[English] | 简体中文
Sprintest is a high-performance Client-Server (C/S) architecture test runner specifically engineered for heavy AI/ML projects.
In projects involving large language models (LLMs), deep learning frameworks (PyTorch, TensorFlow), or massive datasets, standard test runners suffer from excruciatingly slow startup times (often 30s to several minutes) because they re-initialize the entire environment for every run. Sprintest solves this by keeping your heavy dependencies pre-loaded in memory.
🚀 Key Highlights
- ⚡ Blazing Fast Feedback: Reduces test startup time from minutes to milliseconds by keeping heavy frameworks and models pre-loaded in a background daemon.
- 🔄 Intelligent Hot-Reloading: Features a "Nuke Engine" that surgically unloads only your project's modified modules, ensuring you always test against the latest code without losing the pre-loaded state.
- 🔌 Unified Transport Layer: Automatically chooses between Unix Domain Sockets (UDS) for zero-latency local communication and TCP for maximum compatibility.
- 🛠️ Decoupled Architecture: Built with a robust service layer and atomic state management, ensuring stable communication even during heavy test execution.
- 🤖 Agent-Optimized: Designed for AI coding agents (like Antigravity or Cursor) with clean, ANSI-free output and reliable status tracking.
- 🎯 Configurable Strategy: Fine-tune hot-reloading with
ignore_patternsin yourpyproject.tomlto prevent specific heavy modules from being reloaded.
⚡ Performance Comparison
For AI/ML projects with heavy dependencies (torch, transformers, etc.), Sprintest provides a massive speedup by eliminating redundant initialization.
| Run Type | Total Time |
|---|---|
| Pytest (Standard) | ~6.0s |
| Sprintest (First Run) | ~7.0s |
| Sprintest (Warm Start) | ~2.0s |
Numbers above are measured on examples/test_ai_model.py and are provided for reference only. In heavier real-world projects, speedups typically reach 5x - 10x—for example, in my other project engram-peft, unit test total wall time improved by 7.8x (integration tests not included).
🏗️ Architecture
Sprintest uses a decoupled architecture to ensure the daemon remains responsive even when running heavy tests.
System Architecture
graph TD
Client["Client CLI"] -->|HTTP over UDS/TCP| App["FastAPI App"]
subgraph "Daemon Process"
App --> Service["TestService"]
Service -->|Atomic Lock| Service
Service --> Nuke["NukeStrategy"]
Nuke -->|Module Unloading| PySys[sys.modules]
Service --> Runner["TestRunner"]
Runner -->|Pytest execution| Tests["User Tests"]
end
App -.-> Status["status.json"]
Client -.-> Status
Test Execution Flow
sequenceDiagram
participant C as "Client CLI"
participant S as "status.json"
participant D as "Daemon (FastAPI)"
participant N as "NukeStrategy"
participant R as "TestRunner"
C->>S: Read status
alt Daemon not running
C->>D: Start Daemon (subprocess)
D->>D: Acquire daemon.lock
D->>D: Start Uvicorn
D->>S: Write status (lifespan)
C->>S: Poll until ready
end
C->>D: POST /v1/test/run/stream
activate D
D->>D: Acquire test_lock
D->>N: nuke(target_pkg)
N-->>D: Modules unloaded
D->>R: run_tests(args)
R->>R: Redirect stdout/stderr
R->>R: pytest.main()
R-->>D: Exit code & Output
D->>N: nuke_tests()
N-->>D: Test modules cleared
D-->>C: Stream results
deactivate D
C->>C: Print output & exit
📦 Installation
pip install sprintest
📖 Quick Start
-
Run a test: Simply run
stestfollowed by your test file. If the daemon isn't running, it will start automatically.stest tests/test_model_loading.py -
Check Daemon status:
stest status -
Stop the Daemon:
stest stop
⚙️ Configuration
Environment Variables & Isolation
SPRINTEST_TARGET_PKG: The name of the package you are developing. Sprintest will prioritize hot-reloading this package.SPRINTEST_FORCE_TCP: Set to1to bypass Unix Sockets and force TCP communication.SPRINTEST_PORT: Customize the TCP port (default:8000).SPRINTEST_DIR: Override the default.sprintestdirectory (useful for multi-project isolation or CI environments).SPRINTEST_LOCK_FILE: Override the daemon lock file path.SPRINTEST_LOG_LEVEL: Set log level (DEBUG, INFO, WARNING, ERROR).
Advanced: pyproject.toml
You can prevent specific modules from being "nuked" during hot-reload by adding them to the ignore list:
[tool.sprintest]
ignore = [
"torch.*",
"transformers.*",
"heavy_module_to_keep"
]
🧪 Testing the Runner
Standard Unit Tests
uv run pytest tests
Self-Hosting (Bootstrap) Test
Sprintest can reliably run its own test suite through its own daemon to verify infrastructure stability:
stest tests
📄 License
MIT License. See LICENSE for details.
Project details
Release history Release notifications | RSS feed
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 sprintest-1.0.7.tar.gz.
File metadata
- Download URL: sprintest-1.0.7.tar.gz
- Upload date:
- Size: 32.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
268d007b1e6b2449c783e8e72dba45d912594fd753a2bb09edc179840c5a74a4
|
|
| MD5 |
8185fec3408fb51c065e9a814ca01063
|
|
| BLAKE2b-256 |
01c1bed5f40bcf33499c8ce6c025db0e8cc261e4d20c2151636d223e4040cbe6
|
Provenance
The following attestation bundles were made for sprintest-1.0.7.tar.gz:
Publisher:
publish.yml on QingGo/sprintest
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sprintest-1.0.7.tar.gz -
Subject digest:
268d007b1e6b2449c783e8e72dba45d912594fd753a2bb09edc179840c5a74a4 - Sigstore transparency entry: 1349697347
- Sigstore integration time:
-
Permalink:
QingGo/sprintest@55527fd87a152d99d7e73c323828db0bcee233f2 -
Branch / Tag:
refs/tags/v1.0.7 - Owner: https://github.com/QingGo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@55527fd87a152d99d7e73c323828db0bcee233f2 -
Trigger Event:
push
-
Statement type:
File details
Details for the file sprintest-1.0.7-py3-none-any.whl.
File metadata
- Download URL: sprintest-1.0.7-py3-none-any.whl
- Upload date:
- Size: 25.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6acb5f7fc012cd3831e3d1bd833cd3a29c5e058668ff00a7d0199b070c88b411
|
|
| MD5 |
3cc8f5c51349b986add13c40111fc213
|
|
| BLAKE2b-256 |
6de6c2d29bbe1a44ce9de01ba66182ac3d31d308e59a7829c9f0f1c3fbaa53e8
|
Provenance
The following attestation bundles were made for sprintest-1.0.7-py3-none-any.whl:
Publisher:
publish.yml on QingGo/sprintest
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sprintest-1.0.7-py3-none-any.whl -
Subject digest:
6acb5f7fc012cd3831e3d1bd833cd3a29c5e058668ff00a7d0199b070c88b411 - Sigstore transparency entry: 1349697437
- Sigstore integration time:
-
Permalink:
QingGo/sprintest@55527fd87a152d99d7e73c323828db0bcee233f2 -
Branch / Tag:
refs/tags/v1.0.7 - Owner: https://github.com/QingGo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@55527fd87a152d99d7e73c323828db0bcee233f2 -
Trigger Event:
push
-
Statement type: