问题
The problem:
pytest (decided by policy) takes 1536 seconds to run the same test suite (585 tests) as nosetest, which runs in 71 seconds.
The pytest.ini
files is:
[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
Things I've checked (following advice from the 14 other SO posts):
- 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('a@b.com')
assert 'a@b.com' in w.friends()
Questions:
Do I really have to plaster @pytest.fixtures(scope='module') on the
setup
andteardown
of every 585 tests? I hope not.What can I do to get the runtime of
pytest
to be similar tonosetests
?
回答1:
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)
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'
来源:https://stackoverflow.com/questions/55904597/pytest-configuration-problem-transition-from-nosetests-71-sec-to-pytest-1536