python unittest с отчетом о (под) процессах

Я использую nose для выполнения моих "модульных" тестов и nose-cov для включения отчетов о покрытии. Все они работают нормально, но часть моих тестов требует запуска некоторого кода как multiprocessing.Process. В nose-cov документах указано, что он может делать multiprocessing, но я не уверен, как заставить это работать.

Я просто запускаю тесты, запустив nosetests и используя следующие .coveragerc:

[run]
branch = True
parallel = True

[report]
# Regexes for lines to exclude from consideration
exclude_lines =
    # Have to re-enable the standard pragma
    pragma: no cover

    # Don't complain about missing debug-only code:
    def __repr__
    #if self\.debug

    # Don't complain if tests don't hit defensive assertion code:
    raise AssertionError
    raise NotImplementedError

    # Don't complain if non-runnable code isn't run:
    if 0:
    if __name__ == .__main__.:
    def __main__\(\):

omit =
    mainserver/tests/*

РЕДАКТИРОВАТЬ:

Я исправил переключатель parallel в моем файле ".coveragerc". Я также пробовал добавить такой sitecustomize.py в каталог моих сайтов:

import os
import coverage
os.environ['COVERAGE_PROCESS_START']='/sites/metrics_dev/.coveragerc'
coverage.process_startup()

Я почти уверен, что он по-прежнему не работает должным образом, потому что в отчете «об отсутствии» по-прежнему отображаются строки, которые, как я знаю, работают (они выводятся на консоль). Я также пробовал добавить переменную среды в свой файл тестового примера, а также в оболочку перед запуском тестовых примеров. Я также попытался явно вызвать те же самые вещи в функции, которая вызывается multiprocessing.Process, чтобы запустить новый процесс.


person Tim Tisdall    schedule 08.12.2014    source источник


Ответы (3)


Еще одна вещь, которую следует учитывать, - если вы видите более одного файла покрытия во время выполнения покрытия. Может, дело только в их последующем соединении.

person Drachenfels    schedule 10.06.2015
comment
К сожалению, я думаю, что получил только один файл. - person Tim Tisdall; 10.06.2015
comment
Не могли бы вы пройти полную командную строку, я пытаюсь решить аналогичную проблему. Однако мой кажется еще более сложным. Если найду что-нибудь полезное, выложу здесь. - person Drachenfels; 10.06.2015
comment
Извините, не помню ... Наверное, nosetests --with-coverage - person Tim Tisdall; 10.06.2015

Во-первых, вам нужен параметр конфигурации parallel, а не parallel-mode. Во-вторых, вам, вероятно, потребуется следовать инструкциям в разделе Измерение подпроцессов в файле покрытия .py документы

person Ned Batchelder    schedule 08.12.2014
comment
Командный переключатель для покрытия - --parallel-mode, поэтому я предположил, что он был в конфигурации. Спасибо, что указали на эту страницу, я посмотрю, смогу ли я заставить это работать. И спасибо за разработку такого замечательного инструмента для тестирования! - person Tim Tisdall; 09.12.2014
comment
пожалуйста, посмотрите мою правку выше ... Кажется, я все еще не могу заставить его работать. - person Tim Tisdall; 09.12.2014

tl; dr - чтобы использовать параметр coverage + nosetests + носа --processes, установите для параметра покрытия --concurrency значение multiprocessing, предпочтительно в .coveragerc или setup.cfg, а не в командной строке (см. также: использование командной строки и файлы конфигурации).


Длинная версия…

Я также боролся с этим некоторое время, следуя документации по Настройка Python для покрытия подпроцессов к письму. Наконец, при более внимательном рассмотрении вывода coverage run --help я наткнулся на параметр --concurrency=multiprocessing, который я никогда раньше не использовал и который, похоже, является недостающим звеном. (В ретроспективе это имеет смысл: параметр --processing в носу использует библиотеку multiprocessing под капотом.)

Вот минимальная конфигурация, которая работает должным образом:


unit.py:

def is_even(x):
    if x % 2 == 0:
        return True
    else:
        return False

test.py:

import time
from unittest import TestCase

import unit


class TestIsEvenTrue(TestCase):
    def test_is_even_true(self):
        time.sleep(1)  # verify multiprocessing is being used
        self.assertTrue(unit.is_even(2))


# use a separate class to encourage nose to use a separate process for this
class TestIsEvenFalse(TestCase):
    def test_is_even_false(self):
        time.sleep(1)
        self.assertFalse(unit.is_even(1))

setup.cfg:

[nosetests]
processes = 2
verbosity = 2

[coverage:run]
branch = True
concurrency = multiprocessing
parallel = True
source = unit

sitecustomize.py (примечание: находится в пакеты сайтов)

import os
try:
    import coverage
    os.environ['COVERAGE_PROCESS_START'] = 'setup.cfg'
    coverage.process_startup()
except ImportError:
    pass

$ coverage run $(command -v nosetests)
test_is_even_false (test.TestIsEvenFalse) ... ok
test_is_even_true (test.TestIsEvenTrue) ... ok

----------------------------------------------------------------------
Ran 2 tests in 1.085s

OK

$ coverage combine && coverage report
Name      Stmts   Miss Branch BrPart  Cover
-------------------------------------------
unit.py       4      0      2      0   100%
person Mark G.    schedule 18.09.2018