"Testing Standard — SSOT"

Testing Standard — SSOT

This document is the Single Source of Truth for how tests are organized, named, and structured across all 51 crates in the Vox workspace.

[!IMPORTANT] All new tests and test refactors must conform to this standard. PRs that introduce new dummy_span() definitions, _tests.rs naming, or tests inside src/ files will be flagged by TOESTUB.

1. File Naming

Use the _test.rs suffix (singular) for all test files:

ContextPatternExample
Unit (inline)#[cfg(test)] mod tests { ... } at bottom of filesrc/unify.rsmod tests {}
Integrationtests/<feature>_test.rstests/scope_test.rs
End-to-endvox-integration-tests/tests/<domain>_test.rstests/pipeline_ts_codegen_test.rs

Never use _tests.rs (plural). Never create tests_*.rs source files inside src/.

2. Test Placement Rules

Unit tests (#[cfg(test)] mod tests)

  • Test private internals; live inline in the source file.
  • Maximum 150 lines per inline test module.
  • If a module tests only the public API and exceeds 50 lines → extract to tests/.

Integration tests (tests/*.rs)

  • Test the public API of the crate.
  • Each file covers one feature domain, not a mix.
  • Never put multiple unrelated subsystems in one test file.

End-to-end tests (vox-integration-tests/tests/)

  • Cross-crate pipeline scenarios (lex → parse → hir → typeck → codegen).
  • Grouped by pipeline phase or language feature area.
  • Do not put 20+ tests in a single file (sign of a God file).

3. Shared Test Infrastructure

All shared test builders and assertion helpers live in vox-test-harness.

#![allow(unused)]
fn main() {
// ✅ Correct — import from shared harness
use vox_test_harness::spans::dummy_span;
use vox_test_harness::hir_builders::minimal_hir_module;
use vox_test_harness::assertions::{has_error, error_messages};
use vox_test_harness::pipeline::{parse_str_unwrap, typecheck_str};

// ❌ Wrong — define locally
fn dummy_span() -> Span { Span { start: 0, end: 0 } }
}

Never define dummy_span(), minimal_module(), module_with_fn(), or similar helpers locally in test files.

4. Test Function Naming

LocationPatternExample
Inline mod teststest_<unit>_<scenario>test_unify_simple_int
Integration (tests/)<feature>_<scenario>scope_affinity_group_routing
B-ticket regressionb<NNN>_<description>b090_vox_init_creates_expected_scaffold

5. Anti-Patterns (Banned)

Anti-PatternResolution
fn dummy_span() defined locallyImport from vox_test_harness::spans
fn minimal_module() defined locallyImport from vox_test_harness::hir_builders
Test file named *_tests.rsRename to *_test.rs
tests_*.rs file inside src/Move to tests/ directory
>20 tests in a single integration test fileSplit by feature domain
Zero tests in a non-stub crateAdd smoke tests at minimum

6. Crate Test Coverage Requirements

Crate TierRequirement
Compiler pipeline (lexer, parser, hir, typeck, codegen)Full unit + integration coverage
Runtime, orchestrator, MCPUnit coverage of all public API + integration smoke tests
CLI commandsIntegration test for each subcommand happy path
Future/stub crates (vox-codegen-llvm, vox-codegen-wasm)Exempt until implementation begins

7. Running Tests

# All tests
cargo test --workspace

# Single crate
cargo test -p vox-<crate>

# Specific integration test file
cargo test -p vox-integration-tests --test pipeline_ts_codegen_test

# Shared harness
cargo test -p vox-test-harness

8. References