Skip to main content
gen-test-tools is the crate that powers integration tests against the Grid validators. It provides the test fixture, the validator-mode abstraction, and the deterministic entity generation that contract tests use.

What’s in the crate

  • TestContext: the main context object exposing an RPC client and an entity factory.
  • fixture::test_context: an rstest fixture for easy test setup.
  • TestSeed and EntityFactory: deterministic seeding for reproducible entity generation.
  • ValidatorSubprocess: manages a local validator subprocess.
  • ValidatorContainer: manages a validator in a Docker container via testcontainers.
  • ValidatorMode: enum representing the available validator execution modes.

Quick start

The easiest way to write a test is with the test_context fixture:
use gen_test_tools::fixture::test_context;
use gen_test_tools::TestContext;
use rstest::rstest;

#[rstest]
#[tokio::test]
async fn my_test(#[future] test_context: TestContext) {
    let ctx = test_context.await;

    // Generate a new entity and bootstrap it
    let (entity_id, activation_id) = ctx
        .new_bootstrapped_entity()
        .await
        .expect("bootstrap should succeed");

    // Create a payload-first Gen client for SDK interactions
    let gen_client = ctx.gen_client().expect("Gen client creation should succeed");

    // Use the RPC client directly
    let json_rpc_client = ctx.json_rpc_client();
}
For the end-to-end loop (scaffold a contract, build it, exercise it from a test), see Build and test a contract.

IDE integration

Run and Debug panel entries

A scaffolded workspace includes .vscode/launch.json with:
  • gen-framework: build contract
  • gen-framework: run contract tests
The contract-test launch entry uses plain cargo test, and the cargo wrapper ensures or reuses the validator before tests begin. It remains useful as a manual Run and Debug panel integration even though the inline Rust Analyzer buttons use the same cargo-wrapper path directly. The build launch entry uses scripts/genie-build.sh, which respects GEN_CLI_PATH with a fallback to gen.

IDE test and debug buttons

The bundled workspace settings hook the Rust Analyzer Run Test and Debug buttons into the shared-validator flow:
  • .vscode/bin/cargo delegates to scripts/cargo-with-local-validator.sh.
  • .vscode/settings.json puts that wrapper first in the runnable PATH.
  • In the .devcontainer, the remote PATH also prefers the wrapper.
As a result, IDE-triggered test and debug actions use the same validator-aware Cargo entrypoint instead of bypassing the startup logic. This integration is available when your repository includes the bundled .vscode/ and scripts/ files (for example, via the released devcontainer.tar.gz bundle or by working directly in the framework repository).

Shell workflow

For non-VS Code users, the same shared-validator flow is available via:
./scripts/test-with-local-validator.sh -p my-contract-tests
This wrapper:
  1. Runs ./scripts/ensure-local-validator.sh.
  2. Reuses the validator if it is already reachable.
  3. Exports the environment for external mode.
  4. Executes cargo test with your arguments.
You can also run the bootstrap step directly:
./scripts/ensure-local-validator.sh

Validator modes

Control the validator mode via GEN_VALIDATOR_MODE.
ModeValueDescription
Subprocesssubprocess (default)Runs the validator as a local subprocess
TestContainertest-containerRuns the validator in Docker via testcontainers
ExternalexternalConnects to an already-running validator

Subprocess mode

cargo test
# or explicitly:
GEN_VALIDATOR_MODE=subprocess cargo test
This mode starts a shared validator subprocess using gen service validator local. See Run a local validator (host mode) for the same command run standalone.

TestContainer mode

# install.sh builds gen-cli:latest automatically when Docker is available
GEN_VALIDATOR_MODE=test-container cargo test
This mode provides better isolation by running the validator in Docker. The expected image is gen-cli:latest, which the framework installer (install.sh) builds automatically when Docker is installed and reachable.

External mode

# Uses default RPC URL (http://127.0.0.1:30001)
GEN_VALIDATOR_MODE=external cargo test

# Or specify a custom URL
VALIDATOR_RPC_URL=http://my-validator:30001 GEN_VALIDATOR_MODE=external cargo test
Useful when keeping a validator running between test runs. This is the configured mode inside the bundled .devcontainer and IDE helper flows, where a shared validator process is reused between test executions.
Only works against fresh local or self-hosted validators today. The fixture does not send an Authorization header from ~/.gen/client_config.yml, and it hard-fails on a “wait for genesis migrations” call that can never succeed on an already-running chain. As a result, you cannot point external mode at an authenticated, established DevNet. To exercise a contract on DevNet, use gen client push and gen client deploy instead.

Deterministic entity generation

Use TestSeed and EntityFactory for reproducible entity IDs:
use gen_test_tools::{TestSeed, EntityFactory};

let seed = TestSeed::new(12345);
let factory = EntityFactory::new(seed);

let entity_1 = factory.new_entity();
let entity_2 = factory.new_entity();
// entity_1 and entity_2 are deterministic based on the seed
To reproduce a failed test:
TEST_SEED=1234567890 cargo test

Environment variables

VariableDescriptionDefault
GEN_VALIDATOR_MODEValidator mode: subprocess, test-container, externalsubprocess
VALIDATOR_RPC_URLRPC endpoint URL for external modehttp://127.0.0.1:30001
GEN_CLI_PATHPath to gen CLI binarygen
GEN_VALIDATOR_CONFIGCustom validator config fileCLI default
GEN_CONTAINER_IMAGEDocker image name for test-container modegen-cli
GEN_CONTAINER_TAGDocker image tag for test-container modelatest
TEST_SEEDFixed seed for deterministic entity generationRandom

Troubleshooting

  • Devcontainer + plain cargo test fails immediately.
    • The bundled devcontainer should route cargo test through the validator-aware cargo wrapper.
    • If your shell bypasses the bundled PATH ordering, start the validator first with ./scripts/ensure-local-validator.sh.
  • Docker is installed but test-container mode is not selected.
    • Ensure the Docker daemon is reachable.
    • Ensure gen-cli:latest exists locally. The framework installer (install.sh) builds it automatically when Docker is available.
  • Need deterministic behavior. Set GEN_VALIDATOR_MODE explicitly.

See also