# Pytest

Pytest es un marco de pruebas de Python que tiene su origen en el proyecto PyPy. Se puede utilizar para escribir varios tipos de pruebas de software, incluyendo pruebas unitarias, pruebas de integración, pruebas de extremo a extremo y pruebas funcionales. Sus características incluyen pruebas parametrizadas, fixtures y reescritura de aserciones.
Pytest fixtures proporciona los contextos para las pruebas pasando nombres de parámetros en los casos de prueba; su parametrización elimina el código duplicado para probar múltiples conjuntos de entrada y salida; y sus declaraciones assert reescritas proporcionan una salida detallada de las causas de los fallos.

## Historia

Pytest fue desarrollado como parte de un esfuerzo de paquetes de terceros para hacer frente a las deficiencias del módulo integrado unittest de Python. Se originó como parte de PyPy, una implementación alternativa de Python al estándar CPython. Desde su creación a principios de 2003, PyPy ha puesto un gran énfasis en las pruebas. PyPy tenía pruebas unitarias para el código recién escrito, pruebas de regresión para errores y pruebas de integración utilizando el conjunto de pruebas de CPython.
A mediados de 2004, surgió un marco de pruebas llamado utest y los colaboradores de PyPy comenzaron a convertir los casos de prueba existentes a utest. Mientras tanto, en EuroPython 2004 se inventó una librería estándar complementaria para pruebas, llamada std. Este paquete estableció los principios, como la reescritura de aserciones, de lo que más tarde se convertiría en pytest. A finales de 2004, el proyecto std pasó a llamarse py, std.utest se convirtió en py.test, y la biblioteca py se separó de PyPy. En noviembre de 2010, pytest 2.0.0 fue lanzado como un paquete separado de py. Siguió llamándose py.test hasta agosto de 2016, pero tras el lanzamiento de pytest 3.0.0 el punto de entrada recomendado en la línea de comandos pasó a ser pytest.
Pytest ha sido clasificado por la plataforma de seguridad para desarrolladores Snyk como uno de los proyectos clave del ecosistema en Python debido a su popularidad. Algunos proyectos conocidos que cambiaron a pytest desde unittest y nose (otro paquete de pruebas) incluyen los de Mozilla y Dropbox.

## Características
### Pruebas parametrizadas

Es un patrón común en las pruebas de software enviar valores a través de funciones de prueba y comprobar si la salida es correcta. En muchos casos, con el fin de probar a fondo las funcionalidades, uno necesita probar múltiples conjuntos de entrada/salida, y escribir estos casos por separado causaría código duplicado, ya que la mayoría de las acciones seguirían siendo las mismas, sólo difieren en los valores de entrada/salida. La función de pruebas parametrizadas de pytest elimina el código duplicado combinando diferentes iteraciones en un caso de prueba, ejecutando estas iteraciones y mostrando el resultado de cada prueba por separado.
Las pruebas parametrizadas en pytest están marcadas por el decorador @pytest.mark.parametrize(argnames, argvalues), donde el primer parámetro, argnames, es una cadena de nombres separados por comas, y argvalues es una lista de valores para pasar a argnames. Cuando hay varios nombres en argnames, argvalues sería una lista de tuplas en la que los valores de cada tupla corresponden a los nombres de argnames por índice. Los nombres en argnames se pasan entonces a la función de prueba marcada por el decorador como parámetros. Cuando pytest ejecuta tales pruebas decoradas, cada par de argnames y argvalues constituiría una ejecución separada con su propia salida de prueba e identificador único. El identificador puede usarse entonces para ejecutar pares de datos individuales$^:$ $^{52-58.}$

### Reescritura de afirmaciones

Cuando se escriben pruebas de software, la sentencia assert es un medio primario para comunicar el fallo de la prueba, donde los valores esperados se comparan con los valores reales$^:$ $^{32-34}$ Mientras que la palabra clave assert incorporada en Python sólo lanzaría AssertionError sin detalles en casos de fallo, pytest reescribe la palabra clave assert de Python y proporciona una salida detallada para las causas de los fallos, como a qué se evalúan las expresiones en la sentencia assert. Se puede hacer una comparación con las sentencias assert de unittest (el módulo incorporado de Python para pruebas):$^:$ $^{32}$
| pytest | unittest |
| assert x | assertTrue(x) |
| assert x == y | assertEqual(x, y) |
| assert x <= y | assertLessEqual(x, y) |
unittest se adhiere a una sintaxis más verbosa porque está inspirada en JUnit del lenguaje de programación Java, al igual que la mayoría de las bibliotecas de pruebas unitarias; pytest logra lo mismo interceptando las llamadas de aserción incorporadas en Python, lo que hace que el enfoque sea más conciso$^:$

### Fixtures de Pytest

Las pruebas de Pytest verifican que el código de la computadora funciona como se esperausando pruebas que están estructuradas en una secuencia de arreglar, actuar y afirmar conocida como AAASus accesorios proporcionan el contexto para las pruebas. Pueden utilizarse para poner un sistema en un estado conocido y para pasar datos a las funciones de prueba. Los fixtures constituyen prácticamente la fase arrange en la anatomía de una prueba (AAA, abreviatura de arrange, act, assert) Los fixtures de Pytest pueden ejecutarse antes de los casos de prueba como setup o después de los casos de prueba para limpiar, pero son diferentes de los setups y teardowns de unittest y nose (otro framework de pruebas de Python de terceros) . Las funciones declaradas como fixtures de pytest se marcan con el decorador @pytest.fixture, cuyos nombres pueden pasarse a las funciones de prueba como parámetros. Cuando pytest encuentra los nombres de los fixtures en los parámetros de las funciones de prueba, primero busca en el mismo módulo tales fixtures, y si no los encuentra, busca tales fixtures en el archivo conftest.py.$^{:61}$
Por ejemplo:
En el ejemplo anterior, pytest fixture dataset devuelve un diccionario, que luego se pasa a la función de prueba test_dataset para su aserción. Además de la detección de fixture dentro del mismo archivo que los casos de prueba, los fixtures de pytest también se pueden colocar en el archivo conftest.py en el directorio de pruebas. Puede haber múltiples archivos conftest.py, cada uno colocado dentro de un directorio de pruebas para que las fijaciones sean detectadas para cada subconjunto de pruebas.$^{:63}$

#### Ámbitos de fixture

En pytest, los ámbitos de fixture permiten al usuario definir cuándo se debe llamar a un fixture. Hay cuatro ámbitos de fixture: ámbito de función, ámbito de clase, ámbito de módulo y ámbito de sesión. Las fixture con ámbito de función son las predeterminadas para todas las fixture de pytest, que se llaman cada vez que se ejecuta una función que tiene la fixture como parámetro. El objetivo de especificar un ámbito de fixture más amplio es eliminar las llamadas repetidas al fixture, que podrían ralentizar la ejecución de la prueba. Las fixture con ámbito de clase se llaman una vez por clase de prueba, independientemente del número de veces que se llamen, y la misma lógica se aplica a todos los demás ámbitos. Para cambiar el ámbito de las fixture, basta con añadir el parámetro scope a los decoradores de fixture, por ejemplo, @pytest.fixture(scope="class").$^{:72}$

### Filtrado de pruebas

Otra característica de pytest es su capacidad para filtrar a través de las pruebas, donde sólo las pruebas deseadas se seleccionan para ejecutarse, o se comportan de cierta manera según lo deseado por el desarrollador. Con la opción "k" (por ejemplo, pytest -k nombre_de_alguien), pytest sólo ejecutará las pruebas cuyos nombres incluyan nombre_de_alguien. Lo contrario es cierto, donde uno puede ejecutar pytest -k "no algún_nombre", y pytest ejecutará todas las pruebas cuyos nombres no incluyan algún_nombre.
Los marcadores de Pytest pueden, además de alterar el comportamiento de las pruebas, también filtrarlas. Los marcadores de Pytest son decoradores de Python que comienzan con la sintaxis@pytest.mark.<markername> colocados encima de las funciones de prueba. Con diferentes marcadores de nombre arbitrario, al ejecutar pytest -m <marcador> en la línea de comandos sólo se ejecutarán aquellas pruebas decoradas con dichos marcadores$^:$ $^{13}$ Todos los marcadores disponibles pueden ser listados por pytest --markers junto con sus descripciones; los marcadores personalizados también pueden ser definidos por los usuarios y registrados en pytest.ini, en cuyo caso pytest --markers también listará esos marcadores personalizados junto con los marcadores incorporados.