pytest:测试之间的完全清理
pytest: full cleanup between tests
在一个模块中,我有两个测试:
@pytest.fixture
def myfixture(request):
prepare_stuff()
yield 1
clean_stuff()
# time.sleep(10) # in doubt, I tried that, did not help
def test_1(myfixture):
a = somecode()
assert a==1
def test_2(myfixture):
b = somecode()
assert b==1
案例 1
当这两个测试单独执行时,一切正常,即两者
pytest ./test_module.py:test_1
紧接着:
pytest ./test_module.py:test_2
运行直到完成并成功通过。
案例 2
但是:
pytest ./test_module.py -k "test_1 or test_2"
报告:
collected 2 items
test_module.py .
并永远挂起(调查后:test_1
成功完成,但第二次调用 prepare_stuff
挂起)。
问题
在我的特定设置中,prepare_stuff
、clean_stuff
和 somecode
已经相当先进,即它们创建和删除一些共享内存段,如果操作不当,可能会导致一些挂起。所以这里可能会出现一些问题。
但我的问题是:在 pytest
的两次调用(情况 1)之间是否发生了某些事情,而这些事情不会发生在来自同一个 test_1
和 test_2
的调用之间? pytest 过程”(案例 2),这可以解释为什么“案例 1”工作正常而“案例 2”挂在 test_1
和 test_2
之间?如果是这样,对于“案例 2”,有没有办法“强制”在 test_1
和 test_2
之间发生相同的“清理”?
注意:我已经尝试将“myfixture”的范围指定为“function”,并且还仔细检查了“clean_stuff”是在“test_1”之后调用的,即使在“case”中也是如此2".
myfixture
保证 cleanup()
的当前结构在 test_1
和 test_2
之间调用,除非 prepare_stuff()
引发未处理的异常。您可能会注意到这一点,所以最有可能的问题是 cleanup()
没有“清理” prepare_stuff()
所做的一切,因此 prepare_stuff()
无法再次设置。
至于您的问题,没有任何 pytest
相关的问题会导致测试之间的挂起。您可以通过添加 finalizer 强制调用 cleanup()
(即使引发异常),它将在拆解部分
之后调用
@pytest.fixture
def myfixture(request):
request.addfinalizer(cleanup)
prepare_stuff()
yield 1
它必须是 prepare_stuff
、clean_stuff
或 somecode
上的内容,因为如果您用伪代码替换这些方法,它就可以工作!
def prepare_stuff():
logging.warning("prepare_stuff()")
def clean_stuff():
logging.warning("clean_stuff()")
def somecode():
logging.warning("somecode()")
return 0
/tmp/tmp.JOfTxVUv1z via v3.8.10 (.env)
❯ pytest ./test_module.py -k "test_1 or test_2"
============================= test session starts ==============================
platform linux -- Python 3.8.10, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /tmp/tmp.JOfTxVUv1z
collected 2 items
test_module.py FF [100%]
=================================== FAILURES ===================================
____________________________________ test_1 ____________________________________
myfixture = 1
def test_1(myfixture):
a = somecode()
> assert a==1
E assert 0 == 1
test_module.py:25: AssertionError
------------------------------ Captured log setup ------------------------------
WARNING root:test_module.py:5 prepare_stuff()
------------------------------ Captured log call -------------------------------
WARNING root:test_module.py:13 somecode()
---------------------------- Captured log teardown -----------------------------
WARNING root:test_module.py:9 clean_stuff()
____________________________________ test_2 ____________________________________
myfixture = 1
def test_2(myfixture):
b = somecode()
> assert b==1
E assert 0 == 1
test_module.py:29: AssertionError
------------------------------ Captured log setup ------------------------------
WARNING root:test_module.py:5 prepare_stuff()
------------------------------ Captured log call -------------------------------
WARNING root:test_module.py:13 somecode()
---------------------------- Captured log teardown -----------------------------
WARNING root:test_module.py:9 clean_stuff()
=========================== short test summary info ============================
FAILED test_module.py::test_1 - assert 0 == 1
FAILED test_module.py::test_2 - assert 0 == 1
============================== 2 failed in 0.03s ===============================
/tmp/tmp.JOfTxVUv1z via v3.8.10 (.env)
您的 prepare_stuff
and/or clean_stuff
函数中可能发生了某些事情。当您 运行 测试为:
pytest ./test_module.py -k "test_1 or test_2"
它们 运行 在相同的执行上下文、相同的进程等中运行。因此,例如,如果 clean_stuff
没有进行适当的清理,则执行下一个测试会失败。当您 运行 测试为:
pytest ./test_module.py:test_1
pytest ./test_module.py:test_2
它们 运行 在不同的执行上下文中运行,即它们在绝对干净的环境中启动,并且,除非您要修改一些外部资源,否则在这种情况下您可以轻松删除 clean_stuff
他们无论如何都会过去。
要排除 pytest
问题,只需尝试 运行:
prepare_stuff()
a = somecode()
assert a==1
clean_stuff()
prepare_stuff()
b = somecode()
assert b==1
clean_stuff()
我很确定你会遇到同样的问题,这将确认问题出在你的代码中,而不是在 pytest
。
在一个模块中,我有两个测试:
@pytest.fixture
def myfixture(request):
prepare_stuff()
yield 1
clean_stuff()
# time.sleep(10) # in doubt, I tried that, did not help
def test_1(myfixture):
a = somecode()
assert a==1
def test_2(myfixture):
b = somecode()
assert b==1
案例 1
当这两个测试单独执行时,一切正常,即两者
pytest ./test_module.py:test_1
紧接着:
pytest ./test_module.py:test_2
运行直到完成并成功通过。
案例 2
但是:
pytest ./test_module.py -k "test_1 or test_2"
报告:
collected 2 items
test_module.py .
并永远挂起(调查后:test_1
成功完成,但第二次调用 prepare_stuff
挂起)。
问题
在我的特定设置中,prepare_stuff
、clean_stuff
和 somecode
已经相当先进,即它们创建和删除一些共享内存段,如果操作不当,可能会导致一些挂起。所以这里可能会出现一些问题。
但我的问题是:在 pytest
的两次调用(情况 1)之间是否发生了某些事情,而这些事情不会发生在来自同一个 test_1
和 test_2
的调用之间? pytest 过程”(案例 2),这可以解释为什么“案例 1”工作正常而“案例 2”挂在 test_1
和 test_2
之间?如果是这样,对于“案例 2”,有没有办法“强制”在 test_1
和 test_2
之间发生相同的“清理”?
注意:我已经尝试将“myfixture”的范围指定为“function”,并且还仔细检查了“clean_stuff”是在“test_1”之后调用的,即使在“case”中也是如此2".
myfixture
保证 cleanup()
的当前结构在 test_1
和 test_2
之间调用,除非 prepare_stuff()
引发未处理的异常。您可能会注意到这一点,所以最有可能的问题是 cleanup()
没有“清理” prepare_stuff()
所做的一切,因此 prepare_stuff()
无法再次设置。
至于您的问题,没有任何 pytest
相关的问题会导致测试之间的挂起。您可以通过添加 finalizer 强制调用 cleanup()
(即使引发异常),它将在拆解部分
@pytest.fixture
def myfixture(request):
request.addfinalizer(cleanup)
prepare_stuff()
yield 1
它必须是 prepare_stuff
、clean_stuff
或 somecode
上的内容,因为如果您用伪代码替换这些方法,它就可以工作!
def prepare_stuff():
logging.warning("prepare_stuff()")
def clean_stuff():
logging.warning("clean_stuff()")
def somecode():
logging.warning("somecode()")
return 0
/tmp/tmp.JOfTxVUv1z via v3.8.10 (.env)
❯ pytest ./test_module.py -k "test_1 or test_2"
============================= test session starts ==============================
platform linux -- Python 3.8.10, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /tmp/tmp.JOfTxVUv1z
collected 2 items
test_module.py FF [100%]
=================================== FAILURES ===================================
____________________________________ test_1 ____________________________________
myfixture = 1
def test_1(myfixture):
a = somecode()
> assert a==1
E assert 0 == 1
test_module.py:25: AssertionError
------------------------------ Captured log setup ------------------------------
WARNING root:test_module.py:5 prepare_stuff()
------------------------------ Captured log call -------------------------------
WARNING root:test_module.py:13 somecode()
---------------------------- Captured log teardown -----------------------------
WARNING root:test_module.py:9 clean_stuff()
____________________________________ test_2 ____________________________________
myfixture = 1
def test_2(myfixture):
b = somecode()
> assert b==1
E assert 0 == 1
test_module.py:29: AssertionError
------------------------------ Captured log setup ------------------------------
WARNING root:test_module.py:5 prepare_stuff()
------------------------------ Captured log call -------------------------------
WARNING root:test_module.py:13 somecode()
---------------------------- Captured log teardown -----------------------------
WARNING root:test_module.py:9 clean_stuff()
=========================== short test summary info ============================
FAILED test_module.py::test_1 - assert 0 == 1
FAILED test_module.py::test_2 - assert 0 == 1
============================== 2 failed in 0.03s ===============================
/tmp/tmp.JOfTxVUv1z via v3.8.10 (.env)
您的 prepare_stuff
and/or clean_stuff
函数中可能发生了某些事情。当您 运行 测试为:
pytest ./test_module.py -k "test_1 or test_2"
它们 运行 在相同的执行上下文、相同的进程等中运行。因此,例如,如果 clean_stuff
没有进行适当的清理,则执行下一个测试会失败。当您 运行 测试为:
pytest ./test_module.py:test_1
pytest ./test_module.py:test_2
它们 运行 在不同的执行上下文中运行,即它们在绝对干净的环境中启动,并且,除非您要修改一些外部资源,否则在这种情况下您可以轻松删除 clean_stuff
他们无论如何都会过去。
要排除 pytest
问题,只需尝试 运行:
prepare_stuff()
a = somecode()
assert a==1
clean_stuff()
prepare_stuff()
b = somecode()
assert b==1
clean_stuff()
我很确定你会遇到同样的问题,这将确认问题出在你的代码中,而不是在 pytest
。