下面是关于使用 Hypothesis 自动化单元测试的完整攻略。
什么是 Hypothesis?
Hypothesis 是一个基于属性推理(property-based)的 Python 测试框架,它使用了随机数据生成器和“假设”(assumptions)来创建、执行和简化测试。该框架允许你只编写一小部分的测试用例,就能发现许多边缘情况和隐含错误。
安装 Hypothesis
Hypothesis 的安装非常简单,只需使用 pip 命令即可:
pip install hypothesis
Hypothesis 的基本用法
-
创建一个测试函数,使用
@hypothesis.given()
装饰器指定测试函数接收的参数和 参数的数据来源; -
在测试函数中编写测试代码,使用随机数据进行测试。
以一个简单的例子为例,假设我们要测试一个函数,该函数接受两个字符串作为参数并将它们连接起来,我们可以写出如下的测试函数:
import hypothesis
import hypothesis.strategies as st
# 定义测试用例输入数据和测试函数
@hypothesis.given(st.text(), st.text())
def test_string_concatenation(s1, s2):
# 执行测试操作
result = s1 + s2
# 校验测试结果
assert isinstance(result, str)
assert result == s1 + s2
在上面的代码中,我们使用了 @hypothesis.given()
装饰器指定了测试函数 test_string_concatenation()
有两个参数,这两个参数均使用了 hypothesis.strategies
中的 text()
策略生成。text()
生成器用于生成一个任意长度的字符串。
在测试函数中,我们使用生成器生成的两个字符串做字符串连接操作,并断言连接结果的数据类型和值都正确。
- 执行测试代码,使用
hypothesis.find()
函数即可自动化执行单元测试:
hypothesis.find(test_string_concatenation)
执行 find()
函数将会自动使用随机的字符串输入执行 test_string_concatenation()
函数。
使用 Hypothesis 还可以使用 @hypothesis.settings()
装饰器指定测试用例的数量、测试用例执行中最多可用的生成次数以及其他配置。
两个实例
下面我们将使用两个示例介绍 Hypothesis 的常规配置和使用方法:
示例一:测试数组是否排序
首先,我们编写一个数组排序的函数,代码如下:
from typing import List
def bubble_sort(arr: List[int]) -> List[int]:
"""
对输入数组进行冒泡排序,返回排序后的数组。
"""
n = len(arr)
for i in range(n):
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr
然后,我们使用 Hypothesis 自动化创建单元测试。我们可以定义一个生成器 array_st()
生成长度在 1~100 之间的正整数数组,然后编写一个测试函数 test_bubble_sort()
来测试数组排序的函数是否正确:
import hypothesis.strategies as st
@hypothesis.given(array_st())
def test_bubble_sort(arr):
# 进行排序操作
res = bubble_sort(arr)
# 校验各种属性是否满足要求
assert len(res) == len(arr)
assert res == sorted(arr)
assert sorted(arr) == list(res)
最后,我们使用 Hypothesis 执行测试:
hypothesis.find(test_bubble_sort)
示例二:测试电话号码格式
在下一个例子中,我们将使用 Hypothesis 自动化测试电话号码的格式是否正确。首先,我们定义一个可以接收电话号码作为输入的函数 is_phone_number()
;然后,使用 Hypothesis 进行测试。
我们可以通过 st.builds()
函数轻松创建电话号码生成器 phone_number()
,如下所示:
import hypothesis.strategies as st
def phone_number():
# 随机生成前缀、省份、市区和行政区号
prefix = st.sampled_from(["+86", "86", "0086"])
province = st.sampled_from(["北京", "上海", "广州", "深圳", "天津", "南京", "杭州"])
city_code = st.sampled_from(["10", "21", "20", "22", "25", "21", "23"])
area_code = st.text(min_size=3, max_size=4, alphabet=st.characters(whitelist_categories=("Nd",)))
# 使用上述信息格式化电话号码
return st.builds(
lambda p, pr, c, ac: f"{p} {pr} {c}-{ac}",
prefix, province, city_code, area_code
)
# 定义测试函数
@hypothesis.given(phone_number())
def test_phone_number_format(phone):
pattern = r'\+?(\d{1,3})?[\s-]?(\d{1,4})?[\s-]?\d{7,8}$'
# 校验电话号码格式是否正确
assert re.match(pattern, phone) is not None
在上面的代码中,我们通过 st.sampled_from()
函数生成随机的电话号码前缀、省份、市区和行政区号,然后使用 st.builds()
函数将这些信息格式化成最终的电话号码。在测试函数中,我们使用正则表达式校验电话号码是否符合要求。
现在,让我们使用 Hypothesis 执行测试代码:
hypothesis.find(test_phone_number_format)
至此,我们已经学会了如何使用 Hypothesis 自动化进行单元测试,希望这个攻略对你有所帮助!
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:python 如何用 Hypothesis 来自动化单元测试 - Python技术站