Parametrización de pruebas con SubTest en UnitTest
Resumen
El uso de SubTest en UnitTest te permite optimizar tus pruebas evitando la duplicación de código. Imagina que necesitas probar un método con varios valores diferentes. Sin SubTest, tendrías que crear varias pruebas casi idénticas, lo que resulta ineficiente. SubTest permite parametrizar pruebas, lo que significa que puedes ejecutar la misma prueba con diferentes valores sin repetir el código.
¿Cómo evitar la duplicación de pruebas con SubTest?
Al utilizar SubTest, puedes definir todos los valores que deseas probar en una lista o diccionario. Luego, iteras sobre estos valores mediante un bucle for, ejecutando la misma prueba con cada conjunto de parámetros. Así, si es necesario modificar la prueba, solo tienes que hacer cambios en un único lugar.
¿Cómo implementar SubTest en un caso práctico?
Para ilustrarlo, se puede crear una prueba llamada test_deposit_various_values. En lugar de duplicar la prueba con diferentes valores de depósito, utilizas un diccionario que contiene los valores a probar y el resultado esperado. Después, recorres estos valores con SubTest usando la estructura with self.subTest(case=case) y ejecutas la prueba para cada valor del diccionario. Esto asegura que cada prueba sea independiente y evita sumar valores a la cuenta de manera incorrecta.
¿Cómo gestionar errores con SubTest?
SubTest también es útil para identificar errores específicos. Si una prueba falla con un conjunto particular de parámetros, SubTest te permite ver fácilmente qué valores causaron el fallo. Esto facilita mucho la corrección de errores, ya que puedes aislar rápidamente los casos problemáticos y corregirlos de manera eficiente.
🧪 SubTest en unittest: optimización de pruebas parametrizadas
✅ ¿Qué es subTest?
subTest es una funcionalidad del módulo unittest que permite ejecutar múltiples variantes de una misma prueba dentro de un solo método, sin duplicar código ni perder visibilidad sobre qué casos fallan.
🚀 Ventajas clave
Evita duplicación: No necesitas escribir múltiples métodos de prueba para cada caso.
Mejor trazabilidad: Si un caso falla, unittest lo reporta individualmente sin detener los demás.
Más legible y mantenible: Ideal para probar funciones con múltiples entradas esperadas.
Cada subTest se ejecuta como una unidad independiente. Si uno falla, el resto continúa, y el reporte indica exactamente qué entrada falló.
Gran aporte!
En Python, el uso de subTest dentro del módulo unittest permite parametrizar pruebas, facilitando la ejecución de múltiples casos de prueba dentro de una sola función de prueba. Esto es útil cuando quieres probar una función con diferentes entradas y verificar sus resultados sin necesidad de crear múltiples métodos de prueba. Aquí tienes una guía sobre cómo usar subTest para parametrizar pruebas.
### 1. Importar el Módulo Necesario
Primero, asegúrate de importar unittest.
import unittest
### 2. Definir tu Clase de Pruebas
Crea una clase de prueba que herede de unittest.TestCase.
classTestMiFuncion(unittest.TestCase):  def mi\_funcion(self, x):  \# Esta es la función que estás probando  return x \* 2
### 3. Usar subTest para Parametrizar las Pruebas
Dentro de tu método de prueba, utiliza un bucle para iterar sobre los casos de prueba. Usa subTest para encapsular cada caso.
classTestMiFuncion(unittest.TestCase):  def mi\_funcion(self, x):  return x \* 2  def test\_multiplicacion(self):  casos\_de\_prueba = \[  (1, 2),  (2, 4),  (3, 6),  (4, 8),  (5, 10)  ]     for entrada, resultado\_esperado in casos\_de\_prueba:  with self.subTest(entrada=entrada):  resultado = self.mi\_funcion(entrada)  self.assertEqual(resultado, resultado\_esperado)
### 4. Ejecutar las Pruebas
Finalmente, ejecuta las pruebas utilizando la línea de comando.
python -m unittest nombre\_del\_archivo.py
### Ejemplo Completo
Aquí tienes un ejemplo completo que incluye todas las partes mencionadas:
- **Claridad**: Cada caso de prueba se ejecuta de manera aislada, lo que facilita identificar cuál falló.
- **Mantenimiento**: Evita la duplicación de código, lo que hace que sea más fácil mantener y actualizar las pruebas.
- **Resultados Detallados**: subTest proporciona un informe claro sobre qué subprueba falló, lo que facilita la depuración.
Usar subTest es una excelente manera de mantener tus pruebas organizadas y eficientes, especialmente cuando trabajas con múltiples casos de entrada y salida.
Hola Clase, Yo creo que este codigo es mas correcto para nuestro caso contexto de test_Bank_Account que ya tenemos en ./tests/test_bankAccount.py :
def test_deposit_multiple_amounts(self): test_amounts =[{"amount":150,"expected":1150},{"amount":1250,"expected":2250},{"amount":1500,"expected":2500}]forcaseintest_amounts:with self.subTest(amount=case["amount"], expected=case["expected"]): # Reset balance to 1000for each test
self.account.balance=1000 # Make deposit and verify success
self.assertTrue(self.account.deposit(case["amount"]), f"Deposit of ${case['amount']} should succeed") # Check balance
self.assertEqual(self.account.get_balance(),case["expected"], f"After depositing ${case['amount']} to $1000")
\n Este Usa setUp y Restart el balance cada iteracion.
En mis pruebas no falla el hecho de no instanciar nuevamente el BankAccount, de igual manera por qué fallaría si según lo visto con el setUp siempre se estaría regenerando este valor?
Sí, usando el del setUp debería bastar, pero si tienes dos con el mismo nombre si deberia fallar.
# test con multiples valores.@pytest.mark.parametrize("deposit_amount, expected_balance",[(1000,2000),(3000,4000),(5000,6000),])deftest_deposit_multiple_values(setup_account, deposit_amount, expected_balance):"""
Prueba el método deposit con múltiples valores usando parametrización.
""" new_balance = setup_account.deposit(deposit_amount)assert new_balance == expected_balance
# test con multiples valores usando un diccionario.@pytest.mark.parametrize("data",[{"deposit_amount":1000,"expected_balance":2000},{"deposit_amount":3000,"expected_balance":4000},{"deposit_amount":5000,"expected_balance":6000},])deftest_deposit_multiple_values_dict(setup_account, data):"""
Prueba el método deposit con múltiples valores usando un diccionario.
""" new_balance = setup_account.deposit(data["deposit_amount"])assert new_balance == data["expected_balance"]