Python 之真假“美猴王”

本文探讨了Python单元测试中的布尔断言方法assertTrue和assertFalse与身份断言assertIs的区别。通过示例展示了不同断言方法在函数返回值验证时的行为差异,强调了使用assertIs进行精确类型检查的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

导读单元测试的重要性就不多说了,可恶的是Python中有太多的单元测试框架和工具,什么unittest, testtools, subunit, coverage, testrepository, nose, mox, mock, fixtures, discover,再加上setuptools, distutils等等这些。在这篇文章中,我们将介绍单元测试的布尔断言方法 assertTrue 和 assertFalse 与身份断言 assertIs 之间的区别。
定义

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

assertTrue(expr, msg=None)
assertFalse(expr, msg=None)
测试该表达式是真值(或假值)。 注:这等价于 bool(expr) is True 而不等价于 expr is True (后一种情况请使用 assertIs(expr, True))。 Mozilla 开发者网络中定义 真值 如下: [info]在一个布尔值的上下文环境中能变成“真”的值[/info] 在 Python 中等价于:
bool(expr) is True

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

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

python-t-f

在实践中怎么理解?

我们使用一个非常简单的例子 - 一个名称为 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

现在,某个人将 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 给了我们一个误判。在它不应该通过测试时,它通过了。很幸运的是我们第二个测试是使用 assertIs 来写的。

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

215451lzjhnhy8qquumq8n

使用断言的辅助方法

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

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

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

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

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

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

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

本文转载自:http://www.linuxprobe.com/python-asserttrue-assertfalse.html

免费提供最新Linux技术教程书籍,为开源技术爱好者努力做得更多更好:http://www.linuxprobe.com/

### Python 中的“美猴王”实现分析 在讨论 Python 的“美猴王”项目或其实现时,可以从多个角度切入。以下是关于该主题的一个综合解析。 #### 1. 测试中的断言方法改进 当涉及到单元测试时,“美猴王”的案例展示了如何优化断言逻辑以提高代码质量。例如,在某些情况下 `assertTrue` 方法可能会导致误判[^1]。为了避免这种情况的发生并使测试更加严格,推荐使用 `assertIs` 替代 `assertTrue`: ```python def test_example(self): value = True self.assertIs(value, True) # 更严格的判断方式 ``` 这种方式不仅能够减少潜在错误,还能提升代码的可维护性和清晰度[^3]。 #### 2. 自定义辅助函数增强可读性 如果在一个大型项目中频繁检查布尔值的状态,则可以通过创建自定义断言来简化操作流程。下面是一个简单的例子展示如何封装这些功能: ```python class CustomAssertions: def assertIsTrue(self, value): self.assertIs(value, True) def assertIsFalse(self, value): self.assertIs(value, False) ``` 尽管这样做表面上并未显著缩短代码长度,但它确实增强了程序结构的一致性和易理解程度[^3]。 #### 3. 面向对象编程的应用场景 考虑到“美猴王”这一形象本身具备丰富的属性和行为特征,采用面向对象的方式对其进行建模是非常合适的。比如我们可以这样设计一个基础版本的角色类: ```python class MonkeyKing: def __init__(self, name="孙悟空"): self.name = name def introduce(self): print(f'大家好我是{self.name},多多关照!') monkey_king_instance = MonkeyKing() monkey_king_instance.introduce() # 输出: 大家好我是孙悟空,多多关照! ``` 这里利用了 `__init__()` 构造器初始化角色名称,并通过成员方法完成自我介绍的功能演示[^4]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值