问题描述
问题:
pytest(由政策决定)运行与 nosetest 相同的测试套件(585 个测试)需要 1536 秒,后者运行 71 秒.
pytest (decided by policy) takes 1536 seconds to run the same test suite (585 tests) as nosetest, which runs in 71 seconds.
pytest.ini
文件是:
[pytest]
python_files = tests_*.py *_tests.py
norecursedirs = .idea (pycharm env).
testpaths = tests
并将文件放在项目的根目录下:
And the file is placed at the root of the project:
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 帖子的建议):
Things I've checked (following advice from the 14 other SO posts):
- 通过/失败的数量是相同的.
- 当使用 pytests 单独运行测试时,它们需要大约 20 毫秒.
- 使用 pytests 运行文件夹时,10-20 个测试需要 14-15 秒.
- 测试套件有一个环境,没有 env 或 os 魔法.只是很多技术逻辑.
- 每个 test_xyz.py 文件都有自己独立的
def setup
和def teardown
,用于创建/删除 sqlite 数据库.测试通过添加新事务和检查添加内容与数据库交互.示例:
- The number of Pass/Fails is the same.
- When running the tests individually with pytests they take ~ 20ms.
- When running the folder with pytests 10-20 tests take 14-15 seconds.
- The test suite has one environment, there's no env or os magic. Just lots of technical logic.
- Each test_xyz.py file has it's own isolated
def setup
anddef teardown
that creates/drop an sqlite database. The tests interact with the database, by adding new transactions and checking the additions. Example:
global db
def setup():
db = get_new_db()
def teardown():
pass
def test_01():
w = Widget(db) # create widget instance.
w.add_friend('[email protected]')
assert '[email protected]' in w.friends()
问题:
我真的需要在每 585 次测试的
setup
和teardown
上贴上 @pytest.fixtures(scope='module') 吗?我希望不会.
Do I really have to plaster @pytest.fixtures(scope='module') on the
setup
andteardown
of every 585 tests? I hope not.
如何使 pytest
的运行时与 nosetests
类似?
What can I do to get the runtime of pytest
to be similar to nosetests
?
推荐答案
我不知道为什么 pytest
选择在 pytest_runtest_setup
钩子中调用模块设置函数每个测试运行一次而不是模块范围的自动使用装置,但是 这里是:
I'm not sure why pytest
chose to invoke the module setup function in a pytest_runtest_setup
hook that runs once per each test instead of a module-scoped autouse fixture, but here it is:
@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
进行批量重命名:
This means you'll need to rename the setup/teardown functions to setup_module()
/teardown_module()
. If you're on Linux/MacOS, you can use sed
combined with grep
for batch renaming:
$ grep -lr "\(def setup():\|def teardown():\)" | \
xargs sed -i 's/def setup():/def setup_module():/g;s/def teardown():/def teardown_module():/g'
这篇关于pytest 配置问题(从鼻子测试(71 秒)到 pytest(1536 秒)的转换)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!