¿Qué hace pruebas-basadas-en-propiedades?
Proporciona orientación para pruebas basadas en propiedades en múltiples lenguajes y contratos inteligentes. Úsalo al escribir pruebas, revisar código con patrones de serialización/validación/parseo, diseñar funciones, o cuando las pruebas basadas en propiedades brinden una cobertura más sólida que las pruebas basadas en ejemplos.
¿Qué son las pruebas basadas en propiedades?
Las pruebas basadas en propiedades (property-based testing) son una técnica de testing automatizado donde en lugar de escribir casos de prueba específicos (ejemplo: sum(2, 3) == 5), se definen propiedades generales invariantes que deben cumplirse (ejemplo: sum(a, b) == sum(b, a) para cualquier a y b). Un framework de pruebas basado en propiedades genera automáticamente entradas variadas (incluyendo casos límite) para probar estas propiedades.
¿Por qué usarlas?
- Mayor cobertura: Descubre casos límite inesperados que las pruebas basadas en ejemplos suelen pasar por alto.
- Menos sesgo humano: El generador automático explora escenarios que no se te habrían ocurrido manualmente.
- Eficiencia: Con una sola propiedad puedes probar miles de combinaciones de entrada.
- Documentación viva: Las propiedades son especificaciones ejecutables del comportamiento esperado.
Lenguajes compatibles
| Lenguaje/Plataforma | Framework recomendado |
|---|---|
| Python (PyTest) | Hypothesis |
| JavaScript/TypeScript | fast-check |
| Rust | proptest |
| Solidity (contratos inteligentes) | Echidna, Foundry fuzzing |
| Java | jqwik |
| Go | rapid |
| Haskell | QuickCheck |
Ejemplos prácticos
Ejemplo básico en Python con Hypothesis
from hypothesis import given
from hypothesis import strategies as st
def test_conmutatividad_suma():
@given(a=st.integers(), b=st.integers())
def test(a, b):
assert a + b == b + a
Ejemplo en Solidity con Echidna
contract TestToken {
Token token;
function echidna_test_total_supply_invariant() public view returns (bool) {
// Propiedad: La oferta total nunca debe exceder MAX_SUPPLY
return token.totalSupply() <= token.MAX_SUPPLY();
}
}
Estrategias comunes
- Invariantes: Propiedades que deben cumplirse siempre (ej:
x + 0 == x). - Idempotencia: Aplicar la operación dos veces produce el mismo resultado (ej:
sort(sort(lista)) == sort(lista)). - Inversión: La operación inversa deshace la original (ej:
deserializar(serializar(objeto)) == objeto). - Metamorfismo: Relaciones entre entradas y salidas (ej:
concat(a, b).length == a.length + b.length).
Integración con asistentes de IA
Esta skill está optimizada para ser utilizada con Claude Code, Cursor, Codex y otros asistentes de codificación. Cuando el asistente detecte patrones de serialización, validación, parseo, o diseño de nuevas funciones, sugerirá automáticamente la aplicación de pruebas basadas en propiedades y proporcionará ejemplos específicos para el lenguaje en uso.
Buenas prácticas
- Comienza con propiedades simples e incrementa la complejidad gradualmente.
- Combina pruebas basadas en propiedades con pruebas basadas en ejemplos para casos críticos.
- Ajusta los generadores para incluir casos límite (ceros, nulos, valores extremos).
- Documenta cada propiedad con una descripción clara de lo que verifica.
- Ejecuta las pruebas con semillas fijas para reproducir fallos.