assertraises必须用上下文管理器或可调用对象:正确写法是with self.assertraises(valueerror): int('abc')或self.assertraises(valueerror, int, 'abc');捕获后可用as获取异常实例校验消息;仅捕获exception及其子类,systemexit是特例,keyboardinterrupt等不被捕获。

assertRaises 必须用上下文管理器或可调用对象,不能直接传表达式
很多人写 self.assertRaises(ValueError, int('abc')),结果测试直接失败——不是因为没抛错,而是因为这行代码在 assertRaises 调用前就执行了,int('abc') 立即抛出异常,导致测试函数根本进不到断言逻辑里。
正确做法只有两种:
- 用
with语句包裹待测代码:with self.assertRaises(ValueError):<br> int('abc') - 传入函数名和参数(不加括号):
self.assertRaises(ValueError, int, 'abc')
第二种方式本质是让 assertRaises 内部调用 int('abc'),从而捕获异常;第一种更直观、支持多行逻辑,也推荐优先使用。
捕获异常后想检查错误信息?用 as 语法取异常实例
assertRaises 默认只校验异常类型,不关心内容。如果要验证 ValueError('invalid literal for int()') 中的提示文字,必须拿到异常对象本身。
用 as 绑定变量即可:
with self.assertRaises(ValueError) as cm:<br> int('xyz')<br>self.assertIn('invalid literal', str(cm.exception))
注意:cm.exception 是实际抛出的异常实例,str() 或 .args[0] 才能访问消息内容;直接打印 cm 只会看到 _AssertRaisesContext 对象,没用。
测试自定义异常或带参数的异常类,传类名即可
无论异常是否带参数、是否继承自 Exception,只要它是类(而非实例),assertRaises 都能识别:
- 自定义异常:
class MyError(Exception): pass→ 断言用self.assertRaises(MyError) - 内置异常带参数:
raise KeyError('missing')→ 仍用self.assertRaises(KeyError),无需指定参数 - 不能传实例:
self.assertRaises(ValueError('oops'))是错的,会报TypeError: exceptions must be old-style classes or derived from BaseException
assertRaises 不捕获 KeyboardInterrupt 和 SystemExit
这是容易被忽略的边界行为:assertRaises 默认只捕获继承自 Exception 的异常,而 KeyboardInterrupt 和 SystemExit 直接继承自 BaseException,所以:
-
with self.assertRaises(KeyboardInterrupt): raise KeyboardInterrupt()→ 测试会崩溃退出,不会通过 - 真要测这类退出逻辑,得用
self.assertRaises(SystemExit)—— 它是特例,unittest 显式支持 - 其他
BaseException子类(如MemoryError)一般也不该在业务逻辑里主动抛,不建议强行覆盖测试
真正写业务时,99% 的错误路径都走 Exception 分支,但如果你在封装 CLI 工具并显式调用 sys.exit(),就得记得这个例外。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











