Python单元测试:assertTrue是真值,assertFalse是假值

开发 测试
在这篇文章中,我们将介绍单元测试的布尔断言方法 assertTrue 和 assertFalse 与身份断言 assertIs 之间的区别。

[[174859]]

在这篇文章中,我们将介绍单元测试的布尔断言方法 assertTrue 和 assertFalse 与身份断言 assertIs 之间的区别。

定义

下面是目前单元测试模块文档中关于 assertTrue 和 assertFalse 的说明,代码进行了高亮:

assertTrue(expr, msg=None)

assertFalse(expr, msg=None)

测试该表达式是真值(或假值)。

注:这等价于

bool(expr) is True

而不等价于

expr is True

(后一种情况请使用 assertIs(expr, True))。

Mozilla 开发者网络中定义 真值 如下:

在一个布尔值的上下文环境中能变成“真”的值在 Python 中等价于:

  1. bool(expr) is True 

这个和 assertTrue 的测试目的完全匹配。

因此该文档中已经指出 assertTrue 返回真值,assertFalse 返回假值。这些断言方法从接受到的值构造出一个布尔值,然后判断它。同样文档中也建议我们根本不应该使用 assertTrue 和 assertFalse。

在实践中怎么理解?

我们使用一个非常简单的例子 - 一个名称为 always_true 的函数,它返回 True。我们为它写一些测试用例,然后改变代码,看看测试用例的表现。

作为开始,我们先写两个测试用例。一个是“宽松的”:使用 assertTrue 来测试真值。另外一个是“严格的”:使用文档中建议的 assertIs 函数。

  1. import unittest 
  2. from func import always_true 
  3. class TestAlwaysTrue(unittest.TestCase): 
  4.     def test_assertTrue(self): 
  5.         ""
  6.         always_true returns a truthy value 
  7.         ""
  8.         result = always_true() 
  9.         self.assertTrue(result) 
  10.     def test_assertIs(self): 
  11.         ""
  12.         always_true returns True 
  13.         ""
  14.         result = always_true() 
  15.         self.assertIs(result, True

下面是 func.py 中的非常简单的函数代码:

  1. def always_true(): 
  2.     ""
  3.     I'm always True
  4.     Returns
  5.         bool: True 
  6.     ""
  7.     return True 

当你运行时,所有测试都通过了:

  1. always_true returns True ... ok 
  2. always_true returns a truthy value ... ok 
  3. ---------------------------------------------------------------------- 
  4. Ran 2 tests in 0.004s 
  5. OK 

开心ing~

现在,某个人将 always_true 函数改变成下面这样:

  1. def always_true(): 
  2.     ""
  3.     I'm always True
  4.     Returns
  5.         bool: True 
  6.     ""
  7.     return 'True' 

它现在是用返回字符串 "True" 来替代之前反馈的 True (布尔值)。(当然,那个“某人”并没有更新文档 - 后面我们会增加难度。)

这次结果并不如开心了:

  1. always_true returns True ... FAIL 
  2. always_true returns a truthy value ... ok 
  3. ====================================================================== 
  4. FAIL: always_true returns True 
  5. ---------------------------------------------------------------------- 
  6. Traceback (most recent call last): 
  7.   File "/tmp/assertttt/test.py", line 22, in test_is_true 
  8.     self.assertIs(result, True
  9. AssertionError: 'True' is not True 
  10. ---------------------------------------------------------------------- 
  11. Ran 2 tests in 0.004s 
  12. FAILED (failures=1) 

只有一个测试用例失败了!这意味着 assertTrue 给了我们一个误判false-positive。在它不应该通过测试时,它通过了。很幸运的是我们第二个测试是使用 assertIs 来写的。

因此,跟手册上了解到的信息一样,为了保证 always_true 的功能和更严格测试的结果保持一致,应该使用assertIs 而不是 assertTrue。

使用断言的辅助方法

使用 assertIs 来测试返回 True 和 False 来冗长了。因此,如果你有个项目需要经常检查是否是返回了True 或者 False,那们你可以自己编写一些断言的辅助方法。

这好像并没有节省大量的代码,但是我个人觉得提高了代码的可读性。

  1. def assertIsTrue(self, value): 
  2.     self.assertIs(value, True
  3. def assertIsFalse(self, value): 
  4.     self.assertIs(value, False

总结

一般来说,我的建议是让测试越严格越好。如果你想测试 True 或者 False,听从文档的建议,使用assertIs。除非不得已,否则不要使用 assertTrue 和 assertFalse。

如果你面对的是一个可以返回多种类型的函数,例如,有时候返回布尔值,有时候返回整形,那么考虑重构它。这是代码的异味。在 Python 中,抛出一个异常比使用 False 表示错误更好。

此外,如果你确实想使用断言来判断函数的返回值是否是真,可能还存在第二个代码异味 - 代码是正确封装了吗?如果 assertTrue 和 assertFalse 是根据正确的 if 语句来执行,那么值得检查下你是否把所有你想要的东西都封装在合适的位置。也许这些 if 语句应该封装在测试的函数中。

测试开心!

责任编辑:庞桂玉 来源: Linux中国
相关推荐

2017-01-14 23:42:49

单元测试框架软件测试

2022-12-08 08:01:02

Python测试单元

2021-03-28 23:03:50

Python程序员编码

2017-01-14 23:26:17

单元测试JUnit测试

2017-01-16 12:12:29

单元测试JUnit

2010-03-04 15:40:14

Python单元测试

2020-08-18 08:10:02

单元测试Java

2017-03-23 16:02:10

Mock技术单元测试

2023-07-26 08:58:45

Golang单元测试

2021-05-05 11:38:40

TestNGPowerMock单元测试

2020-05-07 17:30:49

开发iOS技术

2011-07-04 18:16:42

单元测试

2021-09-27 13:02:05

Python技巧测试

2011-05-16 16:52:09

单元测试彻底测试

2012-05-17 09:09:05

Titanium单元测试

2009-09-25 10:33:25

Hibernate单元

2011-04-18 13:20:40

单元测试软件测试

2009-09-01 10:20:06

protected方法单元测试

2017-02-23 15:59:53

测试MockSetup

2020-09-30 08:08:15

单元测试应用
点赞
收藏

51CTO技术栈公众号