Ejercicio
En este ejercicio, usarás pytest con parametrize para probar una función. A continuación, actualizará una clase de prueba para usar un accesorio de prueba en lugar de un método setup() y teardown(). El uso de parametrize y el trabajo con accesorios de prueba le permitirá ser más flexible al crear o actualizar las pruebas.
Paso 1: Adición de un archivo con pruebas para este ejercicio
Cree un nuevo archivo de prueba denominado test_advanced.py y agregue el código siguiente:
def str_to_bool(string): if string.lower() in ['yes', 'y', '1']: return True elif string.lower() in ['no', 'n', '0']: return FalseLa función
str_to_bool()acepta una cadena como entrada y, en función de su contenido, devolverá un valorTrueoFalse.En el mismo archivo, anexe las pruebas para la función
str_to_bool(). Usepytest.mark.parametrize()para probar primero todos los valores true:import pytest @pytest.mark.parametrize("string", ['Y', 'y', '1', 'YES']) def test_str_to_bool_true(string): assert str_to_bool(string) is TrueA continuación, anexe otra prueba con los valores false:
@pytest.mark.parametrize("string", ['N', 'n', '0', 'NO']) def test_str_to_bool_false(string): assert str_to_bool(string) is FalseAhora hay dos pruebas que cubren todas las entradas posibles para los valores devueltos
TrueyFalse.
Nota
No es habitual tener pruebas dentro del mismo archivo como código real. Por motivos de simplicidad, los ejemplos de este ejercicio tendrán código real en el mismo archivo. En los proyectos de Python reales, descubrirá que las pruebas están separadas por archivos y directorios del código que está probando.
Paso 2: Ejecución de las pruebas y exploración del informe
Después de agregar pruebas, el siguiente paso consiste en ejecutar pytest e inspeccionar la salida. Use la marca de detalle aumentada (-v) para que pueda ver que todos los valores de entrada se tratan como una prueba independiente.
$ pytest -v test_avanced.py
============================= test session starts ==============================
Python 3.9.6, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /private
collected 8 items
test_advanced.py::test_str_to_bool_true[Y] PASSED [ 12%]
test_advanced.py::test_str_to_bool_true[y] PASSED [ 25%]
test_advanced.py::test_str_to_bool_true[1] PASSED [ 37%]
test_advanced.py::test_str_to_bool_true[YES] PASSED [ 50%]
test_advanced.py::test_str_to_bool_false[N] PASSED [ 62%]
test_advanced.py::test_str_to_bool_false[n] PASSED [ 75%]
test_advanced.py::test_str_to_bool_false[0] PASSED [ 87%]
test_advanced.py::test_str_to_bool_false[NO] PASSED [100%]
============================== 8 passed in 0.01s ===============================
Aunque escribió solo dos funciones de prueba, pytest pudo crear ocho pruebas en total gracias a la función parametrize().
Paso 3: Migración de una prueba existente a un accesorio
Agregue una nueva prueba basada en clases al archivo test_advanced.py . Esta prueba debe usar una función
setup()yteardown()que crea un archivo temporal con texto sobre él. Después de cada prueba, el archivo se elimina. Debería tener este aspecto:import os class TestFile: def setup(self): with open("/tmp/done", 'w') as _f: _f.write("1") def teardown(self): try: os.remove("/tmp/done") except OSError: pass def test_done_file(self): with open("/tmp/done") as _f: contents = _f.read() assert contents == "1"Esta clase de prueba crea un archivo, pero es problemático porque no se garantiza que la ruta de acceso /tmp/ esté presente en todos los sistemas.
Cree un accesorio de prueba que use el accesorio de prueba
pytesttmpdir()para escribir en el archivo y devolver la ruta de acceso:import pytest @pytest.fixture def tmpfile(tmpdir): def write(): file = tmpdir.join("done") file.write("1") return file.strpath return writeEl accesorio de prueba
tmpfile()usa el accesorio de pruebatmpdir()de Pytest, que garantiza un archivo temporal válido que se limpia una vez realizadas las pruebas.Actualice la
TestFileclase para que use el accesorio en lugar de los métodos auxiliares:class TestFile: def test_f(self, tmpfile): path = tmpfile() with open(path) as _f: contents = _f.read() assert contents == "1"Esta clase de prueba ahora puede garantizar que se crea y se limpia un archivo temporal con el contenido adecuado para que funcione la aserción.
Compruebe su trabajo
Por ahora debería tener un archivo de Python denominado test_advanced.py con el código siguiente:
- Función
str_to_bool()que acepta una cadena y devuelve un valor booleano en función del contenido de la cadena. - Dos pruebas parametrizadas para la función
str_to_bool(); una que prueba los valoresTruey la otra que prueba los valoresFalse. - Un accesorio de prueba de
pytestpersonalizado que usa el accesorio de pruebatmpdir()para crear un archivo done temporal con contenido. - Clase de prueba que usa el accesorio personalizado
tmpfile()para crear el archivo.
Todas las pruebas deben superarse al ejecutarlas en el terminal, sin errores.