Usar py.test con cobertura no incluye importaciones

Para Jedi queremos generar nuestra cobertura de prueba . Hay una pregunta relacionada en stackoverflow, pero no ayudó.

Estamos usando py.test como un corredor de prueba. Sin embargo, no podemos agregar las importaciones y otras cosas “importadas” al informe. Por ejemplo, __init__.py siempre se informa como descubierto:

 Name Stmts Miss Cover -------------------------------------------------- jedi/__init__ 5 5 0% [..] 

Claramente, este archivo se está importando y, por lo tanto, debe informarse como probado.

Comenzamos pruebas como esta [*]:

 py.test --cov jedi 

Como puedes ver, estamos usando pytest-coverage .

Entonces, ¿cómo es posible contar adecuadamente la cobertura de archivos como __init__.py ?

[*] También intentamos iniciar la prueba sin --doctest-modules (eliminado de pytest.ini ) y activamos el módulo de cobertura anteriormente mediante py.test -p pytest_cov --cov jedi . Ninguno de ellos trabaja.

He ofrecido una recompensa. Por favor, intenta arreglarlo dentro de Jedi. Está disponible públicamente.

Related of "Usar py.test con cobertura no incluye importaciones"

@Hynekcer me dio la idea correcta. Pero básicamente la solución más fácil está en otra parte:

Deshazte de pytest-cov !

Utilizar

 coverage run --source jedi -m py.test coverage report 

¡¡¡en lugar!!! De esta manera, solo está ejecutando una cobertura en su configuración actual de py.test, ¡que funciona perfectamente bien! También es filosóficamente el camino correcto: haga que cada progtwig haga una cosa bien: py.test realiza pruebas y la coverage verifica la cobertura del código.

Ahora esto puede sonar como una perorata, pero en realidad. pytest-cov no ha funcionado correctamente por un tiempo. Algunas pruebas estaban fallando, solo porque las usamos.


A partir de 2014 , pytest-cov parece haber cambiado de manos. py.test --cov jedi test parece ser un comando útil de nuevo (mira los comentarios). Sin embargo, no es necesario utilizarlo. Pero en combinación con xdist puede acelerar sus informes de cobertura.

Fijé la cobertura de prueba al 94% con este parche que simplifica las dependencias de importación y con el comando:

 py.test --cov jedi test # or py.test --cov jedi test --cov-report=html # + a listing with red uncovered lines 

Las líneas descubiertas están solo en comandos condicionales o en algunas funciones menos utilizadas, pero todos los encabezados están completamente cubiertos.

El problema fue que la prueba de configuración de test/conftest.py importó prematuramente por las dependencias de casi todos los archivos del proyecto. El archivo conftest define también las opciones de línea de comandos adicionales y las configuraciones que deben establecerse antes de ejecutar la prueba. Por lo tanto, creo que el complemento pytest_cov funciona correctamente si ignora todo lo que se importó junto con este archivo, aunque es un problema. También __init__.py y settings.py del informe porque son simples y con la cobertura completa, pero también importan prematuramente en la dependencia de conftest.

En mi caso, todas las pruebas se ejecutan, pero la cobertura fue del 0%.

La solución fue:

 $ export PYTHONPATH="." 

Después los resultados fueron correctos.

En el pasado tuve algunos problemas con el comando py.test tenía problemas para importar algo y configurar PYTHONPATH env var era la solución. Funcionó para mí esta vez también.

Mi ejemplo real con awslogs

Primero con PYTHONPATH unset:

 $ py.test --cov=awslogs tests/ ========================================= test session starts ========================================= platform linux2 -- Python 2.7.9, pytest-2.8.5, py-1.4.31, pluggy-0.3.1 rootdir: /home/javl/sandbox/awslogs/github/awslogs, inifile: plugins: cov-2.2.0 collected 11 items tests/test_it.py ...........Coverage.py warning: No data was collected. --------------------------- coverage: platform linux2, python 2.7.9-final-0 --------------------------- Name Stmts Miss Cover ------------------------------------------- awslogs/__init__.py 2 2 0% awslogs/bin.py 85 85 0% awslogs/core.py 143 143 0% awslogs/exceptions.py 12 12 0% ------------------------------------------- TOTAL 242 242 0% ====================================== 11 passed in 0.38 seconds ====================================== 

La cobertura resultante es del 0%.

Luego puse el PYTHONPATH :

 $ export PYTHONPATH="." 

y volver a ejecutar la prueba:

 $ py.test --cov=awslogs tests/ ========================================= test session starts ========================================= platform linux2 -- Python 2.7.9, pytest-2.8.5, py-1.4.31, pluggy-0.3.1 rootdir: /home/javl/sandbox/awslogs/github/awslogs, inifile: plugins: cov-2.2.0 collected 11 items tests/test_it.py ........... --------------------------- coverage: platform linux2, python 2.7.9-final-0 --------------------------- Name Stmts Miss Cover ------------------------------------------- awslogs/__init__.py 2 0 100% awslogs/bin.py 85 9 89% awslogs/core.py 143 12 92% awslogs/exceptions.py 12 2 83% ------------------------------------------- TOTAL 242 23 90% ====================================== 11 passed in 0.44 seconds ====================================== 

Ahora es la cobertura del 90%.

ADVERTENCIA : la manipulación de PYTHONPATH puede tener efectos secundarios extraños. Actualmente me encuentro con un problema, ese paquete basado en pbr está creando el directorio de egg al comstackr distribuible y si PYTHONPATH está configurado en “.”, Automáticamente considera que el paquete relacionado con egg está instalado. Por este motivo, dejé de usar pytest-cov y pytest-cov los consejos para usar la herramienta de coverage .

Tuve este problema con py.test, la cobertura y el complemento django. Al parecer, los archivos de modelo se importan antes de que se inicie la cobertura. Ni siquiera la “cobertura -p” para la carga temprana del complemento de cobertura funcionó.

Lo arreglé (¿feo?) Quitando el módulo de modelos de sys.modules y volviéndolo a importar en el archivo de prueba que prueba el modelo:

 import sys del sys.modules['project.my_app.models'] from project.my_app import models def test_my_model(): ...