Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/noir-lang/noir/llms.txt

Use this file to discover all available pages before exploring further.

Nargo has a built-in test runner. Any function annotated with #[test] is compiled and executed as a test when you run nargo test. Tests pass if the function completes without a constraint failure, and fail otherwise.

Writing tests

Annotate a function with #[test] to mark it as a test. The function must take no arguments for a standard unit test.
fn add(x: u64, y: u64) -> u64 {
    x + y
}

#[test]
fn test_add() {
    assert(add(2, 2) == 4);
    assert(add(0, 1) == 1);
    assert(add(1, 0) == 1);
}
Run all tests with:
nargo test
Nargo compiles and executes every #[test] function, then reports the results:
[my_project] Testing 1 test(s)
[my_project] test test_add ... ok
[my_project] 1 passed, 0 failed, 0 skipped

Using assert and assert_eq

Tests express expectations using assert and assert_eq. A failing assertion causes the test to fail.
#[test]
fn test_assertions() {
    let x: u32 = 10;
    let y: u32 = 5;

    assert(x > y);
    assert_eq(x - y, 5);
    assert(x != 0, "x should not be zero");
}
assert_eq(a, b) checks that a == b and provides a clearer failure message than assert(a == b).

Running specific tests

Pass a name substring to nargo test to run only matching tests:
nargo test add
This runs all tests whose names contain "add". Use --exact to match the full name only:
nargo test test_add --exact
To list all tests without running them:
nargo test --list-tests

Tests expected to fail

Use #[test(should_fail)] for tests that are expected to trigger a constraint failure. The test passes only if execution fails.
fn add(x: u64, y: u64) -> u64 {
    x + y
}

#[test(should_fail)]
fn test_incorrect_result() {
    // This assertion is wrong — the test passes because it fails
    assert(add(2, 2) == 5);
}

Matching the failure message

Use should_fail_with to assert that the failure message contains a specific string. This lets you verify that the right assertion failed.
fn check_speed(speed: u64) {
    assert(speed == 65, "What is the airspeed velocity of an unladen swallow");
}

#[test]
fn test_correct_speed() {
    check_speed(65);
}

#[test(should_fail_with = "What is the airspeed velocity of an unladen swallow")]
fn test_wrong_speed() {
    check_speed(32);
}
The string passed to should_fail_with does not need to be an exact match — it only needs to be a substring of the failure message:
#[test(should_fail_with = "airspeed velocity")]
fn test_wrong_speed_substring() {
    check_speed(32);
}

Unconstrained tests

Tests can call unconstrained functions directly. Marking a test function itself as unconstrained allows it to run entirely in the Brillig (unconstrained) VM, which can be useful for testing helper logic without circuit constraints.
unconstrained fn double(x: u32) -> u32 {
    x * 2
}

#[test]
fn test_double() {
    assert_eq(double(4), 8);
}

Fuzz tests

When a #[test] function takes one or more arguments, it becomes a fuzz test. Nargo automatically generates and mutates inputs to explore the function’s behavior.
#[test]
fn test_commutativity(a: Field, b: Field) {
    assert(a + b == b + a);
}
The fuzzer runs for up to 1 second and 100,000 executions by default, using all available threads. Fuzz tests also support should_fail and should_fail_with:
#[test(should_fail)]
fn test_should_find_failure(a: [bool; 32]) {
    let mut or_sum = false;
    for i in 0..32 {
        or_sum = or_sum | (a[i] == ((i & 1) as bool));
    }
    assert(!or_sum);
}
#[test(should_fail_with = "overflow")]
fn test_overflow_detected(a: u8, b: u8) {
    let sum: u8 = a + b;
    assert(sum > a, "overflow");
}

Fuzz test options

Pass these flags to nargo test to control fuzzer behavior:
FlagDescription
--no-fuzzSkip fuzz tests; run only argument-free tests.
--only-fuzzRun only fuzz tests; skip argument-free tests.
--corpus-dir <DIR>Load and save the fuzzer corpus from this directory.
--minimized-corpus-dir <DIR>Minimize the corpus and store results here instead of fuzzing.
--fuzzing-failure-dir <DIR>Save failing inputs to this directory.
--fuzz-timeout <SECONDS>Maximum time per fuzz test. Default: 1.
--fuzz-max-executions <N>Maximum executions per fuzz test. Default: 100000.
--fuzz-show-progressPrint live fuzzing progress.
By default the corpus is stored in a temporary directory. Specify --corpus-dir to persist it across runs, enabling continuous fuzzing or regression testing with previous failures.
nargo test --only-fuzz --fuzz-timeout 30 --corpus-dir ./corpus
For dedicated fuzzing sessions without the test runner, use the nargo fuzz command, which has a standalone fuzzing harness with additional controls like --num-threads and --list-all. See the Nargo CLI reference for details.

Parallel test execution

Tests run in parallel by default, using all available CPU threads. Control the thread count with --test-threads:
nargo test --test-threads 4

Output formatting

FlagDescription
--show-outputPrint println output from tests to the terminal.
-q, --quietShow one character per test instead of one line per test.
--format prettyVerbose output (default).
--format terseCompact one-character-per-test output.
--format jsonJSON Lines output, one object per test result.

Full example

fn is_even(n: u64) -> bool {
    n % 2 == 0
}

fn is_positive(n: u64) -> bool {
    n > 0
}

#[test]
fn test_is_even() {
    assert(is_even(4));
    assert(!is_even(3));
    assert(is_even(0));
}

#[test]
fn test_is_positive() {
    assert(is_positive(1));
    assert(!is_positive(0));
}

#[test(should_fail)]
fn test_even_fails_on_odd() {
    assert(is_even(7));
}

#[test(should_fail_with = "assertion failed")]
fn test_positive_fails_on_zero() {
    assert(is_positive(0), "assertion failed");
}

// Fuzz test: verifies commutativity of addition for all u64 inputs
#[test]
fn test_add_commutative(a: u64, b: u64) {
    assert(a + b == b + a);
}
Run:
nargo test
[my_project] Testing 5 test(s)
[my_project] test test_is_even ... ok
[my_project] test test_is_positive ... ok
[my_project] test test_even_fails_on_odd ... ok
[my_project] test test_positive_fails_on_zero ... ok
[my_project] test test_add_commutative ... ok
[my_project] 5 passed, 0 failed, 0 skipped

Build docs developers (and LLMs) love