Un error que arreglas puede volver
Una regresión es un error que vuelve después de arreglarlo, o una función que funcionaba y deja de hacerlo tras un cambio. Una prueba de regresión es una prueba escrita para un error concreto, para que ese error no vuelva sin avisar.
En esta lección un cliente informa de un error. Tú escribes primero la prueba y después la corrección.
Al terminar esta lección
Nota
Puedo convertir el informe de un error en una prueba que falla, arreglar el error y guardar la prueba.
Palabras clave
| Palabra | Qué significa |
|---|---|
| Regresión | un error que vuelve, o una función que deja de funcionar tras un cambio |
| Prueba de regresión | una prueba escrita para un error informado, que se guarda para siempre |
| Informe de error | lo que dice un usuario que salió mal, con la entrada que lo causó |
| Rojo | una ejecución en la que una prueba falla |
| Verde | una ejecución en la que todas las pruebas pasan |
| Caso vecino | una entrada cercana a la del informe, para ver que la corrección no movió el error |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Convierte un informe en una prueba
Una tienda da una décima parte de descuento en pedidos de 100 euros o más. Un cliente escribe: "Gasté justo 100 euros y no tuve descuento."
El informe contiene la entrada: 10000 céntimos. La tienda trabaja en céntimos para que ningún precio sea una fracción. Crea primero la carpeta y el código tal como está hoy, con el defecto.
Crea una carpeta para la lección
mkdir -p ~/regtestSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Entra en ella
cd ~/regtestSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el código de la tienda de hoy
printf 'def discount(total_cents):\n if total_cents > 10000:\n return total_cents // 10\n return 0\n' > shop.pySe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe la prueba antes de la corrección
Convierte el informe en una prueba con la entrada exacta del cliente. Ponle el nombre de lo que vio el cliente, para que un fallo se lea como el informe.
Ejecútala antes de arreglar nada. Debe fallar. Una prueba que pasa con el código roto no demuestra nada.
Escribe la prueba a partir del informe
printf 'import unittest\nfrom shop import discount\n\n\nclass DiscountReport(unittest.TestCase):\n def test_exactly_100_euros_gets_a_tenth_off(self):\n self.assertEqual(discount(10000), 1000)\n' > test_shop.pySe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejecútala y mira cómo falla
python3 -m unittest test_shop 2>&1 | grep -E "^(OK|FAILED|AssertionError)"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Arregla solo lo que muestra la prueba
El código dice > donde la regla dice "o más". Cámbialo a >= y nada más. Después ejecuta la prueba otra vez. Debe ponerse verde.
Cambia el signo mayor que
sed -i 's|total_cents > 10000|total_cents >= 10000|' shop.pySe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejecuta la prueba otra vez
python3 -m unittest test_shop 2>&1 | grep -E "^(OK|FAILED|AssertionError)"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Añade los vecinos del error
Una corrección puede mover un error en lugar de quitarlo. Si por error escribes >= 9999, un pedido de 99,99 euros recibe descuento. Prueba las entradas a cada lado de la del informe.
Ejemplo resuelto: los casos junto al límite
| Pedido en céntimos | Descuento que debe recibir | Por qué está |
|---|---|---|
| 9999 | 0 | Un céntimo menos: sin descuento |
| 10000 | 1000 | El informe: justo en el límite |
| 10001 | 1000 | Uno más: céntimos enteros, hacia abajo |
| 25000 | 2500 | Muy por encima: el descuento no tiene tope |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Añade dos pruebas vecinas
printf ' def test_one_cent_under_gets_nothing(self):\n self.assertEqual(discount(9999), 0)\n\n def test_over_the_line_gets_a_tenth(self):\n self.assertEqual(discount(25000), 2500)\n' >> test_shop.pySe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejecuta las tres
python3 -m unittest test_shop 2>&1 | grep -E "^(OK|FAILED|AssertionError)"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Demuestra que la prueba protege la corrección
Una prueba de regresión se gana su sitio cuando el error vuelve. Devuelve el error a propósito, como haría un cambio descuidado, y mira cómo lo detecta el conjunto. Después devuelve la corrección.
Devuelve el error
sed -i 's|total_cents >= 10000|total_cents > 10000|' shop.pySe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejecuta las pruebas
python3 -m unittest test_shop 2>&1 | grep -E "^(OK|FAILED|AssertionError)"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Devuelve la corrección
sed -i 's|total_cents > 10000|total_cents >= 10000|' shop.pySe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejecuta las pruebas una vez más
python3 -m unittest test_shop 2>&1 | grep -E "^(OK|FAILED|AssertionError)"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Un error frecuente
Advertencia
Mucha gente arregla el error, escribe una prueba que pasa y da el trabajo por hecho. Esa prueba nunca estuvo en rojo, así que nadie sabe si detecta el fallo. Escríbela primero, mira cómo falla y después arregla.
Más lejos: un informe sin entrada
Algunos informes no traen entrada: "el total se veía mal el martes". Antes de escribir una prueba tienes que encontrar una.
Anota tres preguntas que harías al cliente para obtener una entrada que puedas reproducir. ¿Cuál harías primero?