Python断言教程展示了如何在Python中使用断言。我们定义断言,解释断言和异常之间的区别,并展示它们与单元测试的关系。
断言
断言是代码中的内部自检;它们适合开发人员尽快发现错误。断言的目的是在程序的早期检测问题,原因很清楚,并避免它们作为其他操作的副作用弹出。
断言不应该用于数据处理或验证,因为它们在生产中被关闭。一些编程语言,例如Go,不使用断言。其他语言也有assert语句,但很少使用(Java)。
断言与异常
断言是布尔表达式,必须为真才能使代码正确。断言失败会导致代码更正。异常是关于可能在运行时发生的非典型情况的指示。异常可能不会导致代码中缀。例如,如果Internet连接中断,或文件权限不足,则用户必须进行处理。断言不应用于处理运行时错误。
按合同设计
按合同设计或按合同编程是一种软件开发实践,开发人员在其中为软件组件定义正式、精确和可验证的接口规范。规范分为前置条件、后置条件和不变量。
先决条件是在执行一段代码之前必须始终为真的谓词。poscondition是一个谓词,在执行一段代码后必须始终为真。不变量是在所有操作之后保持不变的属性。
合同设计方法是在1980年代发展起来的,受到商业合同的启发。
断言和单元测试
断言和单元测试在某些方面有重叠,但也存在一些差异。断言是对程序内部状态的假设,而单元测试检查模块的外部行为。单元测试使用测试数据,而断言则不行。
断言语句用于单元测试。经典断言是关于真实情况的假设,而在单元测试中,开发人员经常测试错误条件。
Python断言
assert
语句是将调试断言插入Python程序的便捷方式。使用-O
、-OO
选项和PYTHONOPTIMIZE
变量删除断言语句。
Pythonassert
语句由一个布尔条件和一个可选的错误消息组成,以逗号分隔。
Python断言示例
以下示例展示了Pythonassert语句的用法。
#!/usr/bin/python def info(age, name): assert age >= 18 and age <= 65, 'age value must be between values 18 and 65' print(f'{name} is {age} years old') age = 84 name = 'Peter' info(age, name)
在这个例子中,我们有一个关于年龄值的先决条件。
$ ./precondition.py Traceback (most recent call last): File "./precondition.py", line 14, in <module> info(age, name) File "./precondition.py", line 6, in info assert age >= 18 and age <= 65, 'age value must be between values 18 and 65' AssertionError: age value must be between values 18 and 65
程序失败,因为前提条件无效。
#!/usr/bin/python def do_discount(price, discount): discounted_price = price - discount * price assert 0 < discounted_price < price, 'discounted price must be greater than zero and lower than original price' return discounted_price price = 120 discount = 0.2 dis_price = do_discount(price, discount) print(dis_price)
第二个例子有一个关于折扣价的后置条件。它必须大于零且低于原始价格。
单元测试中的Python断言
Python有几个流行的单元测试框架,包括pytest
、unittest
和nose
。虽然pytest
和nose
使用assert
语句,但unittest
支持assertEqual
等函数和assertLess
。
Pytest示例
下面的例子展示了pytest
框架的使用。
def max(values): _max = values[0] for val in values: if val > _max: _max = val return _max def min(values): _min = values[0] for val in values: if val < _min: _min = val return _min
我们在一个模块中有两个算法。
#!/usr/bin/python import algo def test_min(): values = (2, 3, 1, 4, 6) val = algo.min(values) assert val == 1 def test_max(): values = (2, 3, 1, 4, 6) val = algo.max(values) assert val == 6
我们将测试数据传递给被测试的algo
函数。我们使用assert
语句检查预期值。
$ pytest-3 min_max_test.py ============================================================= test session starts ============================================================= platform linux -- Python 3.7.6, pytest-4.6.9, py-1.8.1, pluggy-0.13.0 rootdir: /root/Documents/prog/python/assert collected 2 items min_max_test.py ..
我们运行测试。
单元测试示例
现在我们用unittest
测试同一个模块。
#!/usr/bin/python import unittest import algo class SimpleTest(unittest.TestCase): def test_min(self): values = (2, 3, 1, 4, 6) val = algo.min(values) self.assertEqual(val, 1) def test_max(self): values = (2, 3, 1, 4, 6) val = algo.max(values) self.assertEqual(val, 6) if __name__ == '__main__': unittest.main()
在示例中,我们使用了assertEqual
断言。
$ ./min_max_test.py .. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK
我们运行测试。
在本教程中,我们使用了Pythonassert语句并大体解释了断言。
列出所有Python教程。