Подтвердить что ты не робот

Cover.py не распространяется на script, если py.test выполняет его из другого каталога

У меня есть python script, который принимает аргументы командной строки, работая с некоторыми файлами. Я пишу следующие тесты с py.test, помещая этот script через его шаги, выполняя его с помощью subprocess.call.

Теперь я хочу проанализировать покрытие кода с помощью coverage.py. Coverage, при использовании через плагин pytest-cov (который имеет встроенную подпроцессорную обработку) не видит/не закрывает мой script, когда он вызывается из временного каталога тестирования, созданного с помощью py.test tmpdir. Coverage видит мой script, когда он вызывает в каталоге, в котором он находится (и аргумент имени файла указывает на удаленный путь).

В обеих ситуациях мои тесты проходят! Покрытие 3.6, pytest-2.3.5, pytest-cov 1.6, все от PyPi.

Вопрос. Как получить покрытие для распознавания моего script, даже если оно выполнено в другом каталоге? Это ошибка в охвате или что-то, что просто невозможно сделать? Был бы удивлен, если последний, в конце концов, tmpdir является запасным механизмом py.test...

Минимальный пример:

Я получил script my_script.py, который просто перекликается с содержимым файла arg_file.txt, предоставленного с помощью аргумента командной строки. В двух разных тестах это один раз вызывается в tmpdir и один раз в script. Оба теста проходят, но в тесте tmpdir я не получаю информацию о покрытии!

Тестирование:

~/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 =================================

Покрытие:

~/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 =================================

Файлы находятся здесь: https://gist.github.com/bilderbuchi/6412754

Изменить: Интересно, что при запуске тестов покрытия с помощью -s тоже появляется более любопытный вывод - покрытие предупреждает, что No data was collected, когда он был собран, и в tmpdir test предупреждает, что 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 =================================
4b9b3361

Ответ 1

Это оказалось проблемой относительных путей, запутывающих покрытие, когда измеренный script запускается из другого каталога. Файлы результатов покрытия попали в этот каталог, а не в корневую директорию проекта.

Чтобы решить эту проблему, я остановился на использовании pytest-cov и вместо этого использовал чистый coverage. Я использовал полные пути вместо относительных путей везде, где это необходимо.

Так, например, определить переменную среды, необходимую для обеспечения охвата субпроцесса через export COVERAGE_PROCESS_START=/full/path/to/.coveragerc. В .coveragerc файл результата покрытия указан через

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

и любые опции --source и --include также должны использовать полные пути. Тогда было возможно получить правильное измерение покрытия.

Ответ 2

Я столкнулся с той же проблемой при вызове "py.test --cov..." от tox. Я нашел подсказку на этой странице: http://blog.ionelmc.ro/2014/05/25/python-packaging/, хотя она не упоминает об этом явно. Использование "--develop" для токсичных веществ гарантирует, что сбор данных о покрытии вызывается из того же каталога, что и анализ покрытия. Этот раздел в tox.ini заставил меня работать с тестовой средой для покрытия:

[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=<MODULE_NAME>
deps = pytest pytest-cov