---
title: Program Testing
description: Load and test custom Solana programs with LiteSVM
---

Testing a custom Solana program means loading its compiled `.so` file into the
SVM, setting up the accounts it expects, and sending instructions against it.
LiteSVM handles all of this in-process — no validator needed. We recommend
generating program clients with the
[Codama JS Renderer](https://github.com/codama-idl/renderers-js) so you can have
access to a compatible Kit Plugin.

## Loading a Program

```typescript
import { createClient, address, generateKeyPairSigner } from "@solana/kit";
import { litesvm } from "@solana/kit-plugin-litesvm";
import { signer } from "@solana/kit-plugin-signer";
import { myProgramPlugin } from "@my-program/sdk";
import * as fs from "node:fs";

const mySigner = await generateKeyPairSigner();
const client = createClient()
  .use(signer(mySigner))
  .use(litesvm())
  .use(myProgramPlugin());

// Configure for program testing
client.svm
  .withSigverify(false)
  .withBlockhashCheck(false)
  .withSysvars()
  .withBuiltins();

// Load program from .so file
const programId = address("YourProgramId111111111111111111111111111");
const soPath = "/path/to/target/deploy/my_program.so";

if (fs.existsSync(soPath)) {
  client.svm.addProgramFromFile(programId, soPath);
  console.log("Program loaded:", programId);

  // Verify program account
  const programAccount = client.svm.getAccount(programId);
  if (programAccount.exists) {
    console.log("  Executable:", programAccount.executable);
    console.log("  Data size:", programAccount.data.length, "bytes");
  }
} else {
  console.log("Program file not found:", soPath);
  console.log("Build with: cargo build-sbf");
}
```

## Complete Program Test Setup

```typescript
import { createClient, address, generateKeyPairSigner, lamports } from '@solana/kit';
import { litesvm } from '@solana/kit-plugin-litesvm';
import { signer } from '@solana/kit-plugin-signer';
import { myProgramPlugin } from '@my-program/sdk';
import * as fs from 'node:fs';

const mySigner = await generateKeyPairSigner();
const client = createClient()
    .use(signer(mySigner))
    .use(litesvm())
    .use(myProgramPlugin());

client.svm
    .withSigverify(false)
    .withBlockhashCheck(false)
    .withSysvars()
    .withBuiltins()
    .withPrecompiles()
    .withTransactionHistory(100n);

// Load program
const programId = address('YourProgramId111111111111111111111111111');
const soPath = '/path/to/target/deploy/my_program.so';

if (fs.existsSync(soPath)) {
    client.svm.addProgramFromFile(programId, soPath);
}

// Set up any required data accounts
const dataAccountAddress = address('DataAccount111111111111111111111111111');
const minBalance = client.svm.minimumBalanceForRentExemption(100n);
client.svm.setAccount({
    address: dataAccountAddress,
    data: new Uint8Array(100),
    executable: false,
    lamports: lamports(minBalance),
    programAddress: programId,
    space: 100n,
});

// Send the transaction
await client.myProgram.testInstruction({..}).sendTransaction();

// Verify state changes
const updatedAccount = client.myProgram.myAccount.fetch(dataAccountAddress);
// assert on decoded account
```

## Using Default Programs

For testing that requires standard programs:

```typescript
const mySigner = await generateKeyPairSigner();
const client = createClient().use(signer(mySigner)).use(litesvm());

// Add all default programs (System, BPF Loader, etc.)
client.svm.withDefaultPrograms();

// Or add specific programs you need
// The Token program, Associated Token program, etc. would need
// to be added manually via addProgramFromFile if needed
```

<Callout type="info">
  Build your Solana program with `cargo build-sbf` to generate the `.so` file.
</Callout>

The pattern is always the same:

1. **Program Loading**: Use `addProgramFromFile` to load compiled programs and
   import myProgramPlugin() from your client
2. **Configuration**: Enable sysvars, builtins, and precompiles as needed
3. **Account Setup**: Pre-populate data accounts with `setAccount`
4. **Sending**: Use `client.myProgram.testInstruction({..}).sendTransaction()` —
   no manual transaction building
5. **Verification**: Check account state after execution
   (`client.myProgram.myAccount.fetch`)

Once you have this skeleton working, you can build out a full test suite by
adding more instructions and assertions.
