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.
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
-
Build the context
TestContextBuilderhands you a mockedEnvplus ready-made addresses. -
Register the contract
Bind your contract to the context environment and create its client.
-
Invoke the contract
Call the function under test, then read the metering that call left behind.
-
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);
}
}
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
Setup, once
Eliminates manual Env creation, address generation and auth mocking. Opt out of mocked auth when a test needs explicit authorization.
Readable assertions
Replaces raw tuple iteration over emitted events with a chainable filter by contract and topic.
Costs made visible
Surfaces the per-call CPU-instruction and memory costs that standard Soroban tests never show.
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.