Integration Tests with Mainnet Data
Testing with mainnet data is another form of integration test, where not only mainnet contracts can be used, but also their data on mainnet.
Our ability to test a contract that relies on another contract is limited to our own knowledge of this other contract and the different states it can get into. Integration testing, where real dependencies are used removes some assumptions, but if a dependency has complex state it may also be useful to test against mainnet data as it exists at different points in time.
Testing with mainnet data is one way to further close the gap.
The Soroban Rust SDK and Stellar CLI come together to make possible testing with mainnet data.
How to Write Tests with Mainnet Dataβ
The following is an example of a test that includes a dependency contract into the test, rather than mock it. The test is written to test the increment-with-pause contract and the pause contract. The contract has an increment
function that increases a counter value by one on every invocation. The contract depends on the pause contract to control whether the increment functionality is paused.
The following tests set up the increment-with-pause
contract, using a ledger snapshot that has the dependency pause
contract already deployed along with it's contract data.
-
Use [stellar snapshot create] command to create a snapshot of the pause contract and its data.
stellar snapshot create --address C... --output json --out snapshot.json
infoThe
--ledger <ledger-seq>
option can be added to specify a ledger to snapshot. When not specified the latest ledger that's been pushed to archives is snapshot, that is usually less than 5 minutes old. -
Use
Env::from_ledger_snapshot_file(...)
to load the snapshot into anEnv
in the test.let env = Env::from_ledger_snapshot_file("snapshot.json");
-
Write a test similar to the following that uses the
Env
preloaded with the contracts and contract data insnapshot.json
. The test makes assertions about the behavior of the main contract in the context of the real dependencies and data that the dependencies have on the network.#[test]
fn test() {
let env = Env::from_ledger_snapshot_file("snapshot.json");
let contract_id = env.register(
IncrementContract,
IncrementContractArgs::__constructor(&pause_id),
);
let client = IncrementContractClient::new(&env, &contract_id);
assert_eq!(client.increment(), 1);
}
Most tests, whether they're unit, mocks, or integration tests, will look very similar to the test above. The tests will do four things:
- Create an environment, the
Env
, either withEnv::default()
orEnv::from_ledger_snapshot_file(...)
. - Register the contract(s) to be tested.
- Invoke functions using the generated client.
- Assert the outcome.
Snapshots created from testnet or mainnet can also be a way to test and debug incidents with a contract on network. A snapshot can be created at a specific ledger and tests written using that snapshot to better understand why or how a series of events occurred.
A snapshot can be created of any contract deployed to mainnet or testnet using the stellar snapshot create
command. It can be a fun way to experiment with and learn about deployed contracts by loading a snapshot into a test and invoking the contract. Fuzzing can even be performed on contracts using this tooling.
Guides in this category:
ποΈ Unit Tests
Unit tests are small tests that test smart contracts.
ποΈ Mocking
Mocking dependency contracts in tests.
ποΈ Test Authorization
Write tests that test contract authorization.
ποΈ Test Events
Write tests that test contract events.
ποΈ Integration Tests
Integration testing uses dependency contracts instead of mocks.
ποΈ Integration Tests with Mainnet Data
Integration testing uses dependency contracts instead of mocks.
ποΈ Fuzzing
Fuzzing and property testing to find unexpected behavior.
ποΈ Differential Tests
Differential testing detects unintended changes.
ποΈ Differential Tests with Test Snapshots
Differential testing using automatic test snapshots.
ποΈ Code Coverage
Code coverage tools find code not tested.
ποΈ Mutation Testing
Mutation testing finds code not tested.