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

Quick Start

Write a complete Soroban test in about a minute: build a context, register the contract, invoke it, then assert on events and resource cost in the same test.

Time~5 minutes
Crates usedfixtures · assert · core
PrerequisiteInstallation done

Imports

#![allow(unused)]
fn main() {
use soroban_sdk::{Env, Address};
use soroban_testkit_fixtures::builder::TestContextBuilder;
use soroban_testkit_assert::events::EventMatcher;
use soroban_testkit_core::budget::BudgetSnapshot;
}

Write a test

  1. Build the context

    TestContextBuilder hands you a mocked Env plus ready-made addresses.

  2. Register the contract

    Bind your contract to the context environment and create its client.

  3. Invoke the contract

    Call the function under test, then read the metering that call left behind.

  4. Assert on events and cost

    Match the events the call emitted and check its instruction count against a ceiling.

#![allow(unused)]
fn main() {
#[test]
fn test_token_transfer() {
    // 1. Create a test context with pre-generated users
    let ctx = TestContextBuilder::new()
        .with_users(2)
        .build();

    let sender = &ctx.users[0];
    let receiver = &ctx.users[1];

    // 2. Register your contract
    let contract_id = ctx.env.register(MyContract, ());
    let client = MyContractClient::new(&ctx.env, &contract_id);

    // 3. Invoke the function under test
    client.transfer(sender, receiver, &1000);

    // 4. Read the metering that invocation left behind
    let cost = BudgetSnapshot::last_invocation(&ctx.env);

    // 5. Assert events were emitted, and what they carried
    EventMatcher::new(&ctx.env)
        .from_contract(&contract_id)
        .with_topic("Transfer")
        .assert_emitted();
    EventMatcher::new(&ctx.env)
        .with_topic("Transfer")
        .assert_data_matches(|data| data.deserialize::<i128>() == Some(1_000));

    // 6. Check resource consumption
    assert!(cost.cpu_insns < 500_000);
}
}
Expected output

The test passes with no extra scaffolding — no manual Env construction, no tuple destructuring over env.events().all(), no separate budget harness.

What’s happening

TestContextBuilder

Setup, once

Eliminates manual Env creation, address generation and auth mocking. Opt out of mocked auth when a test needs explicit authorization.

EventMatcher

Readable assertions

Replaces raw tuple iteration over emitted events with a chainable filter by contract and topic.

BudgetSnapshot

Costs made visible

Surfaces the per-call CPU-instruction and memory costs that standard Soroban tests never show.

Composable

Adopt piecemeal

Each crate stands alone. Start with fixtures, add assertions when your tests grow, keep budget checks for CI.

Next steps

Testing patterns

Layouts for unit, integration and contract-interaction tests.

Budget-aware testing

Turn resource regressions into ordinary failing assertions.

Property testing

Generate Soroban-aware inputs with proptest strategies.