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 上不... 如果你在股票市场做投资,那么你可能非常清楚投资组合管理计划有多重要。管理投资组合的目标是依据你能承受...
通过 SaltStack 管理... 我在搜索Puppet的替代品时,偶然间碰到了Salt。我喜欢puppet,但是我又爱上Salt了:)...
Epic 游戏商店现在可在 S... 现在可以在 Steam Deck 上运行 Epic 游戏商店了,几乎无懈可击! 但是,它是非官方的。...
《Apex 英雄》正式可在 S... 《Apex 英雄》现已通过 Steam Deck 验证,这使其成为支持 Linux 的顶级多人游戏之...
如何在 Github 上创建一... 学习如何复刻一个仓库,进行更改,并要求维护人员审查并合并它。你知道如何使用 git 了,你有一个 G...
2024 开年,LLUG 和你... Hi,Linuxer,2024 新年伊始,不知道你是否已经准备好迎接新的一年~ 2024 年,Lin...
什么是 KDE Connect... 什么是 KDE Connect?它的主要特性是什么?它应该如何安装?本文提供了基本的使用指南。科技日...
Opera 浏览器内置的 VP... 昨天我们报道过 Opera 浏览器内置了 VPN 服务,用户打开它可以防止他们的在线活动被窥视。不过...