首页 > 解决方案 > pytest 配置问题(从nosetests(71 秒)到pytest(153​​6 秒)的过渡)

问题描述

问题:

pytest (由策略决定)需要 1536 秒来运行与nosetest相同的测试套件(585 个测试),后者在 71 秒内运行。

这些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 帖子的建议):

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. 我真的必须在每 585 次测试中setup涂抹@pytest.fixtures(scope='module')吗?teardown我希望不是。

  2. 我该怎么做才能使运行时pytest类似于nosetests

标签: pythonpython-3.xpytest

解决方案


我不确定为什么选择在每个测试运行一次pytest的钩子中调用模块设置函数,而不是模块范围的自动使用夹具,但这里是pytest_runtest_setup

@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/teardown 函数重命名为setup_module()/ teardown_module()。如果您使用的是 Linux/MacOS,则可以使用sed组合 withgrep进行批量重命名:

$ grep -lr "\(def setup():\|def teardown():\)" | \
  xargs sed -i 's/def setup():/def setup_module():/g;s/def teardown():/def teardown_module():/g'

推荐阅读