Testando programas Solana
Testar programas Solana não é "rodar anchor test e publicar." Código on-chain falha em account metas, signers, PDAs, CPIs e orçamentos CU que testes unitários comuns nunca tocam. Você precisa de uma stack de harnesses que troca fidelidade por velocidade, depois gasta tempo caro de validador onde RPC e comportamento multi-transação importam.
Esta página é o guarda-chuva da seção. Páginas irmãs cobrem LiteSVM, Mollusk, Bankrun, testes Anchor TypeScript, fuzzing, cenários CPI/PDA e E2E com validador em profundidade. Fixe a stack que este site usa: Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, Rust 1.91.1, @solana/kit 7.0.0 e LiteSVM 0.6.x.
Resumo
- Estruture testes de programa como pirâmide. Coloque a maior cobertura em runners SVM in-process rápidos (LiteSVM, Mollusk, Bankrun), use testes Anchor TypeScript para contratos IDL e cliente, reserve
solana-test-validator/ Surfpool para E2E e forks no formato mainnet, e faça fuzz em hot paths antes da auditoria. - Por que importa: Suites só de validador são lentas e instáveis;
#[test]puro no host sem SVM perde regras Sealevel. Escolha errada de camada ou queima minutos de CI ou deixa bugs de signer, owner e aritmética para mainnet-beta. - Conceitos-chave: pirâmide de testes, SVM in-process, LiteSVM, Mollusk, Bankrun,
anchor test, validador local, fork Surfpool, fuzz / Trident, testes negativos, compute units. - Quando usar: Construir ou revisar qualquer programa Anchor 0.32.1 ou nativo; projetar CI; endurecimento pré-auditoria; decidir se bug precisa teste unitário Rust ou caminho RPC completo.
- Limitações / trade-offs: VMs in-process aproximam mas não replicam totalmente gossip, ALTs, alguns sysvars e timing de cluster. Testes de validador têm alta fidelidade e são mais lentos. Fuzzing precisa invariantes e orçamento de runtime, não apenas "bytes aleatórios."
- Tópicos relacionados: LiteSVM, Mollusk, Bankrun (TS), Testes Anchor TS, Fuzzing de programas, Testando contra validador.
Fundamentos
Programas Solana são executáveis sBPF que a SVM executa sob locks de conta e medição de compute. Suite útil exercita lógica de instrução, validação de conta, encoding de cliente e fluxos multi-etapa, cada um na camada mais barata que ainda captura a classe de bug.
A pirâmide de testes (formato Solana)
| Camada | Ferramentas (este site) | Velocidade | Fidelidade | Trabalho principal |
|---|---|---|---|---|
| Unitário / instrução | LiteSVM 0.6.x, Mollusk, testes math Rust puros | Mais rápido | SVM sem cluster completo | Handlers, erros, signers, smoke CU |
| Integração cliente | Bankrun / anchor-bankrun, Anchor TS focado | Rápido | In-process + IDL/cliente | Builders de método, contas, scripts multi-ix |
| Integração / E2E | anchor test, solana-test-validator, Surfpool | Mais lento | RPC completo, deploy, multi-tx | Caminho deploy, semântica RPC, forks |
| Propriedade / adversarial | Trident, estilo cargo-fuzz | Execuções longas | Depende do harness | Parsing, limites math, flags de conta |
Leia a pirâmide de baixo para cima. Corrija bugs de parse e signer em LiteSVM ou Mollusk em segundos. Prove que cliente TypeScript ainda constrói metas certas com Bankrun ou Anchor. Só então pague spin-up de validador. Rode campanhas fuzz em deposit, withdraw, swap e caminhos remaining_accounts antes de revisão externa.
O que "passar" deve significar
Suite verde não é só happy paths. Para toda instrução que move valor ou authority, inclua testes negativos: signer ausente, owner errado, mint errado, oracle obsoleto, bump PDA ruim, re-init e CPI não autorizado. Asserte códigos de erro tipados (Anchor #[error_code] ou códigos nativos ProgramError), não só "lançou algo." Onde dinheiro se move, asserte saldos pós-estado e invariantes de vault, não só Ok(()).
Testes só no host (math de taxa pura, round-trips Borsh) ainda pertencem à base. Não substituem carregar .so em SVM e submeter transação ou instrução.
Mecânica e interações
LiteSVM: camada Rust rápida padrão
LiteSVM 0.6.x embute VM Solana no processo de teste. Você faz airdrop, carrega bytes de programa, define estado de conta, assina transações e asserta logs ou erros sem iniciar solana-test-validator.
Loop típico:
LiteSVM::new()add_programcom.sode deploy (ou include_bytes apósanchor build/cargo build-sbf)- Airdrop payers; semeia contas com owners, dados e lamports
- Construa
Instruction+Transaction, processe, asserte
Use LiteSVM para a maior parte da cobertura voltada a Rust: roteamento de discriminator, falhas de restrição, seeds PDA e casos "atacante omitiu is_signer". Mantenha testes determinísticos: keypairs fixos ou RNG com seed, clocks explícitos quando programa lê Clock, sem dependência de latência RPC de relógio de parede.
Mollusk: harness Rust em nível de instrução
Mollusk foca execução de instrução única contra programa compilado com account store explícito e checks opcionais (sucesso, falha, CU). Prefira quando quer superfície mais fina que API de transação do LiteSVM, equipes de programa nativo em #[test] ou checks apertados de regressão CU de instrução.
LiteSVM é a ferramenta in-process mais ampla de bank/tx; Mollusk é o harness enxuto de processador de instrução. Muitos codebases usam ambos: Mollusk para tabelas ix puras, LiteSVM para transações multi-instrução e setup de bank mais rico.
Bankrun: TypeScript sem validador
Bankrun (e anchor-bankrun) dá bank in-process a suites TypeScript. startAnchor carrega programas do workspace; BankrunProvider conecta ao Program Anchor para .methods...rpc() não precisar de localhost:8899.
Use Bankrun quando equipe possui Mocha/Node + tipos IDL, quando spin-up de validador de anchor test domina CI ou quando quer fluxos TypeScript multi-instrução sem corridas de porta. Multiplica cobertura de transações construídas pelo cliente; mantenha suite de validador mais fina para deploy e caminhos sensíveis a RPC.
Testes Anchor TypeScript: IDL e caminhos de produto
anchor test (Anchor 0.32.1) é o caminho de produto padrão: build, deploy em validador local (a menos que pulado), executa tests/*.ts contra programa e IDL do workspace. Use para histórias end-to-end (init → deposit → withdraw), CPIs SPL Token / Token-2022 com contas associadas reais e contratos de cliente orientados por IDL.
Configure Anchor.toml consistentemente. Prefira --skip-local-validator no CI apenas quando solana-test-validator gerenciado (ou Surfpool) já estiver ativo com binários Agave 4.1.1 fixados. Flakes frequentemente vêm de validadores órfãos na 8899, ledgers remanescentes ou versões CLI misturadas.
Clientes fora do Anchor podem usar @solana/kit 7.0.0 para RPC, simulação e meta (computeUnitsConsumed, err). Kit é a stack de cliente, não VM de programa; combine com harnesses estilo Bankrun ou validador conforme necessário.
Testes de validador e fork: alta fidelidade
solana-test-validator (Solana CLI 3.0.10 / Agave 4.1.1) exercita deploy real, confirmação, sysvars e sequenciamento multi-transação. Use para transações versionadas e ALTs, fluxos de produto multi-tx que banks in-process só aproximam, métodos RPC dos quais app depende e smoke pré-devnet/mainnet.
Surfpool (pin do site 0.12.0 onde usado) adiciona simulação local com fork mainnet para CPIs DeFi verem estado realista de pool. Testes fork são mais pesados: fixe endereços de pool, documente listas de clone e não trate sucesso em fork como prova de segurança de suas restrições.
Fuzzing: input adversarial em escala
Fuzzing (Trident para fluxos orientados a Anchor, alvos estilo cargo-fuzz para parsers) muta dados de instrução, amounts e flags de conta enquanto você asserta invariantes (vault nunca excede depósitos, authority sempre exigida, nenhum caminho de overflow sucede).
Coloque fuzzing na pirâmide: parse/math no host quando possível, entrada de instrução via Trident ou harnesses SVM para combinações de flags de conta e execuções longas pré-auditoria (max_total_time), não só smoke CI de 30 segundos. Fuzzing sem invariantes é ruído; defina propriedades fail-closed primeiro.
Como camadas se encaixam em um repo
programs/*/src/** → testes unitários host + LiteSVM/Mollusk
tests/*.ts → suite Bankrun (rápida) + suite validador opcional
fuzz/ ou trident/ → alvos deposit/withdraw/swap
CI → cargo test (SVM) → bankrun → anchor test fino → fuzz nightlyBuild uma vez (anchor build / cargo build-sbf) e reutilize o mesmo .so em LiteSVM, Mollusk e Bankrun para nunca assertar contra bytecode obsoleto.
Considerações avançadas e aplicações
Quando usar cada ferramenta
| Necessidade | Prefira | Pule quando |
|---|---|---|
| Testes negativos Rust rápidos | LiteSVM 0.6.x | Só se importa com builders cliente TS |
| Checks de ix única e CU | Mollusk | Precisa scripts multi-ix de transação em TS |
| Anchor/TS rápido sem portas | Bankrun | Precisa validar semântica real de deploy RPC |
| IDL + caminho de produto completo | anchor test + validador | Todo commit precisa só feedback sub-segundo |
| ALT, multi-tx, DeFi fork | Validador / Surfpool | Bugs de restrição em nível unitário (corrija embaixo primeiro) |
| Descoberta de borda pré-auditoria | Trident / fuzz | Sem invariantes ou sem orçamento de tempo |
Padrão para novas equipes: LiteSVM ou Mollusk para core Rust, Bankrun para a maior parte do TS, anchor test fino em validador para E2E, fuzz em caminhos de dinheiro quente. Expanda cobertura de validador ao adotar ALTs, CPIs multi-programa contra estado Token real ou checklists de release que exigem smoke de deploy.
Design de teste orientado a segurança
Mapeie classes de ameaça para camadas:
- Substituição signer/owner/mint → LiteSVM ou Mollusk (muitos casos, rápido)
- Confusão de seed PDA → LiteSVM + um teste cliente que deriva seeds
- Overflow aritmético e arredondamento → testes de propriedade host + fuzz
- Erros de privilégio CPI → LiteSVM/Bankrun multi-programa, depois validador se loaders diferem
- Erros de encoding cliente → Bankrun/Anchor TS contra IDL
Não espere auditoria para inventar casos negativos. Catalogue erros customizados esperados e escreva um caminho de falha cada.
CI, determinismo e lacunas de cobertura
- Fixe Agave 4.1.1 / CLI 3.0.10, Anchor 0.32.1, Rust 1.91.1, LiteSVM 0.6.x no CI; deriva laptop/pipeline é fonte top de flake.
- Reset ledgers (
solana-test-validator --reset) e mate órfãos porta 8899. - Invalide
.soem cache em mudanças de fonte de programa e dependências. - Job PR obrigatório: units SVM rápidas (+ Bankrun se TS-heavy). Opcional ou agendado: E2E validador completo e fuzz longo.
Cobertura de linha não basta. Rastreie instruções sem caminho negativo, erros nunca assertados por clientes, tetos CU em ix críticas (checks Mollusk ou meta simulação Kit) e fluxos de produto cobertos em apenas uma linguagem. Quando postmortem público nomeia classe de bug (re-init, índice de conta errado, aritmética não verificada), adicione regressão na camada mais baixa que possa expressá-la.
Equívocos comuns
- "
anchor testsozinho é estratégia completa." É camada de integração forte, não substituto para testes unitários SVM rápidos ou fuzzing. - "LiteSVM / Bankrun são brinquedos; só validador conta." VMs in-process capturam a maioria dos bugs de lógica de programa barato; use validador para lacunas de fidelidade, não para tudo.
- "Happy paths verdes significam programa seguro." Account metas e amounts adversariais são o teste real; omita-os e você testa demos, não segurança.
- "Fuzzing substitui testes unitários." Fuzzing explora espaço de estado; testes unitários codificam requisitos conhecidos e regressões. Você precisa de ambos.
- "Host
#[test]sem carregar programa basta." Math pura ajuda; regras Sealevel só aparecem quando SVM executa seu entrypoint. - "Bankrun e LiteSVM são clones intercambiáveis." Mesma ideia (velocidade in-process), linguagens e APIs diferentes; escolha por quem possui a suite.
- "Testes fork provam segurança mainnet." Melhoram realismo para CPIs contra estado clonado; não provam restrições contra todos os grafos de conta.
- "CU não pertence a testes." Regressões CU em hot paths falham em produção como bugs de lógica; asserte orçamentos onde importa.
- "Combinar versões é opcional." Majors mistos de Agave CLI, Anchor e LiteSVM produzem falhas "funciona na minha máquina."
FAQs
O que é a pirâmide de testes de programas Solana?
Estratégia em camadas: muitos testes SVM in-process rápidos (LiteSVM, Mollusk, Bankrun), menos testes cliente/integração (anchor test / IDL), camada fina de validador ou fork de alta fidelidade, mais fuzzing para bordas adversariais.
Quando escolher LiteSVM em vez de Mollusk?
Escolha LiteSVM para setup orientado a transação, airdrops e fluxos multi-instrução em Rust. Escolha Mollusk para harness mínimo de instrução única e checks explícitos de resultado/CU. Muitas equipes usam ambos.
Quando escolher Bankrun em vez de `anchor test`?
Use Bankrun para cobertura TypeScript rápida sem subir solana-test-validator. Mantenha suite menor de anchor test com validador para fidelidade de deploy, RPC e multi-tx.
Anchor 0.32.1 exige Mocha?
anchor test comumente executa testes TypeScript estilo Mocha, mas contrato importante é provider + IDL + caminho de deploy de programa. Bankrun pode hospedar a mesma API Program sem processo de validador local.
Posso usar @solana/kit 7.0.0 em testes?
Sim para construção de cliente, RPC contra validador, simulação e leitura de meta de transação. Kit não substitui SVM in-process sozinho; combine com validador ou providers Anchor/Bankrun conforme apropriado.
Como testar PDAs e CPIs efetivamente?
Derive PDAs da mesma forma que o programa, asserte bumps e owners e carregue múltiplos programas em LiteSVM ou Bankrun para CPI. Escale para validador quando Token ou outros programas nativos e comportamento real de rent/sysvar importam.
O que vai em fuzzing vs testes unitários?
Testes unitários travam requisitos conhecidos e regressões com casos fixos. Fuzzing busca grandes espaços de input (amounts, flags, remaining accounts) sob invariantes explícitas. Comece testes unitários cedo; adicione fuzz antes da auditoria em caminhos de dinheiro e parse.
Por que testes de validador são instáveis?
Causas comuns: estado de ledger remanescente, conflitos porta 8899, versões CLI/Agave não fixadas, sleeps de relógio de parede em vez de commitments confirmados e keypairs globais compartilhados. Reset validador, fixe Solana CLI 3.0.10 / Agave 4.1.1 e isole fixtures.
Todo PR deve rodar suite completa de validador?
Prefira jobs PR obrigatórios para LiteSVM/Mollusk (e Bankrun se TS-heavy). Execute E2E validador completo em main, branches de release ou pipelines agendados se custo de wall-clock for alto. Nunca drop testes de caminho negativo para "economizar CI."
Como assertar erros de programa corretamente?
Combine códigos de erro customizados da IDL ou enum de erro do programa. Evite assertar apenas fragmentos de string de log. Testes negativos devem falhar pelo motivo certo.
Onde Surfpool se encaixa em relação ao LiteSVM?
LiteSVM é para testes in-process centrados no programa. Surfpool aproxima estado mainnet via fluxos fork/RPC. Use Surfpool quando grafos de conta externos importam; use LiteSVM para regras do seu programa.
Preciso de fuzzing para programa pequeno?
Se programa detém valor ou analisa remaining accounts complexos, rode pelo menos campanha curta pré-auditoria. Para contador trivial sem risco financeiro, priorize testes negativos unitários e property-test qualquer math.
Como suites Rust e TypeScript permanecem consistentes?
Compartilhe strings de seed, ordens de conta e catálogos de erro. Build um .so por commit e carregue em ambos ecossistemas. Quando bug é encontrado em TS, adicione regressão LiteSVM para falha ser independente de linguagem.
O que ler a seguir nesta seção?
Comece com LiteSVM e Mollusk para velocidade Rust, depois Bankrun (TS) e Testes Anchor TS. Adicione Fuzzing de programas e Testando contra validador antes do lançamento em produção.
Relacionados
- LiteSVM - testes de programa Rust in-process rápidos sem validador
- Mollusk - harness Rust leve em nível de instrução e checks
- Bankrun (TS) - testes TypeScript in-process com providers Anchor
- Testes Anchor TS -
anchor test, integração estilo Mocha orientada por IDL - Fuzzing de programas - Trident e alvos fuzz para casos extremos
- Testando contra validador - E2E contra solana-test-validator e forks
Versões da stack: Esta página foi escrita para Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, Rust 1.91.1, @solana/kit 7.0.0 e LiteSVM 0.6.x.