#solana #blockchain #ian-macalinao

testsvm

A comprehensive testing framework for Solana SVM (Solana Virtual Machine) programs

3 unstable releases

Uses new Rust 2024

0.2.1 Oct 15, 2025
0.2.0 Sep 1, 2025
0.1.1 Aug 28, 2025

#327 in Simulation


Used in testsvm-quarry

Apache-2.0

250KB
1.5K SLoC

testsvm

Crates.io Documentation

A wrapper around LiteSVM that provides a more user-friendly interface for testing.

License

Copyright (c) 2025 Ian Macalinao. Licensed under the Apache License, Version 2.0.


lib.rs:

TestSVM

A comprehensive testing framework for Solana SVM (Solana Virtual Machine) programs.

This crate provides a developer-friendly wrapper around LiteSVM, offering enhanced debugging, transaction management, and testing utilities for Solana program development.

Features

  • Enhanced LiteSVM Interface: Simplified API for common testing operations
  • Transaction Result Management: Detailed error reporting and transaction analysis
  • Address Book Integration: Built-in address tracking and labeling
  • Account References: Type-safe account management with automatic tracking
  • Colored Output: Enhanced debugging with color-coded transaction logs
  • Helper Functions: Utilities for airdrop, account creation, and more

Quick Start

use testsvm::prelude::*;

// Create a new test environment
let mut env = TestSVM::init()?;

// Add a program to test
let program_id = Pubkey::new_unique();
env.add_program_from_path(
    "my_program",
    program_id,
    "path/to/program.so"
)?;

// Create and fund test accounts  
let user = env.new_wallet("alice")?;

// Build and execute transactions
let instructions = vec![
    // Your instructions here
];
let transaction = Transaction::new_signed_with_payer(
    &instructions,
    Some(&env.default_fee_payer()),
    &[&env.default_fee_payer],
    env.svm.latest_blockhash(),
);
let result = env.execute_transaction(transaction)?;

Working with Programs

use testsvm::prelude::*;
use solana_sdk::pubkey::Pubkey;

let mut env = TestSVM::init()?;

// Load program from file
let program_id = Pubkey::new_unique();
env.add_program_from_path(
    "token_program",
    program_id,
    "./fixtures/programs/token.so"
)?;

// Add program fixture from fixtures directory
let fixture_program_id = Pubkey::new_unique();
env.add_program_fixture("my_program", fixture_program_id)?;

Account Management

use testsvm::prelude::*;

let mut env = TestSVM::init()?;

// Create wallets with automatic tracking
let alice = env.new_wallet("alice")?;
let bob = env.new_wallet("bob")?;

// Create token mint
let mint = env.create_mint("usdc_mint", 6, &alice.pubkey())?;

// Create Associated Token Accounts
let (alice_ata_ix, alice_ata) = env.create_ata_ix("alice_usdc", &alice.pubkey(), &mint.key)?;
let (bob_ata_ix, bob_ata) = env.create_ata_ix("bob_usdc", &bob.pubkey(), &mint.key)?;

// Execute the instructions to create the ATAs
env.execute_ixs(&[alice_ata_ix, bob_ata_ix])?;

Transaction Building and Execution

use testsvm::prelude::*;

let mut env = TestSVM::init()?;
let payer = env.new_wallet("payer")?;

// Build transaction
let instructions = vec![
    // Your instructions here
];

let tx = Transaction::new_signed_with_payer(
    &instructions,
    Some(&payer.pubkey()),
    &[&payer],
    env.svm.latest_blockhash(),
);

// Execute and verify
let result = env.execute_transaction(tx)?;

// Access detailed results
println!("Compute units used: {}", result.compute_units_consumed);
println!("Logs: {:?}", result.logs);

Debugging and Analysis

use testsvm::prelude::*;

let mut env = TestSVM::init()?;

// Execute transaction (example transaction)
let instructions = vec![];
let tx = Transaction::new_signed_with_payer(
    &instructions,
    Some(&env.default_fee_payer()),
    &[&env.default_fee_payer],
    env.svm.latest_blockhash(),
);
let result = env.execute_transaction(tx)?;

// Print formatted output
println!("Transaction logs: {:?}", result.logs);

// Access address book for debugging
env.address_book.print_all();

// Get account balance
let account = env.default_fee_payer();
let account_info = env.svm.get_account(&account);
if let Some(info) = account_info {
    println!("Account balance: {} lamports", info.lamports);
}

Integration with Anchor

use testsvm::prelude::*;

// Example program module (would be generated by Anchor)
// declare_program!(my_program) would generate something similar to:

let mut env = TestSVM::init()?;
let payer = env.new_wallet("payer")?;

// Create instruction using Anchor's generated types
let ix = anchor_instruction(
    my_program::ID,
    my_program::accounts::Initialize {},
    my_program::instruction::Initialize {},
);

// Execute in test environment
let result = env.execute_ixs_with_signers(&[ix], &[&payer])?;

Dependencies

~36–53MB
~775K SLoC