Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

You are reading the development version (master). For the latest release (v3.6.0) see the stable docs.

Testing Guide

TestHarness

The primary testing tool. No host UI required.

#![allow(unused)]
fn main() {
use boruna_framework::testing::TestHarness;
use boruna_framework::runtime::AppMessage;
use boruna_bytecode::Value;

let mut harness = TestHarness::from_source(SOURCE)?;
}

Send Messages

#![allow(unused)]
fn main() {
let (state, effects) = harness.send(
    AppMessage::new("increment", Value::Int(0))
)?;
}

Simulate Sequences

#![allow(unused)]
fn main() {
let final_state = harness.simulate(vec![
    AppMessage::new("add", Value::Int(0)),
    AppMessage::new("add", Value::Int(0)),
    AppMessage::new("complete", Value::Int(0)),
])?;
}

Assertions

#![allow(unused)]
fn main() {
// Check a specific field by index
harness.assert_state_field(0, &Value::Int(3))?;

// Check full state equality
harness.assert_state(&expected_value)?;

// Check effects from last cycle
harness.assert_effects(&["http_request"])?;
}

Snapshots

#![allow(unused)]
fn main() {
let json = harness.snapshot();  // JSON string of current state
}

Time Travel

#![allow(unused)]
fn main() {
harness.rewind(0)?;  // Go back to init state
}

Replay Verification

#![allow(unused)]
fn main() {
let messages = vec![
    AppMessage::new("increment", Value::Int(0)),
    AppMessage::new("increment", Value::Int(0)),
];
for msg in &messages {
    harness.send(msg.clone())?;
}

// Replay same messages on fresh runtime, verify identical states
let identical = harness.replay_verify(SOURCE, messages)?;
assert!(identical);
}

Golden Tests

Golden tests verify determinism. Run the same messages twice, compare:

#![allow(unused)]
fn main() {
let mut h1 = TestHarness::from_source(SOURCE)?;
let mut h2 = TestHarness::from_source(SOURCE)?;

for msg in &messages {
    h1.send(msg.clone())?;
    h2.send(msg.clone())?;
}

assert_eq!(h1.state(), h2.state());
assert_eq!(h1.snapshot(), h2.snapshot());
}

CLI Testing

# Validate app protocol
boruna framework validate my_app.ax

# Send messages and see state
boruna framework test my_app.ax -m "add:0,add:0,complete:0"

# Inspect state as JSON
boruna framework inspect-state my_app.ax -m "add:0,add:0"

# Step-by-step simulation
boruna framework simulate my_app.ax "add:0,add:0,complete:0"

# Machine-readable diagnostics
boruna framework diag my_app.ax -m "add:0,add:0"

# Stable trace hash (for CI comparison)
boruna framework trace-hash my_app.ax -m "add:0,add:0"

# App contract summary
boruna framework inspect my_app.ax --json

Message Format

CLI messages use tag:payload format:

  • increment:0 → tag=“increment”, payload=Int(0)
  • fetch:https://example.com → tag=“fetch”, payload=String(“https://example.com”)
  • reset → tag=“reset”, payload=Int(0) (default)

Comma-separated for sequences: add:0,add:0,complete:0

Writing Test Apps

Include fn main() -> Int for standalone execution:

fn main() -> Int {
    let s0: State = init()
    let r1: UpdateResult = update(s0, Msg { tag: "add", payload: 0 })
    let r2: UpdateResult = update(r1.state, Msg { tag: "add", payload: 0 })
    r2.state.total
}

Run directly: boruna run my_app.ax