如何正确使用单元测试的 assertRaises() 和 NoneType 对象? [复制]
Posted
技术标签:
【中文标题】如何正确使用单元测试的 assertRaises() 和 NoneType 对象? [复制]【英文标题】:How to properly use unit-testing's assertRaises() with NoneType objects? [duplicate] 【发布时间】:2011-08-31 12:31:55 【问题描述】:我做了一个简单的测试用例:
def setUp(self):
self.testListNone = None
def testListSlicing(self):
self.assertRaises(TypeError, self.testListNone[:1])
我期待测试通过,但我遇到了异常:
Traceback (most recent call last):
self.assertRaises(TypeError, self.testListNone[:1])
TypeError: 'NoneType' object is unsubscriptable
我认为 assertRaises 会通过,因为 TypeError 异常会 被抚养?
【问题讨论】:
ongspxm.github.io/blog/2016/11/… 你可以参考这个文档,因为他/她已经解释了为什么使用 lambda/context manager 来包装代码 【参考方案1】:如果您使用的是 python2.7 或更高版本,您可以使用assertRaises 的功能作为上下文管理器并执行以下操作:
with self.assertRaises(TypeError):
self.testListNone[:1]
如果您正在使用python2.6,除了到目前为止给定的方法之外的另一种方法是使用unittest2,它是python2.6的unittest新功能的后端口,您可以使用上面的代码使其工作。
N.B:我非常喜欢 unittest 的新功能(SkipTest、测试发现...),所以我打算尽可能多地使用 unittest2。我建议也这样做,因为在 python2.6 中,unittest 的功能远不止这些 <.>
【讨论】:
2.7 或更高版本 .. 你是在向我们隐藏 Python 2.8 吗? 您提到的代码似乎无法解决在断言比较之前结束脚本的问题。仍然没有通过测试(使用 python 3.10)【参考方案2】:问题是 TypeError
在调用 assertRaises
之前被提升,因为在调用方法之前需要评估 assertRaises
的参数。您需要传递一个lambda
表达式,例如:
self.assertRaises(TypeError, lambda: self.testListNone[:1])
【讨论】:
可能是最佳答案 你能帮我解决一个相关的问题吗? ***.com/questions/39909935/… @unutbu 的回答显示了如何调用assertRaises
(不需要 lambda)【参考方案3】:
assertRaises
的常用用法是调用函数:
self.assertRaises(TypeError, test_function, args)
测试函数调用 test_function(args) 是否引发 TypeError。
self.testListNone[:1]
的问题在于 Python 在调用 assertRaises
方法之前立即计算表达式。将test_function
和args
作为单独的参数传递给self.assertRaises
的全部原因是允许assertRaises
从try...except
块内调用test_function(args)
,从而允许assertRaises
捕获异常。
既然你已经定义了self.testListNone = None
,并且你需要一个函数来调用,你可以像这样使用operator.itemgetter:
import operator
self.assertRaises(TypeError, operator.itemgetter, (self.testListNone,slice(None,1)))
因为
operator.itemgetter(self.testListNone,slice(None,1))
self.testListNone[:1]
是一种冗长的说法,但它将函数 (operator.itemgetter
) 与参数分开。
【讨论】:
对于单个 assertRaises,这看起来是最好的答案。对于大量基于异常的测试(假设它们都具有相同的异常类型) with self.assertRaises(...) 将是一个不错的选择。 是的,这应该是正确的答案,因为它实际上解释了问题。 这绝对是正确的答案,它解释了问题。 你能帮我解决一个相关的问题吗? ***.com/questions/39909935/… +1 可以简化为self.assertRaises(TypeError, self.testListNone.__getitem__, slice(None,1))
,因为operator.itemgetter增加了一些小的无用复杂度。【参考方案4】:
完整的 sn-p 如下所示。它将@mouad 的答案扩展到断言错误消息(或通常str
表示其args
),这可能很有用。
from unittest import TestCase
class TestNoneTypeError(TestCase):
def setUp(self):
self.testListNone = None
def testListSlicing(self):
with self.assertRaises(TypeError) as ctx:
self.testListNone[:1]
self.assertEqual("'NoneType' object is not subscriptable", str(ctx.exception))
【讨论】:
以上是关于如何正确使用单元测试的 assertRaises() 和 NoneType 对象? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
用 Python 进行测试 - 如何在使用 unittest 的测试中使用 assertRaises? [复制]