python - 如果夹具设置或拆卸失败,有没有办法跳过 pytest?
问题描述
如果夹具的任何部分抛出异常,有没有办法跳过测试?我正在使用第三方夹具,该夹具在拆卸过程中会随机出错,因此我试图包装我的测试,以便在抛出随机错误时(注意:测试没有失败,夹具出错了) ,pytest
只是跳过测试。
这是一个最小的可重现示例:
import functools
import numpy as np
import pytest
def handle_fixture_errors(f):
"""decorator for wrapping test function in try/catch"""
@functools.wraps(f)
def wrapper(*args, **kwargs):
try:
print('about to run my test')
return f(*args, **kwargs)
print('never reached')
except Exception as e:
msg = 'Ignoring fixture exception ' + str(e)
pytest.skip(msg)
return wrapper
@pytest.fixture()
def failing_fixture(request):
"""fixture fails on teardown"""
x = np.linspace(10, 20, 100)
y = np.random.normal(size=(1000, 5))
def teardown():
print('fixture teardown is failing')
z = x.T.dot(y)
request.addfinalizer(teardown)
return x
@handle_fixture_errors
def test_matmul(failing_fixture):
"""original test function"""
print('hey this is my test')
k = failing_fixture
assert len(k) == 100
问题是测试本身没有抛出异常,它是抛出异常的夹具,所以try/catch
没有捕获测试的异常并防止“.E”导致测试摘要。我的测试输出仍然如下所示:
========================================================= ERRORS =========================================================
____________________________________________ ERROR at teardown of test_matmul ____________________________________________
def teardown():
print('fixture teardown is failing')
> z = x.T.dot(y)
E ValueError: shapes (100,) and (1000,5) not aligned: 100 (dim 0) != 1000 (dim 0)
test_fake.py:25: ValueError
-------------------------------------------------- Captured stdout call --------------------------------------------------
about to run my test
hey this is my test
------------------------------------------------ Captured stdout teardown ------------------------------------------------
fixture teardown is failing
================================================ short test summary info =================================================
ERROR test_fake.py::test_matmul - ValueError: shapes (100,) and (1000,5) not aligned: 100 (dim 0) != 1000 (dim 0)
=============================================== 1 passed, 1 error in 0.18s ===============================================
我不想跳过设置或拆除夹具,我只想让测试被完全“跳过”(或至少,静音或pass
编辑)。谢谢你的帮助!
解决方案
我认为跳过这样的测试是不合理的。要么你想要,要么你不想要!
如果你有间歇性测试(或者在这种情况下是固定装置),考虑重新运行它们,也许在短暂的延迟或一些检查之后(网络流量太高?在非高峰时间再试一次)
pytest 为此建议了一些看起来高质量的插件,并且可以在运行之间添加延迟等
https://docs.pytest.org/en/stable/flaky.html#plugins
如果您确切知道它将在哪里失败,请考虑在您的代码放弃或将控制权交回 pytest 之前自行重试几次,方法是在某个循环中设计您的逻辑
for _ in range(10): # attempt call 10 times
time.sleep(10) # yuck
try:
foo = flakey_call()
except Exception:
continue # failed: try again, consider different waits
if hasattr(foo, "bar"):
break # successfully got a valid foo
else: # did not find and break
raise Exception("the foo had no bar!")
也可以选择模拟第 3 方夹具(我会提醒您不要这样做,因为它可能导致夹具永远无法工作),或每次运行
设计一些逻辑来获得第 3 方逻辑的响应,可能会在夹具中重新运行它,直到它执行您想要的操作。
然后要么
- 将其序列化为对您有用的形式并将其保存以供将来运行(例如,如果它是一些数据收集,则为镶木地板)
- 腌制对象(我只会在有很多调用的单次运行中执行此操作,但现在只需要成功)
推荐阅读
- javascript - 检查表单是否填充了 jQuery
- css - 如何通过 src 设置图像标签的样式?
- c++ - istream_iterator( istream_type& stream ) 如果初始化两次则指向不同的值
- java - Java Json在保存时美化
- javascript - 正则表达式匹配中日字符
- php - PHP post 数组未完成。只收到第一个元素
- php - PHP代码片段无法创建文件
- android - Firebase perf:修改应用开始时间度量
- java - 使用在 SPARQL 查询内的查询字符串之外声明的变量 - 使用 JSP 和 Java Servlet
- php - 如何解决从 App Engine 生成的“等待太久以尝试为您的请求提供服务错误后请求被中止”