Skip to main content

A C/S architecture test runner for heavy AI projects.

Project description

Sprintest

PyPI version License: MIT Python 3.10+

[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_patterns in your pyproject.toml to 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

  1. Run a test: Simply run stest followed by your test file. If the daemon isn't running, it will start automatically.

    stest tests/test_model_loading.py
    
  2. Check Daemon status:

    stest status
    
  3. 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 to 1 to bypass Unix Sockets and force TCP communication.
  • SPRINTEST_PORT: Customize the TCP port (default: 8000).
  • SPRINTEST_DIR: Override the default .sprintest directory (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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sprintest-1.0.7.tar.gz (32.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sprintest-1.0.7-py3-none-any.whl (25.1 kB view details)

Uploaded Python 3

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

Hashes for sprintest-1.0.7.tar.gz
Algorithm Hash digest
SHA256 268d007b1e6b2449c783e8e72dba45d912594fd753a2bb09edc179840c5a74a4
MD5 8185fec3408fb51c065e9a814ca01063
BLAKE2b-256 01c1bed5f40bcf33499c8ce6c025db0e8cc261e4d20c2151636d223e4040cbe6

See more details on using hashes here.

Provenance

The following attestation bundles were made for sprintest-1.0.7.tar.gz:

Publisher: publish.yml on QingGo/sprintest

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for sprintest-1.0.7-py3-none-any.whl
Algorithm Hash digest
SHA256 6acb5f7fc012cd3831e3d1bd833cd3a29c5e058668ff00a7d0199b070c88b411
MD5 3cc8f5c51349b986add13c40111fc213
BLAKE2b-256 6de6c2d29bbe1a44ce9de01ba66182ac3d31d308e59a7829c9f0f1c3fbaa53e8

See more details on using hashes here.

Provenance

The following attestation bundles were made for sprintest-1.0.7-py3-none-any.whl:

Publisher: publish.yml on QingGo/sprintest

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page