cobertura.py no cubre el script si py.test lo ejecuta desde otro directorio

Obtuve una secuencia de comandos de Python que toma argumentos de la línea de comandos, trabajando con algunos archivos. Estoy escribiendo pruebas py.test con py.test poniendo este script a su ritmo, ejecutándolo con subprocess.call .

Ahora quiero analizar la cobertura de código con coverage.py . La cobertura, cuando se usa a través del pytest-cov (que tiene incorporado el manejo de subprocesos), no ve / cubre mi script cuando se llama desde un directorio de prueba temporal creado con el accesorio tmpdir . La cobertura ve mi script cuando se llama en el directorio donde reside (y el argumento de nombre de archivo apunta a una ruta remota).

En ambas situaciones, mis pruebas pasan ! Cobertura 3.6, pytest-2.3.5, pytest-cov 1.6, todas de PyPi.

Pregunta: ¿Cómo puedo obtener cobertura para reconocer mi script incluso si se ejecuta en otro directorio? ¿Es esto un error en la cobertura, o algo que simplemente no es posible hacer? Me sorprendería que este último, después de todo, tmpdir sea ​​un mecanismo común de py.test …

Ejemplo mínimo:

my_script.py un script my_script.py que simplemente refleja el contenido de un archivo arg_file.txt proporcionado a través del argumento de la línea de comandos. En dos pruebas diferentes, esto se llama una vez en un tmpdir , y una vez en la ubicación del script. Ambas pruebas pasan, pero en la prueba tmpdir, ¡no obtengo información de cobertura!

Prueba de funcionamiento:

 ~/pytest_experiment$ py.test -s =================================== test session starts ==================================== platform linux2 -- Python 2.7.4 -- pytest-2.3.5 plugins: cov collected 2 items tests/test_in_scriptdir.py set_up: In directory /tmp/pytest-52/test_10 Running in directory /home/cbuchner/pytest_experiment Command: ./my_script.py /tmp/pytest-52/test_10/arg_file.txt --Contents of arg_file.txt-- . tests/test_in_tmpdir.py set_up: In directory /tmp/pytest-52/test_11 Running in directory /tmp/pytest-52/test_11 Command: /home/cbuchner/pytest_experiment/my_script.py arg_file.txt --Contents of arg_file.txt-- . ================================= 2 passed in 0.06 seconds ================================= 

Cobertura:

 ~/pytest_experiment$ py.test --cov=my_script.py tests/test_in_scriptdir.py=================================== test session starts ==================================== platform linux2 -- Python 2.7.4 -- pytest-2.3.5 plugins: cov collected 1 items tests/test_in_scriptdir.py . --------------------- coverage: platform linux2, python 2.7.4-final-0 ---------------------- Name Stmts Miss Cover ------------------------------- my_script 3 0 100% ================================= 1 passed in 0.09 seconds ================================= ~/pytest_experiment$ py.test --cov=my_script.py tests/test_in_tmpdir.py=================================== test session starts ==================================== platform linux2 -- Python 2.7.4 -- pytest-2.3.5 plugins: cov collected 1 items tests/test_in_tmpdir.py .Coverage.py warning: No data was collected. --------------------- coverage: platform linux2, python 2.7.4-final-0 ---------------------- Name Stmts Miss Cover --------------------------- ================================= 1 passed in 0.09 seconds ================================= 

Los archivos están aquí: https://gist.github.com/bilderbuchi/6412754

Edit: Interstingly, cuando se ejecutan las pruebas de cobertura con -s , también hay resultados más curiosos: la cobertura advierte que No data was collected , cuando obviamente se recostackron, y en la prueba tmpdir advierte que el Module my_script.py was never imported. ??

 ~/pytest_experiment$ py.test -s --cov=my_script.py tests/test_in_scriptdir.py =================================== test session starts ==================================== platform linux2 -- Python 2.7.4 -- pytest-2.3.5 plugins: cov collected 1 items tests/test_in_scriptdir.py set_up: In directory /tmp/pytest-63/test_10 Running in directory /home/cbuchner/pytest_experiment Command: ./my_script.py /tmp/pytest-63/test_10/arg_file.txt --Contents of arg_file.txt-- Coverage.py warning: No data was collected. . --------------------- coverage: platform linux2, python 2.7.4-final-0 ---------------------- Name Stmts Miss Cover ------------------------------- my_script 3 0 100% ================================= 1 passed in 0.09 seconds ================================= ~/pytest_experiment$ py.test -s --cov=my_script.py tests/test_in_tmpdir.py=================================== test session starts ==================================== platform linux2 -- Python 2.7.4 -- pytest-2.3.5 plugins: cov collected 1 items tests/test_in_tmpdir.py set_up: In directory /tmp/pytest-64/test_10 Running in directory /tmp/pytest-64/test_10 Command: /home/cbuchner/pytest_experiment/my_script.py arg_file.txt --Contents of arg_file.txt-- Coverage.py warning: Module my_script.py was never imported. Coverage.py warning: No data was collected. Coverage.py warning: Module my_script.py was never imported. Coverage.py warning: No data was collected. .Coverage.py warning: No data was collected. --------------------- coverage: platform linux2, python 2.7.4-final-0 ---------------------- Name Stmts Miss Cover --------------------------- ================================= 1 passed in 0.09 seconds ================================= 

Encontré el mismo problema al llamar “py.test –cov …” desde tox. Encontré una pista en esta página: http://blog.ionelmc.ro/2014/05/25/python-packaging/ , aunque no menciona esto explícitamente. El uso de “–develop” para tox se asegurará de que la recostackción de datos de cobertura se llame desde el mismo directorio que el análisis de cobertura. Esta sección en tox.ini hizo que me funcionara tener un entorno de prueba para la cobertura:

 [tox] envlist = ...,py34,cov [testenv:cov] # necessary to make cov find the .coverage file # see http://blog.ionelmc.ro/2014/05/25/python-packaging/ usedevelop = true commands = py.test --cov= deps = pytest pytest-cov 

Esto resultó ser un problema de rutas relativas que confunden la cobertura cuando el script medido se ejecuta desde otro directorio. Los archivos de resultados de cobertura terminaron en ese directorio, en lugar del directorio raíz del proyecto.

Para resolver esto, dejé de usar pytest-cov , y en su lugar usé coverage pura. Usé rutas completas en lugar de rutas relativas donde sea relevante.

Entonces, por ejemplo, defina la variable de entorno necesaria para habilitar la cobertura de subproceso a través de la export COVERAGE_PROCESS_START=/full/path/to/.coveragerc . En .coveragerc , el archivo de resultados de cobertura se especifica a través de

  [run] data_file = /full/path/to/.coverage 

y cualquier --source e --include debe usar rutas completas. Entonces fue posible obtener la medición correcta de la cobertura.

Otra opción con tox es configurar PYTHONPATH en tox.ini :

[testenv] setenv = PYTHONPATH = {toxinidir} commands = pytest --cov= - codecov