Python单元测试成功断言None为False。

8
为什么 assertFalseNone 上成功呢?
import unittest

class TestNoneIsFalse(unittest.TestCase):
    def test_none_is_false(self):
        self.assertFalse(None)

结果:

> python -m unittest temp
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

看起来这种行为会引发函数不总是返回值的错误。例如:

def is_lower_than_5(x):
    if x < 5:
        return True
    elif x > 5:
        return False

....

def test_5_is_not_lower_than_5(self):
   self.assertFalse(is_lower_than_5(5))

上面的测试即使应该失败也会通过。代码中缺少一个应该被捕获的错误。
我们应该如何断言该值确实为“False”,而不仅仅是布尔上下文中的false?例如:
self.assertEquals(False, None)  # assert fails. good!

我会说你的测试揭示了函数中的一个错误。如果 x 是 5,它应该返回 False,因为 5 不小于 5。 - chepner
很不幸,看起来我必须使用 assertIs(... False) 来发现这个 bug。使用 assertFalse 测试是通过的。 - icedtrees
一个更好的想法是,如果你需要三种可能的返回值区分,就不要使用True和False。考虑使用0、正整数和负整数(如cmp),然后使用assertEqualassertLessassertGreater - chepner
这不是说明你的函数已经完美地工作了吗?如果你在代码的其他地方有 if it_lower_than_five(number):,由于 None 是假值,正确的行为将会发生。如果你真的需要返回值实际上是 TrueFalse,那么你应该在测试中更加具体。 - jonrsharpe
@jonrsharpe 谢谢你的建议!你说得对,我不一定需要返回值是True或False,但我个人认为在这种情况下使用assertIs更可取,以防止未来由于缺少x == 5导致的可能维护问题。 - icedtrees
3个回答

11

None是假值,以及0""[]等。

assertFalse不通过身份检查来检查给定值是否为False。这种行为与if语句一致:

if not None:
    print('falsy value!')
同样地,assertTrue不检验一个值是否为True,因此像1"abc"[1,2,3]这样的值也能通过测试。请参见Truth Value Testing了解更多信息。
这种行为也有明确记录在案
assertTrue(expr, msg=None)
assertFalse(expr, msg=None)

测试 expr 是否为 true(或 false)。

注意,这相当于 bool(expr) is True 而不是 expr is True

如果您真的想确定一个值是True还是False,请使用assertIs

1
我不喜欢它,但我想我必须接受它。对于未来的vim用户:%s/assert\(True\|False\)(\(.*\))/assertIs(\2, \1)/ - icedtrees

2

0

Python函数的默认返回值是None

Python还实现了鸭子类型,因此一些值被视为假值,这些值包括:

  • 空字符串
  • 整数零
  • 布尔值False
  • 空列表
  • 空元组

所以,如果您想显式检查False布尔值,则应将其实现为self.assertEquals(False, None)。但这不是一个好主意,在Python中,您可以直接执行以下操作:

if my_value:
    print 'truthy value'
else:
    print 'falsey value'

你可以使用边界值分析设计测试用例来检查你的边缘情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接