En este tutorial, exploramos las pruebas basadas en propiedades utilizando Hipótesis y creamos un proceso de pruebas riguroso que va mucho más allá de las pruebas unitarias tradicionales. Implementamos invariantes, pruebas diferenciales, pruebas metamórficas, exploración dirigida y pruebas con estado para validar tanto la corrección funcional como las garantías de comportamiento de nuestros sistemas. En lugar de crear manualmente casos extremos, permitimos que Hypothesis genere entradas estructuradas, reduzca las fallas a contraejemplos mínimos y descubra sistemáticamente errores ocultos. Además, demostramos cómo las prácticas de prueba modernas se pueden integrar directamente en flujos de trabajo experimentales y basados en la investigación.
Configuramos el entorno instalando Hypothesis y pytest e importando todos los módulos necesarios. Comenzamos a construir el conjunto de pruebas completo definiendo funciones de utilidad principales como abrazadera, normalize_whitespace y merge_sorted. Establecemos la base funcional que nuestras pruebas basadas en propiedades validarán rigurosamente en fragmentos posteriores.
elif t[0] == “-“: signo = -1 t = t[1:]
si no es t o cualquiera(ch < "0" o ch > “9” para ch en t): devolver (Falso, “not_an_int”) si len
Implementamos lógica de análisis y definimos estrategias estructuradas que generan entradas de prueba significativas y restringidas. Creamos estrategias compuestas como int_like_strings para controlar con precisión el espacio de entrada para la validación de propiedades. Preparamos generadores de listas ordenadas y estrategias de límites que permiten pruebas basadas en diferenciales e invariantes.
Definimos pruebas de propiedades centrales que validan la corrección y la idempotencia en múltiples funciones. Utilizamos decoradores de hipótesis para explorar automáticamente casos extremos y verificar garantías de comportamiento, como restricciones de límites y normalización determinista. También implementamos pruebas diferenciales para garantizar que nuestra implementación de fusión coincida con una referencia confiable.
Ampliamos nuestra validación para analizar la solidez y la corrección estadística mediante exploración dirigida. Verificamos que dos analizadores de enteros independientes acuerden entradas estructuradas y apliquen reglas de rechazo en cadenas no válidas. Además, implementamos pruebas metamórficas validando invariantes de varianza bajo transformación.
def deposit(self, amt: int): si amt <= 0: aumentar ValueError("el depósito debe ser positivo") self.balance += amt self.ledger.append(("dep", amt)) def retirar(self, amt: int): si amt <= 0: aumentar ValueError("el retiro debe ser positivo") if amt > self.balance: aumentar ValueError(“fondos insuficientes”) self.balance -= amt self.ledger.append((“wd”, amt)) def replay_balance(self): bal = 0 para typ, amt in self.ledger: bal += amt if typ == “dep” else -amt return bal class BankMachine(RuleBasedStateMachine): def __init__(self): super().__init__() self.bank = Bank() @initialize() def init(self): afirmar self.bank.balance == 0 afirmar self.bank.replay_balance() == 0 @rule(amt=st.integers(min_value=1, max_value=10_000)) def deposit(self, amt): self.bank.deposit(amt) @precondition(lambda self: self.bank.balance > 0) @rule(amt=st.integers(min_value=1, max_value=10_000)) def retirar(self, amt): asumir(amt <= self.bank.balance) self.bank.withdraw(amt) @invariant() def balance_never_negative(self): afirmar self.bank.balance >= 0 @invariant() def ledger_replay_matches_balance(self): afirmar self.bank.replay_balance() == self.bank.balance TestBankMachine = BankMachine.TestCase ”’ ruta = “/tmp/test_hypothesis_advanced.py” con open(ruta, “w”, codificación=”utf-8″) como f: f.write(test_code) print(“Versión de hipótesis:”, __import__(“hipótesis”).__versión__) print(“\nEjecutando pytest en:”, ruta, “\n”) res = subprocess.run([sys.executable, “-m”, “pytest”, “-q”, path]capture_output=True, text=True) print(res.stdout) if res.returncode != 0: print(res.stderr) if res.returncode == 0: print(“\nTodas las pruebas de hipótesis aprobadas.”) elif res.returncode == 5: print(“\nPytest no recopiló pruebas.”) else: print(“\nAlgunas pruebas fallaron.”)
Implementamos un sistema con estado utilizando la máquina de estado basada en reglas de Hypothesis para simular una cuenta bancaria. Definimos reglas, condiciones previas e invariantes para garantizar la coherencia del saldo y la integridad del libro mayor en secuencias de operación arbitrarias. Luego ejecutamos todo el conjunto de pruebas a través de pytest, lo que permite a Hypothesis descubrir automáticamente contraejemplos y verificar la corrección del sistema.
En conclusión, creamos un marco de prueba integral basado en propiedades que valida funciones puras, lógica de análisis, comportamiento estadístico e incluso sistemas con estado con invariantes. Aprovechamos las capacidades cada vez más reducidas, de búsqueda dirigida y de pruebas de máquinas de estado de Hypothesis para pasar de las pruebas basadas en ejemplos a la verificación basada en el comportamiento. Nos permite razonar sobre la corrección en un nivel más alto de abstracción mientras mantiene sólidas garantías para los casos extremos y la coherencia del sistema.
Consulte el cuaderno de codificación completo aquí. Además, no dude en seguirnos en Twitter y no olvide unirse a nuestro SubReddit de más de 130.000 ML y suscribirse a nuestro boletín. ¡Esperar! estas en telegrama? Ahora también puedes unirte a nosotros en Telegram.
¿Necesita asociarse con nosotros para promocionar su repositorio de GitHub O su página principal de Hugging O su lanzamiento de producto O seminario web, etc.? Conéctate con nosotros