Testing Solana Programs
Testing Solana programs no es "ejecuta anchor test y envía". El código en cadena falla en metadatos de cuentas, firmantes, PDAs, CPIs y presupuestos de CU que las pruebas unitarias ordinarias nunca tocan. Necesitas una pila de arneses que intercambian fidelidad por velocidad, y luego gastan tiempo caro del validador donde el comportamiento de RPC y multi-transacción importa.
Esta página es el paraguas de la sección. Las páginas hermanas cubren LiteSVM, Mollusk, Bankrun, pruebas de TypeScript de Anchor, fuzzing, escenarios de CPI/PDA y E2E del validador en profundidad. Fija la pila que usa este sitio: Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, y LiteSVM 0.6.x.
Resumen
- Estructura las pruebas de programas como una pirámide. Pon la mayor parte de la cobertura en ejecutores SVM rápidos en proceso (LiteSVM, Mollusk, Bankrun), usa pruebas de TypeScript de Anchor para IDL y contratos de cliente, reserva
solana-test-validator/ Surfpool para E2E y forks con forma de mainnet, y haz fuzzing en rutas calientes antes de la auditoría. - Por Qué Importa: Las suites solo de validador son lentas y propensas a fallos; las pruebas
#[test]puras en host sin un SVM omiten las reglas de Sealevel. La elección incorrecta de capa o quema minutos de CI o deja errores de firmante, propietario e aritméticos para mainnet-beta. - Conceptos Clave: pirámide de pruebas, SVM en proceso, LiteSVM, Mollusk, Bankrun,
anchor test, validador local, fork de Surfpool, fuzz / Trident, pruebas negativas, unidades de cómputo. - Cuándo Usar: Construyendo o revisando cualquier programa nativo o de Anchor 0.32.1; diseñando CI; endurecimiento pre-auditoría; decidiendo si un error necesita una prueba unitaria de Rust o una ruta RPC completa.
- Limitaciones / Compensaciones: Las VMs en proceso aproximan pero no replican completamente gossip, ALTs, algunos sysvars y la temporización del clúster. Las pruebas de validador son de alta fidelidad y más lentas. El fuzzing necesita invariantes y presupuesto de tiempo de ejecución, no solo "bytes aleatorios".
- Temas Relacionados: LiteSVM, Mollusk, Bankrun (TS), Pruebas TS de Anchor, Fuzzing de Programas, Pruebas Contra un Validador.
Fundamentos
Los programas de Solana son ejecutables sBPF que el SVM ejecuta bajo bloqueos de cuenta y medición de cómputo. Una suite útil ejercita lógica de instrucciones, validación de cuentas, codificación de cliente y flujos de múltiples pasos, cada uno en la capa más barata que aún detecta la clase de error.
La pirámide de pruebas (con forma de Solana)
| Capa | Herramientas (este sitio) | Velocidad | Fidelidad | Trabajo principal |
|---|---|---|---|---|
| Unidad / instrucción | LiteSVM 0.6.x, Mollusk, pruebas matemáticas puras de Rust | Más rápido | SVM sin clúster completo | Manejadores, errores, firmantes, humo de CU |
| Integración de cliente | Bankrun / anchor-bankrun, TS de Anchor enfocado | Rápido | En proceso + IDL/cliente | Constructores de métodos, cuentas, scripts multi-ix |
| Integración / E2E | anchor test, solana-test-validator, Surfpool | Más lento | RPC completo, despliegue, multi-tx | Ruta de despliegue, semántica RPC, forks |
| Propiedad / adversarial | Trident, estilo cargo-fuzz | Ejecuciones largas | Depende del arnés | Análisis, límites matemáticos, flags de cuenta |
Lee la pirámide de abajo hacia arriba. Corrige errores de análisis y firmante en LiteSVM o Mollusk en segundos. Demuestra que el cliente TypeScript todavía construye los metadatos correctos con Bankrun o Anchor. Solo entonces paga por el inicio del validador. Ejecuta campañas de fuzzing en rutas de depósito, retiro, intercambio y cuentas restantes antes de la revisión externa.
Qué debe significar "pasar"
Una suite verde no es solo caminos felices. Para cada instrucción que mueve valor o autoridad, incluye pruebas negativas: firmante faltante, propietario incorrecto, mint incorrecto, oráculo obsoleto, mala PDA bump, reinicialización y CPI no autorizada. Asegura códigos de error tipificados (códigos #[error_code] de Anchor o ProgramError nativos), no solo "lanzó algo". Donde el dinero se mueve, asegura saldos post-estado e invariantes de bóveda, no solo Ok(()).
Las pruebas solo en host (matemáticas de tarifas puras, viajes redondos de Borsh) todavía pertenecen a la base. No reemplazan la carga de un .so en un SVM y el envío de una transacción o instrucción.
Mecánicas e Interacciones
LiteSVM: capa Rust rápida predeterminada
LiteSVM 0.6.x incrusta una VM de Solana en el proceso de prueba. Airdropeas, cargas bytes del programa, configuras el estado de la cuenta, firmas transacciones y aseguras logs o errores sin iniciar solana-test-validator.
Bucle típico:
LiteSVM::new()add_programcon el despliegue.so(oinclude_bytesdespués deanchor build/cargo build-sbf)- Airdropeas pagadores; siembras cuentas con propietarios, datos y lamports
- Construye
Instruction+Transaction, procesa, asegura
Usa LiteSVM para la mayor parte de la cobertura orientada a Rust: enrutamiento de discriminador, fallos de restricciones, semillas de PDA y casos de "el atacante omitió is_signer". Mantén las pruebas deterministas: pares de claves fijos o RNG sembrado, relojes explícitos cuando tu programa lee Clock, y sin dependencia de la latencia RPC del reloj de pared.
Mollusk: arnés Rust a nivel de instrucción
Mollusk se enfoca en la ejecución de instrucción única contra un programa compilado con un almacén de cuentas explícito y verificaciones de resultados opcionales (éxito, fallo, CU). Prefiérelo cuando quieras una superficie más delgada que la API de transacciones de LiteSVM, equipos de programas nativos que viven en #[test], o verificaciones de regresión de CU de instrucciones ajustadas.
LiteSVM es la herramienta bancaria/tx en proceso más amplia; Mollusk es el arnés de procesador de instrucciones delgado. Muchas bases de código usan ambos: Mollusk para tablas de ix puras, LiteSVM para transacciones multi-instrucción y configuración bancaria más rica.
Bankrun: TypeScript sin un validador
Bankrun (y anchor-bankrun) proporciona a las suites de TypeScript un banco en proceso. startAnchor carga los programas del espacio de trabajo; BankrunProvider se conecta al Program de Anchor para que .methods...rpc() no necesite localhost:8899.
Busca Bankrun cuando el equipo posea Mocha/Node + tipos IDL, cuando el inicio del validador anchor test domine CI, o cuando quieras flujos de TypeScript multi-instrucción sin carreras de puertos. Multiplica la cobertura de transacciones construidas por el cliente; mantén una suite de validador más delgada para el despliegue y las rutas sensibles a RPC.
Pruebas de TypeScript de Anchor: IDL y rutas de producto
anchor test (Anchor 0.32.1) es la ruta de producto predeterminada: compila, despliega en un validador local (a menos que se omita), ejecuta tests/*.ts contra el programa del espacio de trabajo y la IDL. Úsalo para historias de usuario de extremo a extremo (init → deposit → withdraw), CPIs de SPL Token / Token-2022 con cuentas asociadas reales, y contratos de cliente impulsados por IDL.
Configura Anchor.toml consistentemente. Prefiere --skip-local-validator en CI solo cuando un solana-test-validator (o Surfpool) administrado ya esté activo con binarios de Agave 4.1.1 fijados. Los fallos a menudo provienen de validadores huérfanos en 8899, ledgers sobrantes o versiones mixtas de CLI.
Los clientes fuera de Anchor pueden usar @solana/kit 7.0.0 para RPC, simulación y metadatos (computeUnitsConsumed, err). Kit es la pila del cliente, no una VM de programa; combínalo con arneses estilo Bankrun o validador según sea necesario.
Pruebas de validador y fork: alta fidelidad
solana-test-validator (Solana CLI 3.0.10 / Agave 4.1.1) ejercita el despliegue real, la confirmación, los sysvars y la secuenciación de múltiples transacciones. Úsalo para transacciones versionadas y ALTs, flujos de producto multi-tx que los bancos en proceso solo aproximan, métodos RPC de los que depende tu aplicación y humo pre-devnet/mainnet.
Surfpool (pin del sitio 0.12.0 donde se usa) añade simulación local de fork de mainnet para que las CPIs de DeFi puedan ver el estado realista del pool. Las pruebas de fork son más pesadas: fija las direcciones del pool, documenta las listas de clonación y no trates el éxito del fork como una prueba de seguridad de tus restricciones.
Fuzzing: entrada adversarial a escala
Fuzzing (Trident para flujos orientados a Anchor, objetivos estilo cargo-fuzz para parsers) muta los datos de instrucción, montos y flags de cuenta mientras aseguras invariantes (la bóveda nunca excede los depósitos, la autoridad siempre es requerida, ninguna ruta de desbordamiento tiene éxito).
Coloca el fuzzing en toda la pirámide: host parse/math cuando sea posible, entrada de instrucción a través de arneses Trident o SVM para combinaciones de flags de cuenta, y ejecuciones largas pre-auditoría (max_total_time), no solo un humo de CI de 30 segundos. Fuzzing sin invariantes es ruido; define primero propiedades de fallo cerrado.
Cómo encajan las capas en un repositorio
programs/*/src/** → pruebas unitarias host + LiteSVM/Mollusk
tests/*.ts → suite Bankrun (rápida) + suite de validador opcional
fuzz/ o trident/ → objetivos de depósito/retiro/intercambio
CI → cargo test (SVM) → bankrun → prueba anchor delgada → fuzz nocturnoCompila una vez (anchor build / cargo build-sbf) y reutiliza el mismo .so en LiteSVM, Mollusk y Bankrun para que nunca asegures contra bytecode obsoleto.
Consideraciones y Aplicaciones Avanzadas
Cuándo usar cada herramienta
| Necesidad | Preferir | Omitir cuándo |
|---|---|---|
| Pruebas negativas rápidas de Rust | LiteSVM 0.6.x | Solo te importa la construcción del cliente TS |
| CU de ix única y verificaciones de resultados | Mollusk | Necesitas scripts de transacciones multi-ix en TS |
| Rápido Anchor/TS sin puertos | Bankrun | Debes validar semántica de despliegue RPC real |
| IDL + ruta de producto completa | anchor test + validador | Cada commit necesita retroalimentación sub-segundo solamente |
| ALT, multi-tx, fork DeFi | Validador / Surfpool | Errores de restricciones a nivel de unidad (corregir más abajo primero) |
| Descubrimiento de bordes pre-auditoría | Trident / fuzz | Sin invariantes o sin presupuesto de tiempo |
Predeterminado para nuevos equipos: LiteSVM o Mollusk para el núcleo de Rust, Bankrun para la mayoría de TS, anchor test delgado sobre un validador para E2E, fuzz en rutas de dinero calientes. Expande la cobertura del validador cuando adoptes ALTs, CPIs multi-programa contra estado de Token real, o listas de verificación de lanzamiento que requieran humo de despliegue.
Diseño de pruebas con forma de seguridad
Mapea clases de amenazas a capas:
- Sustitución de firmante/propietario/mint → LiteSVM o Mollusk (muchos casos, rápido)
- Confusión de semillas de PDA → LiteSVM + una prueba de cliente que derive semillas
- Desbordamiento aritmético y redondeo → pruebas de propiedad host + fuzz
- Errores de privilegios de CPI → LiteSVM/Bankrun multi-programa, luego validador si los cargadores difieren
- Errores de codificación del cliente → Bankrun/Anchor TS contra IDL
No esperes a una auditoría para inventar casos negativos. Cataloga los errores personalizados esperados y escribe un camino fallido para cada uno.
CI, determinismo y brechas de cobertura
- Fija Agave 4.1.1 / CLI 3.0.10, Anchor 0.32.1, Rust 1.91.1, LiteSVM 0.6.x en CI; la deriva del portátil/pipeline es una fuente principal de fallos.
- Restablece ledgers (
solana-test-validator --reset) y mata huérfanos del puerto 8899. - Invalida caché
.soen cambios de fuente de programa y dependencias. - Trabajo de PR requerido: unidades SVM rápidas (+ Bankrun si es pesado en TS). Opcional o programado: E2E completo del validador y fuzz largo.
La cobertura de líneas no es suficiente. Rastrea instrucciones sin un camino negativo, errores nunca asegurados por clientes, techos de CU en ix críticos (verificaciones de Mollusk o metadatos de simulación de Kit), y flujos de producto cubiertos en solo un idioma. Cuando una publicación post-mortem nombra una clase de error (re-init, índice de cuenta incorrecto, aritmética no verificada), agrega una regresión en la capa más baja que pueda expresarla.
Conceptos erróneos comunes
- "
anchor testsolo es una estrategia completa." Es una fuerte capa de integración, no un reemplazo para pruebas unitarias SVM rápidas o fuzzing. - "LiteSVM / Bankrun son juguetes; solo cuenta el validador." Las VMs en proceso capturan la mayoría de los errores de lógica del programa de manera económica; usa el validador para brechas de fidelidad, no para todo.
- "Los caminos felices verdes significan que el programa es seguro." Los metadatos de cuentas y montos adversarios son la prueba real; omítelos y pruebas demos, no seguridad.
- "Fuzzing reemplaza las pruebas unitarias." Fuzzing explora el espacio de estado; las pruebas unitarias codifican requisitos y regresiones conocidos. Necesitas ambos.
- "Host
#[test]sin cargar el programa es suficiente." Las matemáticas puras ayudan; las reglas de Sealevel solo aparecen cuando el SVM ejecuta tu punto de entrada. - "Bankrun y LiteSVM son clones intercambiables." Misma idea (velocidad en proceso), diferentes lenguajes y APIs; elige según quién posea la suite.
- "Las pruebas de fork prueban la seguridad de mainnet." Mejoran el realismo para CPIs contra estado clonado; no prueban restricciones contra todos los grafos de cuentas.
- "CU no pertenece a las pruebas." Las regresiones de CU en rutas calientes fallan la producción como errores de lógica; asegura presupuestos donde importa.
- "Emparejar versiones es opcional." Versiones mixtas de Agave CLI, Anchor y LiteSVM producen fallos de "funciona en mi máquina".
Preguntas Frecuentes
¿Qué es la pirámide de pruebas de programas de Solana?
Una estrategia en capas: muchas pruebas SVM rápidas en proceso (LiteSVM, Mollusk, Bankrun), menos pruebas de cliente/integración (anchor test / IDL), una capa delgada de alta fidelidad de validador o fork, más fuzzing para bordes adversarios.
¿Cuándo debería elegir LiteSVM sobre Mollusk?
Elige LiteSVM para configuración orientada a transacciones, airdrops y flujos multi-instrucción en Rust. Elige Mollusk para un arnés mínimo a nivel de instrucción y verificaciones explícitas de resultados/CU. Muchos equipos usan ambos.
¿Cuándo debería elegir Bankrun sobre `anchor test`?
Usa Bankrun para cobertura rápida de TypeScript sin iniciar solana-test-validator. Mantén una suite anchor test más pequeña respaldada por validador para despliegue, RPC y fidelidad multi-tx.
¿Requiere Anchor 0.32.1 Mocha?
anchor test comúnmente ejecuta pruebas de TypeScript estilo Mocha, pero el contrato importante es el proveedor + IDL + ruta de despliegue del programa. Bankrun puede alojar la misma API Program sin un proceso de validador local.
¿Puedo usar @solana/kit 7.0.0 en pruebas?
Sí, para construcción de cliente, RPC contra un validador, simulación y lectura de metadatos de transacciones. Kit no reemplaza un SVM en proceso por sí solo; combínalo con un validador o proveedores Anchor/Bankrun según corresponda.
¿Cómo pruebo PDAs y CPIs de manera efectiva?
Deriva PDAs de la misma manera que lo hace el programa, asegura bumps y propietarios, y carga múltiples programas en LiteSVM o Bankrun para CPIs. Escala a un validador cuando los programas de Token u otros programas nativos y el comportamiento real de alquiler/sysvar importen.
¿Qué pertenece al fuzzing y qué a las pruebas unitarias?
Las pruebas unitarias bloquean requisitos y regresiones conocidos con casos fijos. Fuzzing busca grandes espacios de entrada (montos, flags, cuentas restantes) bajo invariantes explícitos. Comienza las pruebas unitarias temprano; agrega fuzz antes de la auditoría en rutas de dinero y análisis.
¿Por qué mis pruebas de validador son inestables?
Causas comunes: estado de ledger sobrante, conflictos de puerto 8899, versiones de CLI/Agave no fijadas, sleeps de reloj de pared en lugar de compromisos confirmados, y pares de claves globales compartidos. Restablece el validador, fija Solana CLI 3.0.10 / Agave 4.1.1, y aísla fixtures.
¿Debería cada PR ejecutar la suite completa del validador?
Prefiere trabajos de PR requeridos para LiteSVM/Mollusk (y Bankrun si es pesado en TS). Ejecuta E2E completo del validador en ramas principales, de lanzamiento, o pipelines programados si el costo en tiempo de reloj es alto. Nunca omitas pruebas unitarias de ruta negativa para "ahorrar CI".
¿Cómo aserto correctamente los errores del programa?
Empareja códigos de error personalizados de la IDL del programa o del enum de errores. Evita asegurar solo fragmentos de cadenas de log. Las pruebas negativas deberían fallar por la razón correcta.
¿Dónde encaja Surfpool en relación con LiteSVM?
LiteSVM es para pruebas en proceso centradas en el programa. Surfpool aproxima el estado de mainnet a través de flujos de fork/RPC. Usa Surfpool cuando los grafos de cuentas externas importen; usa LiteSVM para las reglas de tu programa.
¿Necesito fuzzing para un programa pequeño?
Si el programa maneja valor o analiza cuentas restantes complejas, ejecuta al menos una campaña corta pre-auditoría. Para un contador trivial sin riesgo financiero, prioriza pruebas unitarias negativas y haz property-testing de cualquier matemática.
¿Cómo se mantienen consistentes las suites de Rust y TypeScript?
Comparte cadenas de semillas, órdenes de cuentas y catálogos de errores. Compila un .so por commit y cárgalo en ambos ecosistemas. Cuando se encuentra un error en TS, agrega una regresión de LiteSVM para que el fallo sea independiente del idioma.
¿Qué debería leer a continuación en esta sección?
Comienza con LiteSVM y Mollusk para velocidad en Rust, luego Bankrun (TS) y Pruebas TS de Anchor. Agrega Fuzzing de Programas y Pruebas Contra un Validador antes del lanzamiento a producción.
Relacionados
- LiteSVM - pruebas rápidas de programas Rust en proceso sin un validador
- Mollusk - arnés y verificaciones ligeras de Rust a nivel de instrucción
- Bankrun (TS) - pruebas en proceso de TypeScript con proveedores Anchor
- Pruebas TS de Anchor -
anchor test, integración estilo Mocha impulsada por IDL - Fuzzing de Programas - Trident y objetivos de fuzz para casos de borde
- Pruebas Contra un Validador - E2E contra solana-test-validator y forks
Versiones de la pila: Esta página fue escrita para Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, y LiteSVM 0.6.x.