Zest is a code coverage CLI tool for Solana programs. Zest is built by LimeChain, a blockchain development and consulting firm founded in 2017. The development of the tool is supported by a grant from the Solana Foundation.
cargo install --git https://github.com/LimeChain/zest zest --force
# Move into the target project
cd ./examples/setter/anchor
# This will run coverage for the example using the `instrument-coverage` strategy without `branch` info
zest coverage
# Path to the target project can also be specified using the `--path` option
zest coverage --path ./examples/setter/anchor
# Configuration options can also be read from a (TOML) config file (`zest-coverage.toml` by default)
cat <<TOML > my_zest_config.toml
path = "./examples/setter/anchor"
branch = true
# contract_style = "anchor"
# tests = ["integration"]
# output_types = ["lcov", "html"]
TOML
# Which would run with
# `coverage_strategy` being `instrument-coverage` (Default)
# `path` being `./examples/setter/anchor/` (from config file)
# `branch` being `false` (CLI override)
zest coverage --config ./my_zest_config.toml --branch false
[!NOTE] Check
zest --help
andzest coverage --help
for more info[!NOTE] More info on the different strategies can be found here
Currently, zest
only supports testing programs, written in Rust, with tests written in Rust (usually using solana-program-test, as opposed to the classic Typescript
tests), which do not depend on the cargo-{build,test}-sbf
toolchain. A.K.A if cargo test
works for you (not cargo test-sbf
), then zest
will too
Here's a small list of publicly available Solana programs that we've tested if they work with zest
or not:
Works on:
How to make sure zest
works for your program:
Make sure your tests are runnable by just cargo test
This is done by supplying your program's processor
(the process_instruction
function) directly when adding it to the test validator
let mut validator = ProgramTest::default();
validator.add_program(
"counter_solana_native",
counter_solana_native::ID,
processor!(counter_solana_native::process_instruction),
);
That requirement is incompatible with shank
framework, since it puts a type constraint on the processor
function.
[!NOTE] That happens because of the
context
function fromShankContext
, seen in their example (the'a
lifetime), which breaks the compatibility (and thus makes it testable only insbf
mode).
[!NOTE] Branch coverage can be enabled with the
--branch
flag but it requires a recent enough version of the nightly compiler to work. It is also only supported when using theinstrument-coverage
coverage strategy (default).
For feedback, feature requests or general inquiries, please reach out to zest@limechain.tech