Python中如何在unittest断言失败时触发另一个方法函数?
在做自动化脚本开发,使用的 unittest 框架, 想在断言失败的时候截图。下面这个例子无论成功或失败都会触发指定的函数,请问怎么修改,只在失败的时候触发函数呢?
import unittest
class loginTests(unittest.TestCase):
@classmethod
def setUpClass(cls):
pass
@classmethod
def tearDownClass(cls):
pass
def aaa(self):
print('触发函数')
def test1(self):
i =2
self.assertEqual(i,1,self.aaa())
if name == ‘main’:
unittest.main()
Python中如何在unittest断言失败时触发另一个方法函数?
3 回复
在unittest里,断言失败会直接抛出AssertionError异常,导致测试方法立即停止。如果你想在断言失败后还能执行一些清理或记录操作,标准的做法是使用try...except块来捕获这个异常。
这里有个例子,展示了怎么在断言失败后调用一个自定义的on_assert_fail方法:
import unittest
class TestExample(unittest.TestCase):
def on_assert_fail(self, message):
"""断言失败后触发的自定义方法"""
print(f"断言失败了,信息是: {message}")
# 这里可以放你的逻辑,比如记录日志、清理资源等
# self.cleanup()
def test_something(self):
a = 5
b = 10
custom_msg = "a 应该等于 b"
try:
self.assertEqual(a, b, msg=custom_msg)
except AssertionError as e:
# 捕获到断言异常,先调用我们的自定义方法
self.on_assert_fail(str(e))
# 然后重新抛出异常,让unittest框架知道测试失败了
raise
if __name__ == '__main__':
unittest.main()
核心思路:
- 把可能失败的断言(比如
self.assertEqual)包在try块里。 - 在
except AssertionError块中,调用你的自定义函数(比如on_assert_fail),并把错误信息传给它。 - 关键一步:在自定义方法执行完后,用
raise把捕获到的异常原样抛出。这样unittest框架才能正确地将这次测试标记为“失败”(FAILED),而不是“出错”(ERROR)。如果你不重新抛出,测试会被错误地认为是“通过”的。
另一种更通用的写法(使用上下文管理器或装饰器):
如果很多测试方法都需要这个功能,写一堆 try...except 太麻烦。可以定义一个装饰器,这样代码更干净:
import unittest
import functools
def catch_assert_and_call(func):
"""装饰器:在断言失败后调用实例的 on_assert_fail 方法"""
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
try:
return func(self, *args, **kwargs)
except AssertionError as e:
if hasattr(self, 'on_assert_fail'):
self.on_assert_fail(str(e))
raise
return wrapper
class TestExampleWithDecorator(unittest.TestCase):
def on_assert_fail(self, message):
print(f"[装饰器版] 断言失败: {message}")
@catch_assert_and_call
def test_with_decorator(self):
self.assertEqual(1, 2, msg="1 应该等于 2")
if __name__ == '__main__':
unittest.main()
总结:用 try…except 捕获 AssertionError,执行你的方法后再把异常抛出去。
try:
self.assertEqual(i,1)
except AssertionError as e:
self.aaa
self.assertEqueal(i,1)
你可以试试看。但是如果只做异常处理,这条用例会被认为正确执行了。
我是在 teardown 里判断用例是否执行失败,失败就截图

