Testing Best Practices
A condensed summary of the 25 most important Solana program testing practices drawn from every page in this section.
-
Pyramid layering: LiteSVM/Mollusk unit tests first, Bankrun/anchor integration second, validator E2E last (Testing Basics).
-
Always --reset in CI: Deterministic ledger for validator jobs (Testing Against a Validator).
-
Rebuild .so before tests:
anchor buildprecedescargo testand fuzz runs. -
Negative tests per ix: At least one failure case per
#[error_code](Sealevel Catalog). -
Signer omission tests: Authority meta with
is_signer: falsemust fail. -
Mint mismatch tests: Wrong ATA mint for vault constraints.
-
PDA bump tests: Canonical bump succeeds; wrong bump fails (Testing CPIs & PDAs).
-
CPI program ID tests: Impostor program account rejected.
-
Load SPL Token in VM: Add token program to LiteSVM/Mollusk for CPI paths.
-
Checks-effects-interactions tests: Reentrancy callback double-withdraw must fail.
-
Oracle staleness tests: Warp clock past max_age and expect error.
-
Reinit double-call test: Second
init_if_neededmust not reset admin. -
Fuzz before audit: Trident on math handlers 1h+ nightly (Fuzzing).
-
Invariant asserts in fuzz: Not just crash hunting - economic invariants encoded.
-
CU range checks: Mollusk
Check::compute_unitswith ranges not exact pins. -
Bankrun for TS speed: Bulk Anchor logic without validator spin-up (Bankrun).
-
anchor test for SPL flows: Real token mint/ATA creation paths (Anchor TS).
-
Surfpool for DeFi E2E: Mainnet fork over long clone lists.
-
Pin toolchain in CI: Agave 4.1.1 validator matches deploy artifacts.
-
Kill port 8899 orphans: Pre-step in CI before validator jobs.
-
Unique keypairs per test: Prevent state leakage flakiness.
-
Match Anchor.toml cluster: Provider URL equals running validator/devnet.
-
IDL regen on PR: Account rename breaks tests if IDL stale.
-
Archive fuzz corpus: Attach stats to audit package.
-
No devnet merge gates: Localnet/Surfpool for CI; devnet smoke optional.
FAQs
What is the minimum test stack?
LiteSVM negative tests + anchor test on reset localnet for Anchor projects.
How many negative tests?
At least one per constraint and per catalog class touching the instruction.
Should fuzz run on every PR?
Short smoke yes; long runs nightly on main branch.
Related
- Testing Basics - section entry
- LiteSVM - fast unit layer
- Security Best Practices - secure code under test
- Local Dev Best Practices - validator setup
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, and LiteSVM 0.6.x.