Pruebas Diferenciales
Las pruebas diferenciales son la prueba de dos cosas para descubrir diferencias en su comportamiento.
El objetivo es probar que las dos cosas se comportan de manera consistente y que no divergen en su comportamiento salvo por algunas diferencias esperadas. Las afirmaciones deben ser tan amplias como sea posible, probando ampliamente que todos los resultados observables no cambian, excepto por cualquier cambio esperado.
Esta estrategia es efectiva al desarrollar algo nuevo que debería comportarse como algo que ya existe. Eso podría ser una nueva versión de un contrato que tiene el mismo comportamiento que su versión anterior. O podría ser el mismo contrato con un SDK o dependencia actualizada. O podría ser una reorganización que espera no tener cambios funcionales.
Esta estrategia se puede utilizar en el contexto de pruebas unitarias e integradas, o en el contexto de pruebas de fuzz también.
Todos los contratos desarrollados con el SDK de Rust Soroban tienen una forma de pruebas diferenciales incorporadas y habilitadas por defecto. Consulta Pruebas Diferenciales con Imágenes de Prueba.
Cómo Escribir Pruebas Diferenciales
Para experimentar escribiendo una prueba diferencial, abre un contrato que hayas desplegado, o revisa un ejemplo del repositorio [soroban-examples] y desplégalo.
Asumiendo que el contrato ha sido desplegado y se están realizando cambios en la copia local. Necesitamos verificar que el comportamiento inalterado en el contrato no ha cambiado en comparación con lo que está desplegado.
-
Utiliza el comando [stellar contract fetch] para obtener el contrato que ya está desplegado. El contrato ya desplegado se utilizará como base que se espera que la copia local iguale.
stellar contract fetch --id C... --out-file contract.wasm
-
Importa el contrato en las pruebas con el macro
contractimport!
.mod deployed {
soroban_sdk::contractimport!(file = "contract.wasm");
} -
Escribe una prueba que ejecute la misma lógica para el contrato desplegado y el contrato local, comparando el resultado. Asumiendo que el ejemplo de incremento está en uso, la prueba se vería algo así como lo siguiente.
#![cfg(test)]
use crate::{IncrementContract, IncrementContractClient};
use soroban_sdk::{testutils::Events as _, Env};
mod deployed {
soroban_sdk::contractimport!(file = "contract.wasm");
}
#[test]
fn differential_test() {
let env = Env::default();
assert_eq!(
// Baseline – the deployed contract
{
let contract_id = env.register(deployed::WASM, ());
let client = IncrementContractClient::new(&env, &contract_id);
(
// Return Values
(
client.increment(),
client.increment(),
client.increment(),
),
// Events
env.events.all(),
)
},
// Local – the changed or refactored contract
{
let contract_id = env.register(IncrementContract, ());
let client = IncrementContractClient::new(&env, &contract_id);
(
// Return Values
(
client.increment(),
client.increment(),
client.increment(),
),
// Events
env.events.all(),
)
},
);
} -
Ejecuta la prueba para comparar la línea base y los resultados observables locales.
Esta prueba utiliza los mismos patrones utilizados en pruebas unitarias y pruebas de integración:
- Crear un entorno, el
Env
. - Importa el contrato Wasm para comparar.
- Registra el contrato local para ser probado.
- Invoca funciones utilizando un cliente.
- Afirmar igualdad.
Las pruebas diferenciales funcionan mejor cuando se hacen menos suposiciones. En lugar de afirmar solo sobre valores de retorno específicos o sobre detalles de implementación como un estado específico, afirmar sobre todos los resultados observables e incluir cosas como eventos publicados o valores de retorno de otras funciones de contrato de solo lectura ayudará a descubrir cambios inesperados.
Dependiendo de la complejidad de la prueba, puede ser deseable usar un Env
independiente para probar el desplegado frente al local. Sin embargo, en este momento solo es posible comparar valores de host, como String
, Bytes
, Vec
, Map
, si han sido creados usando el mismo Env
. El problema de seguimiento para soportar comparaciones entre entornos es stellar/rs-soroban-sdk#1360.
Guías en esta categoría:
📄️ Pruebas Unitarias
Las pruebas unitarias son pruebas pequeñas que prueban contratos inteligentes.
📄️ Simulación
Simular contratos de dependencia en pruebas.
📄️ Pruebas de Integración
Las pruebas de integración utilizan contratos de dependencia en lugar de simulaciones.
📄️ Fuzzing
Fuzzing y pruebas de propiedades para encontrar comportamientos inesperados.
📄️ Pruebas Diferenciales
Las pruebas diferenciales detectan cambios no intencionados.
📄️ Pruebas Diferenciales con Imágenes de Prueba
Prueba diferencial utilizando imágenes de prueba automáticas.
📄️ Pruebas de Mutación
La prueba de mutación encuentra código no probado.
📄️ Prueba de Autorización
Escribe pruebas que verifiquen la autorización del contrato.
📄️ Eventos de Prueba
Escribe pruebas que verifiquen los eventos de contrato.