Python 单元测试:assertTrue 是真值,assertFalse 是假值
创始人
2024-03-01 18:14:13
0

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

定义

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

assertTrue(expr, msg=None)

assertFalse(expr, msg=None)

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

注:这等价于

bool(expr) is True

而不等价于

expr is True

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

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

在一个布尔值的上下文环境中能变成“真”的值

在 Python 中等价于:

bool(expr) is True

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

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

在实践中怎么理解?

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

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

import unittest
from func import always_true

class TestAlwaysTrue(unittest.TestCase):
    def test_assertTrue(self):
        """
        always_true returns a truthy value
        """
        result = always_true()

        self.assertTrue(result)

    def test_assertIs(self):
        """
        always_true returns True
        """
        result = always_true()

        self.assertIs(result, True)

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

def always_true():
    """
    I'm always True.

    Returns:
        bool: True
    """
    return True

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

always_true returns True ... ok
always_true returns a truthy value ... ok

----------------------------------------------------------------------
Ran 2 tests in 0.004s

OK

开心ing~

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

def always_true():
    """
    I'm always True.

    Returns:
        bool: True
    """
    return 'True'

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

这次结果并不如开心了:

always_true returns True ... FAIL
always_true returns a truthy value ... ok

======================================================================
FAIL: always_true returns True
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/assertttt/test.py", line 22, in test_is_true
    self.assertIs(result, True)
AssertionError: 'True' is not True

----------------------------------------------------------------------
Ran 2 tests in 0.004s

FAILED (failures=1)

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

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

使用断言的辅助方法

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

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

def assertIsTrue(self, value):
    self.assertIs(value, True)

def assertIsFalse(self, value):
    self.assertIs(value, False)

总结

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

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

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

测试开心!


via: http://jamescooke.info/python-unittest-asserttrue-is-truthy-assertfalse-is-falsy.html

作者:James Cooke 译者:chunyang-wen 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

相关内容

不支持使用INSERT/S...
要解决不支持使用INSERT/SELECT INTO语法的存储过程...
2025-01-12 00:00:19
不要将Java模块中的单元...
在Java模块中,我们应该将单元测试代码放在与主代码不同的包中,并...
2025-01-10 19:32:05
不需要转换返回类型的单元测...
在编写单元测试时,有时候需要测试返回类型为IHttpActionR...
2025-01-10 16:31:40
不同的单元测试覆盖分支使用...
解决方法如下:import osimport unittestcl...
2025-01-08 13:01:25
不使用 testthat ...
在不使用testthat进行单元测试的情况下,可以使用其他方式来进...
2024-12-28 08:00:44
不确定在哪里添加单元测试
在确定在哪里添加单元测试时,可以按照以下步骤进行解决:确定要测试的...
2024-12-28 00:31:05

热门资讯

Helix:高级 Linux ... 说到 基于终端的文本编辑器,通常 Vim、Emacs 和 Nano 受到了关注。这并不意味着没有其他...
使用 KRAWL 扫描 Kub... 用 KRAWL 脚本来识别 Kubernetes Pod 和容器中的错误。当你使用 Kubernet...
JStock:Linux 上不... 如果你在股票市场做投资,那么你可能非常清楚投资组合管理计划有多重要。管理投资组合的目标是依据你能承受...
Epic 游戏商店现在可在 S... 现在可以在 Steam Deck 上运行 Epic 游戏商店了,几乎无懈可击! 但是,它是非官方的。...
《Apex 英雄》正式可在 S... 《Apex 英雄》现已通过 Steam Deck 验证,这使其成为支持 Linux 的顶级多人游戏之...
从 Yum 更新中排除特定/某... 作为系统更新的一部分,你也许需要在基于 Red Hat 系统中由于应用依赖排除一些软件包。如果是,如...
通过 SaltStack 管理... 我在搜索Puppet的替代品时,偶然间碰到了Salt。我喜欢puppet,但是我又爱上Salt了:)...
如何在 Github 上创建一... 学习如何复刻一个仓库,进行更改,并要求维护人员审查并合并它。你知道如何使用 git 了,你有一个 G...
Opera 浏览器内置的 VP... 昨天我们报道过 Opera 浏览器内置了 VPN 服务,用户打开它可以防止他们的在线活动被窥视。不过...
如何检查你的 Linux 系统... 不知道在使用哪个初始化系统?以下是方法。每个主流 Linux 发行版(包括 Ubuntu、Fedor...