Testing Guide
ICL has 268 tests across Rust, Python, JavaScript, and Go. Every test proves determinism.
Running Tests
Rust (core + CLI)
cd ICL-Runtime
cargo test --workspace
# 203 tests passing (175 icl-core + 28 icl-cli)
Python
cd ICL-Runtime/bindings/python
pip install -e .
pytest tests/
# 18 tests passing
JavaScript
cd ICL-Runtime/bindings/javascript
wasm-pack build --target nodejs
node tests/test_icl.mjs
# 31 tests passing
Go
cd ICL-Runtime/bindings/go
LD_LIBRARY_PATH=../../target/release go test -v
# 16 tests passing
Test Categories
1. Unit Tests (in-crate)
Located alongside source code in #[cfg(test)] modules. Each module has its own tests.
cargo test -p icl-core # All core tests
cargo test -p icl-core parser # Parser tests only
cargo test -p icl-core normalizer # Normalizer tests only
cargo test -p icl-core verifier # Verifier tests only
cargo test -p icl-core executor # Executor tests only
2. Integration Tests
Located in tests/integration/. Test cross-module behavior — parsing a contract, then normalizing, verifying, and executing it.
cargo test --test '*'
3. Conformance Tests
Located in tests/conformance/. Validate the runtime against the ICL-Spec conformance suite.
conformance/valid/— contracts that must parse successfullyconformance/invalid/— contracts that must be rejected with clear errorsconformance/normalization/— input/expected pairs for canonical form
cargo test conformance
4. Determinism Tests
Located in tests/determinism/. Every test runs 100 iterations and verifies identical output.
cargo test determinism
Writing Tests
Rule 1: Every Test Must Prove Determinism
#![allow(unused)] fn main() { #[test] fn test_my_feature() { let input = "..."; let first_result = my_function(input); for _ in 0..100 { assert_eq!(my_function(input), first_result); } } }
Rule 2: No Randomness, No System Time
Tests must not depend on:
- Random number generators
- Current system time
- File system ordering
- Thread scheduling
Rule 3: Test Both Valid and Invalid Inputs
#![allow(unused)] fn main() { #[test] fn test_rejects_invalid_confidence() { let input = r#"Contract { ... PurposeStatement { confidence_level: 1.5 } ... }"#; assert!(parse_contract(input).is_err()); } }
Rule 4: Conformance Fixtures
When adding parser/normalizer features, add matching fixtures to ICL-Spec:
conformance/valid/— must parseconformance/invalid/— must be rejectedconformance/normalization/— input→canonical pairs
Cross-Language Determinism
All language bindings must produce identical results to the Rust core. The binding test suites include 100-iteration determinism proofs:
Python:
def test_normalize_determinism():
first = icl.normalize(contract_text)
for _ in range(100):
assert icl.normalize(contract_text) == first
JavaScript:
const first = icl.normalize(contractText);
for (let i = 0; i < 100; i++) {
assert.strictEqual(icl.normalize(contractText), first);
}
Go:
first, _ := icl.Normalize(contract)
for i := 0; i < 100; i++ {
result, _ := icl.Normalize(contract)
if result != first {
t.Fatalf("Non-determinism at iteration %d", i)
}
}
Test Counts by Component
| Component | Tests | Includes Determinism Proof |
|---|---|---|
| Parser (tokenizer + AST + recursive descent) | ~80 | Yes |
| Normalizer (canonical form + hashing) | ~30 | Yes (idempotence + 100-iter) |
| Verifier (types + invariants + determinism + coherence) | ~40 | Yes |
| Executor (sandbox + provenance) | ~20 | Yes |
| CLI (all 9 commands) | 28 | — |
| Python binding | 18 | Yes (100-iter) |
| JavaScript binding | 31 | Yes (100-iter) |
| Go binding | 16 | Yes (100-iter) |
| Total | ~268 |