Métricas de prueba.

Cobertura de código de Python

Python es uno de los lenguajes de programación más populares disponibles actualmente. Debido a su naturaleza de propósito general, Python encuentra aplicación en varios casos de uso de desarrollo de software que van desde simples scripts hasta servidores web y frameworks como Django.

Sin embargo, al igual que con otros lenguajes de programación, las pruebas siguen siendo uno de los aspectos más importantes del desarrollo de software en Python.

En este post, veremos algunas herramientas para medir y escribir la cobertura de casos de prueba para el código de Python.

Unittest

La biblioteca estándar de Python está pre-construida con un módulo llamado unittest. Inspirado en JUnit y otros marcos de pruebas unitarias de los principales lenguajes de programación, unittest es un marco de pruebas que le permite automatizar las pruebas, la configuración compartida y el código de cierre para las pruebas y más.

Una de las características importantes de unittest es el fixture de prueba, es decir, la configuración necesaria para ejecutar una o más pruebas, y cualquier acción de limpieza asociada. Con el fixture de texto, las actividades, como la creación de bases de datos temporales o proxy, directorios, o el inicio de un proceso de servidor, pueden ser atendidos en un solo lugar.

Tomemos algunos casos de prueba de ejemplo y veamos cómo se implementan utilizando unittest:

importar unittest

clase TestStringMethods(unittest.TestCase):

def test_upper(self):
self.assertEqual(‘foo’.upper(), ‘FOO’)

def test_isupper(self):
self.assertTrue(‘FOO’.isupper())
self.assertFalse(‘Foo’.isupper())

def test_split(self):
s = ‘hola mundo’
self.assertEqual(s.split(), )
# comprueba que s.split falla cuando el separador no es una cadena
con self.assertRaises(TypeError):
s.split(2)

if __name__ == ‘__main__’:
unittest.main()

Crea un caso de prueba subclasificando unittest.TestCase. Luego puede definir pruebas individuales con métodos. Tenga en cuenta que los nombres de los casos de prueba deben comenzar con la palabra test. Esta convención de nomenclatura informa al ejecutor de pruebas sobre qué métodos representan las pruebas.

El ejecutor de pruebas es el componente que orquesta la ejecución de las pruebas y proporciona el resultado al usuario. Su implementación varía y puede utilizar una interfaz gráfica, una interfaz textual, o devolver un valor especial para indicar los resultados de la ejecución de las pruebas.

Pytest

Pytest es un marco de pruebas de Python de terceros. Su objetivo es proporcionar un marco para escribir sus pruebas de manera eficiente, mediante la eliminación de todos los gastos generales para la creación de pruebas. Pytest es compatible con Python 2.7, 3.4, 3.5, 3.6, Jython, PyPy-2.3 en Unix/Posix y Windows.

Veamos cómo empezar con Pytest.En primer lugar, descargue la última versión e instálela mediante pip:

pip install -U pytest

Puede comprobar la versión instalada mediante:

pytest -version

Ahora, tomemos una función de ejemplo y un caso de prueba relacionado.

# contenido de test_sample.py
def func(x):
return x + 1def test_answer():
assert func(3) == 5

La función func toma una entrada x y devuelve un valor x + 1. En el caso de prueba, afirmamos si la función func toma la entrada 3 y devuelve 5. Se espera que este caso de prueba falle. Para ejecutar la prueba simplemente escriba pytest en el directorio que tiene el archivo test_sample.py.

$ pytest
=========================== sesión de prueba se inicia ============================
plataforma linux – Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
rootdir: $REGENDOC_TMPDIR, inifile:
collected 1 itemtest_sample.py F ================================= FAILURES =================================
_______________________________ test_answer ________________________________

def test_answer():
> assert func(3) == 5
E assert 4 == 5
E + where 4 = func(3)

test_sample.py:5: AssertionError
========================= 1 falló en 0,12 segundos =========================

Coverage.py

Coverage.py es una de las herramientas de cobertura de código más populares para Python. Utiliza herramientas de análisis de código y ganchos de rastreo proporcionados en la biblioteca estándar de Python para medir la cobertura. Se ejecuta en las principales versiones de CPython, PyPy, Jython y IronPython. Puede utilizar Coverage.py tanto con unittest como con Pytest.

Puede descargar la última versión de Coverage e instalarla manualmente, o puede instalarla con pip as:

$ pip install coverage

Ahora ejecute su programa con coverage as

$ coverage run my_program.py arg1 arg2

A continuación, para obtener los datos de cobertura, ejecute

$ coverage report -m

Aquí tiene un ejemplo de salida de datos de cobertura

$ coverage report -m
Name Stmts Miss Cover Missing
——————-
my_program.py 20 4 80% 33-35, 39
mi_otro_módulo.py 56 6 89% 17-23
——————-
TOTAL 76 10 87%

Generar informe en archivo html:

$ coverage html

Este es un ejemplo de informe HTML generado por Coverage.py. Incluye Módulo, sentencias, faltantes, excluidos, ramas, parcial y cobertura.

Pytest-cov

Pytest-cov es un plugin de Python para generar informes de cobertura. Además de las funcionalidades soportadas por el comando de cobertura, también soporta pruebas centralizadas y distribuidas. También soporta la cobertura de los subprocesos.

Una vez que haya escrito los casos de prueba como se requiere con Pytest, puede utilizar Pytest-cov para ejecutar todas las pruebas y reportar la cobertura.

Para empezar, instale Pytest-cov como:

$ pip install pytest-cov

Pruebas centralizadas

Las pruebas centralizadas reportan la cobertura combinada del proceso principal y todos sus subprocesos. Puede ejecutar pruebas centralizadas utilizando,

$ py.test -cov= tests/

Pruebas distribuidas

Instalar Pytest-xdist, para el soporte de sistemas distribuidos:

$ pip install pytest-xdist

Las pruebas distribuidas pueden realizarse en dos modos, dist configuradas a carga y each. Cuando se establece a la carga, la cobertura combinada de todos los esclavos se reporta mientras la prueba distribuida. Los esclavos pueden estar repartidos en cualquier número de hosts y cada esclavo puede estar ubicado en cualquier lugar del sistema de archivos. Cada esclavo tendrá sus subprocesos medidos.

Para las pruebas distribuidas en cada modo, pytest-cov también informa sobre la cobertura combinada de todos los esclavos. Dado que cada esclavo está ejecutando todas las pruebas, esto permite generar un informe de cobertura combinada para múltiples entornos

Resumen

En este post, hemos aprendido sobre varios frameworks de pruebas unitarias y cobertura de código de Python. Si bien estos frameworks facilitan el proceso de pruebas, aún es necesario escribir las pruebas. Aquí están algunas de las mejores prácticas a tener en cuenta al escribir pruebas unitarias.

  • Usa nombres largos y descriptivos. Esto a menudo obvia la necesidad de doctrinas en los métodos de prueba.
  • Las pruebas deben ser aisladas. No interactuar con una base de datos real o la red. Utilice una base de datos de prueba separada que se descompone o utiliza objetos simulados.
  • Enfóquese en una pequeña parte de la funcionalidad.
  • Debe ser rápido, pero una prueba lenta es mejor que ninguna prueba.
  • A menudo tiene sentido tener una clase de caso de prueba para una sola clase o modelo.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.