Skip to content

How-To: Test Your Logic

Learn how to write and run automated tests for your Vox application using the built-in test runner.

Use the @test decorator to mark functions as test cases. These functions can be run with the vox test command.

@test
fn test_addition() to Unit {
assert(1 + 1 is 2)
}

Rather than language-level magic, Vox encourages simple, plain functions for setup logic that can be reused across test cases.

type TestFixture {
seed_value: int
}
fn setup_mock_db() to TestFixture {
return { seed_value: 1 }
}
@test
fn test_query() to Unit {
let db_ctx = setup_mock_db()
assert(db_ctx.seed_value is 1)
}

Vox supports property-based testing. The test runner will generate random inputs for your function to find edge cases where your assertions fail.

@forall
fn test_addition_commutative(a: int, b: int) to Unit {
assert(a + b is b + a)
}

For deeper security and stability testing, the @fuzz decorator uses the project’s native LLVM-based fuzzer to explore illegal execution paths.

@fuzz
fn fuzz_parser(input: str) to Unit {
let _result = std.json.parse(input) // Fuzzer tries to crash this
}

Use the vox test command to execute your suite.

Terminal window
vox test src/

Output Example:

[PASS] tests::test_addition (1.2ms)
[PASS] tests::test_addition_commutative (100 iterations)
[FAIL] tests::fuzz_parser
> Reason: Panic at core.vox:120 (division by zero)
> Input: "{"a": 0}"
  • Use @test for standard unit tests.
  • Use @forall for property-based data validation.
  • Use @fuzz for security and crash-resilience testing.
  • Write standard functions that serve as setups, fixtures, and mocks explicitly.
  • Run vox test <path> to execute blocks tagged with @test.