Testing Best Practices
A condensed summary of the 25 most important Solana program testing practices drawn from every page in this section.
Search across all documentation pages
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 build precedes cargo test and fuzz runs.
Negative tests per ix: At least one failure case per #[error_code] (Sealevel Catalog).
Signer omission tests: Authority meta with is_signer: false must 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_needed must 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_units with 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.
LiteSVM negative tests + anchor test on reset localnet for Anchor projects.
At least one per constraint and per catalog class touching the instruction.
Short smoke yes; long runs nightly on main branch.
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.
Reviewed by Chris St. John·Last updated Jul 16, 2026