solana-program-testing

Jan 6, 2025

Solana

Engineering

Passing Test

After multiple years of testing in Typescript using Anchor clients, I’m back to testing the same way I did in 2020 with solana-program-test. Testing in Typescript with an Anchor client provides many benefits like self documenting client implementations with full end to end testing across the stack. However, at Exo we have grown beyond thinking about testing in the context of a single project and need testing infrastructure that we can re-use across projects.

With solana-program-test we can guarantee that the same tests will work across a program written in Anchor, Steel, native, or some future Solana program framework. As we work with a diverse group of organizations with different requirements and preferences, this is a key decision factor in testing frameworks.

The exposedProgramTestContext is incredibly flexible giving developers full access over the Solana bank state and runtime.

Setting Clock

Testing various conditions based on slot or timestamp become trivial with the ability to mock the Clock sysvar.

/// Set the sysvar Clock's time to the given timestamp.
pub async fn set_clock_time(ctx: &mut ProgramTestContext, time_in_seconds: i64) {
  let clock: Clock = ctx.banks_client.get_sysvar().await.unwrap();

  let mut updated_clock = clock.clone();
  updated_clock.unix_timestamp = time_in_seconds;

  ctx.set_sysvar(&updated_clock);
}

Arbitrary State

Set system account state to anything for quick testing of states that would be tedious to set up using transactions under normal runtime conditions. It’s worth noting that it is possible to set states that would not be possible within the runtime.

let mut account = AccountSharedData::new(lamports, space, &owner);
account.set_data_from_slice(&data);
ctx.set_account(&some_address, &account);

We continue to develop internal testing best practices to improve our efficiency when it comes to code coverage.