Docs
Testing

World state snapshots

Save and restore test runner world state as JSON fixtures with testing.saveSnapshot() and testing.loadSnapshot()

World state snapshots capture the current emulation state during a test and restore it later from a JSON file.

This is useful to:

  • reuse a complex setup across multiple test runs;
  • freeze a real regression scenario as a fixture;
  • checkpoint state mid-test and return to it later;
  • debug stateful flows without repeating the full bootstrap sequence every time.

Quick start

Save the current emulation state:

import "@acton/emulation/network"
import "@acton/emulation/testing"
import "@acton/testing/expect"

get fun `test save snapshot`() {
    val target = randomAddress("snapshot-target");

    testing.topUp(target, ton("3"));
    testing.setNow(1_700_023_001);

    expect(testing.saveSnapshot("fixtures/world-state.json")).toBeTrue();
}

Load it in another test run:

import "@acton/emulation/network"
import "@acton/emulation/testing"
import "@acton/testing/expect"

get fun `test load snapshot`() {
    val target = randomAddress("snapshot-target");

    expect(testing.loadSnapshot("fixtures/world-state.json")).toBeTrue();
    expect(testing.getNow()).toEqual(1_700_023_001);
    expect(testing.getAccountBalance(target)).toEqual(ton("3"));
}

Snapshot contents

The snapshot file stores the local emulation state needed for deterministic replay:

  • current logical time
  • current unix time
  • blockchain config
  • registered libraries
  • materialized account state

Snapshots store state, not cache noise

Read-only cache misses such as checking balance on an unknown address are not persisted into the snapshot file.

Cross-run workflow

The most common pattern is:

  1. Run a setup-style test once and save the snapshot.
  2. Start a fresh acton test run.
  3. Load the snapshot in a second test file.
  4. Assert on the restored state or continue execution from there.

Example:

acton test tests/save_snapshot.test.tolk
acton test tests/load_snapshot.test.tolk

This works well for expensive setup flows, multi-contract fixtures, and regression cases captured from earlier debugging sessions.

Same-run restore

Snapshots can also checkpoint state inside one test:

import "@acton/emulation/network"
import "@acton/emulation/testing"
import "@acton/testing/expect"

get fun `test checkpoint and restore`() {
    val target = randomAddress("checkpoint-target");

    testing.topUp(target, ton("5"));
    expect(testing.saveSnapshot("fixtures/checkpoint.json")).toBeTrue();

    testing.topUp(target, ton("7"));
    expect(testing.getAccountBalance(target)).toEqual(ton("12"));

    expect(testing.loadSnapshot("fixtures/checkpoint.json")).toBeTrue();
    expect(testing.getAccountBalance(target)).toEqual(ton("5"));
}

There, testing.loadSnapshot(...) replaces the current local emulation state instead of merging into it.

Failure handling

Both APIs return bool instead of throwing:

  • testing.saveSnapshot(path) returns false on serialization or file I/O failure
  • testing.loadSnapshot(path) returns false if the file is missing, malformed, has unsupported version, or cannot be applied

Example:

expect(testing.loadSnapshot("fixtures/missing.json")).toBeFalse();
expect(testing.saveSnapshot("missing-dir/world-state.json")).toBeFalse();

If loading fails, the current world state is left unchanged.

Limitations

  • Snapshots restore the local emulation state only.
  • Loading a snapshot switches execution to local state, not fork mode.
  • Snapshot file paths are relative to the project root.
  • Absolute paths and paths that normalize outside the project root are rejected.
  • If storage layout or config assumptions change on purpose, an older snapshot may stop loading.

Last updated on

On this page