проблема конфигурации pytest (переход от тестов носа (71 сек) к pytest (1536 сек)) - PullRequest
1 голос
/ 29 апреля 2019

Проблема:

pytest (определяется политикой) для запуска того же набора тестов (585 тестов), что и nosetest , который выполняется за 71 секунду, требуется 1536 секунд.

Файлы pytest.ini:

[pytest]
python_files = tests_*.py *_tests.py
norecursedirs = .idea  (pycharm env).
testpaths = tests

И файл помещается в корень проекта:

root
 |-+ mod1
 | |-- core.py
 | |-- utils.py
 |-+ mod2
 | |-- core.py
 | |-- utils2.py
 |-+ tests
 | |-- test_mod1
 | |-- test_mod2
 |-+ utils (don't test).
 | |-- u1.py
 | |-- u2.py
 |- pytest.ini
 |- readme.md

Вещи, которые я проверял (следуя советам из 14 других сообщений SO):

  • Количество Проходов / неудач одинаково.
  • При индивидуальном запуске тестов с помощью pytests они занимают ~ 20 мс.
  • При запуске папки с pytests 10-20 тестов занимают 14-15 секунд.
  • В тестовом наборе есть одно окружение, в котором нет волшебства env или os. Просто много технической логики.
  • Каждый файл test_xyz.py имеет свои собственные изолированные def setup и def teardown, которые создают / отбрасывают базу данных sqlite. Тесты взаимодействуют с базой данных, добавляя новые транзакции и проверяя дополнения. Пример:
global db

def setup():
   db = get_new_db()

def teardown():
   pass

def test_01():
   w = Widget(db)  # create widget instance.
   w.add_friend('a@b.com')
   assert 'a@b.com' in w.friends()

Вопросы:

  1. Действительно ли мне нужно штукатурить @ pytest.fixtures (scope = 'module') на setup и teardown каждых 585 тестов? Я надеюсь, что нет.

  2. Что я могу сделать, чтобы время выполнения pytest было похоже на nosetests?

1 Ответ

1 голос
/ 04 мая 2019

Я не уверен, почему pytest решил вызывать функцию настройки модуля в хуке pytest_runtest_setup, который запускается один раз для каждого теста, а не в модульном модуле autouse, но здесь это :

@hookimpl(trylast=True)
def pytest_runtest_setup(item):
    if is_potential_nosetest(item):
        if not call_optional(item.obj, "setup"):
            # call module level setup if there is no object level one
            call_optional(item.parent.obj, "setup")
        # XXX this implies we only call teardown when setup worked
        item.session._setupstate.addfinalizer((lambda: teardown_nose(item)), item)

Это означает, что вам нужно переименовать функции настройки / демонтажа в setup_module() / teardown_module().Если вы используете Linux / MacOS, вы можете использовать sed в сочетании с grep для пакетного переименования:

$ grep -lr "\(def setup():\|def teardown():\)" | \
  xargs sed -i 's/def setup():/def setup_module():/g;s/def teardown():/def teardown_module():/g'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...