如何正确使用单元测试的 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_functionargs 作为单独的参数传递给self.assertRaises 的全部原因是允许assertRaisestry...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? [复制]

使用assert在python中引发单元测试

Python unittest - 与assertRaises相反?

Argparse 单元测试:禁止显示帮助消息

灵魂拷问:到底要不要写单元测试,如何正确进行单元测试?

灵魂拷问:到底要不要写单元测试,如何正确进行单元测试?