如何断言 Unittest 上的可迭代对象不为空?
Posted
技术标签:
【中文标题】如何断言 Unittest 上的可迭代对象不为空?【英文标题】:How to assert that an iterable is not empty on Unittest? 【发布时间】:2016-01-17 22:08:17 【问题描述】:向服务提交查询后,我得到了一个字典或列表,我想确保它不为空。我使用 Python 2.7。
我很惊讶unittest.TestCase
类实例没有任何 assertEmpty
方法。
现有的替代品看起来不太对:
self.assertTrue(bool(d))
self.assertNotEqual(d,)
self.assertGreater(len(d),0)
Python unittest 框架中是否缺少这种方法?如果是,那么断言可迭代对象不为空的最pythonic 方式是什么?
【问题讨论】:
***.com/questions/53513/… 可能会有所帮助。 好链接!我知道如何测试可迭代对象是否为空;正在寻找专门的 unittest 断言方法......很惊讶没有 assertEmpty/assertNotEmpty 方法 - 恕我直言,它会大大提高可读性,而不是在代码周围都有 assertTrue 和 assertFalse...... 同意,只是觉得assertTrue
可能更干净一点。我认为我个人的偏好(也许是最具语义意义的选项)是断言 len != 0。我同意 assertEmpty/assertNotEmpty 方法在 unittest 框架中占有一席之地。
请注意,“iterable”比“lists or dictionaries”大得多,如果不实际迭代,一般无法判断可迭代对象是否为空。
【参考方案1】:
Python 中的“假”值
假(有时写成假)值是在布尔上下文中遇到时被认为是假的值。
根据official doc,以下内置类型评估为假:
定义为假的常量:None
和 False
。
任何数字类型的零:0
、0.0
、0j
、Decimal(0)
、Fraction(0, 1)
空序列和集合:''
、()
、[]
、
、set()
、range(0)
因此,可以检查
non-emptiness withassertTrue()
and for
空虚与assertFalse()
。
(官方文档有所有可用assert methods的完整列表。)
清理代码
所有这些 assertTrue()
和 assertFalse()
调用都具有误导性,因为我们想检查是否为空,并且需要知道哪些类型评估为 false
才能正确理解测试中发生的情况。
所以,为了简洁的代码和更好的可读性,我们可以像这样简单地定义自己的assertEmpty()
和assertNotEmpty()
方法:
def assertEmpty(self, obj):
self.assertFalse(obj)
def assertNotEmpty(self, obj):
self.assertTrue(obj)
【讨论】:
在例如一个标量或对象被意外传递了? @Merk 是的,你是对的。但是,如果您仅出于私人原因使用这些辅助函数,那应该没问题,因为您知道这些函数的作用。如果此代码打算与其他开发人员一起在一个小项目中,您可能需要添加一些文档字符串来解释它的安全使用,或者只是正确地重命名函数(例如assert_list_empty(self, a_list)
)。或者,如果您打算将这些函数添加到您的第三方测试库中,只需添加一些代码以确保您处理所有可能的输入(通过添加 if ... elif ... else ...
和实例检查)【参考方案2】:
根据@winklerr 的回答和@Merk 的评论,我首先扩展了检查给定对象是否为Container
的想法。
from typing import Container
def assertContainerEmpty(self, obj: Container) -> None:
"""Asserts whether the given object is an empty container."""
self.assertIsInstance(obj, Container)
self.assertFalse(obj)
def assertContainerNotEmpty(self, obj: Container) -> None:
"""Asserts whether the given object is a non-empty container."""
self.assertIsInstance(obj, Container)
self.assertTrue(obj)
这意味着assertEmpty
和assertNotEmpty
如果给定对象是例如float
,或用户定义类的实例 - 无论它是否会正确评估为 True
/False
。
【讨论】:
【参考方案3】:这一切都归功于 winklerrr,我只是在扩展他的想法:在需要 assertEmpty 或 assertNotEmpty 时使用可导入的 mixin:
class AssertEmptyMixin( object ):
def assertEmpty(self, obj):
self.assertFalse(obj)
class AssertNotEmptyMixin( object ):
def assertNotEmpty(self, obj):
self.assertTrue(obj)
注意,mixin 应该放在左边:
class MyThoroughTests( AssertNotEmptyMixin, TestCase ):
def test_my_code( self ):
...
self.assertNotEmpty( something )
【讨论】:
【参考方案4】:也许:
self.assertRaises(StopIteration, next(iterable_object))
【讨论】:
一般来说这并不理想,因为它可能会消耗您随后需要查看的项目。 最好的一个班轮,因为它甚至适用于发电机。如果您正在测试一个空的可迭代对象,则不需要查看它的项目。 那不会捕获异常,你需要把它放在一个函数中。【参考方案5】:完全取决于您在寻找什么。
如果你想确保对象是一个可迭代对象并且它不为空:
# TypeError: object of type 'NoneType' has no len()
# if my_iterable is None
self.assertTrue(len(my_iterable))
如果被测试的对象可以是None
:
self.assertTrue(my_maybe_iterable)
【讨论】:
【参考方案6】:空列表/字典评估为 False,因此 self.assertTrue(d)
完成工作。
【讨论】:
对。那么在 unittest 中没有断言方法可以检查空虚吗?在代码中到处都有 assertTrue 和 assertFalse 很烦人... 没有断言方法来检查是否为空 - unittest. 这行得通,但不符合最小意外原则,通常在单元测试中清晰胜过简洁。以上是关于如何断言 Unittest 上的可迭代对象不为空?的主要内容,如果未能解决你的问题,请参考以下文章