python 如何用 Hypothesis 来自动化单元测试

下面是关于使用 Hypothesis 自动化单元测试的完整攻略。

什么是 Hypothesis?

Hypothesis 是一个基于属性推理(property-based)的 Python 测试框架,它使用了随机数据生成器和“假设”(assumptions)来创建、执行和简化测试。该框架允许你只编写一小部分的测试用例,就能发现许多边缘情况和隐含错误。

安装 Hypothesis

Hypothesis 的安装非常简单,只需使用 pip 命令即可:

pip install hypothesis

Hypothesis 的基本用法

  1. 创建一个测试函数,使用 @hypothesis.given() 装饰器指定测试函数接收的参数和 参数的数据来源;

  2. 在测试函数中编写测试代码,使用随机数据进行测试。

以一个简单的例子为例,假设我们要测试一个函数,该函数接受两个字符串作为参数并将它们连接起来,我们可以写出如下的测试函数:

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() 生成器用于生成一个任意长度的字符串。

在测试函数中,我们使用生成器生成的两个字符串做字符串连接操作,并断言连接结果的数据类型和值都正确。

  1. 执行测试代码,使用 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技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • 查找NumPy数组中一个序列的出现次数

    查找NumPy数组中一个序列的出现次数可以通过NumPy包中的函数来实现。具体步骤如下: 导入NumPy包 import numpy as np 创建一个NumPy数组 a = np.array([1, 2, 3, 4, 5, 2, 3, 1, 2]) 创建一个要查找的序列 seq = np.array([1, 2]) 使用NumPy包中的frombuffe…

    python-answer 2023年3月25日
    00
  • python内打印变量之%和f的实例

    当我们在Python中想要打印变量的时候,可以使用字符串格式化来将变量插入到字符串中。其中,有两种方法可以进行字符串格式化,即使用%和使用f。 使用%进行字符串格式化 使用%进行字符串格式化的方法是最早的字符串格式化方法,也是最古老的方法之一,它是Python在很长一段时间内唯一可用的字符串格式化方法。它的基本语法如下: print("%s %d&…

    python 2023年6月5日
    00
  • python基础之编码规范总结

    Python基础之编码规范总结 编码规范是编程中非常重要的一部分,它可以提高代码的可读性、可维护性和可扩展性。本文将介绍编码规范,包括命名规范、代码风格、注释规范等。 1. 命名规范 在Python中,命名规范是非常重要的。命名规范可以提高代码的可读性和可维护性。以下是Python命名规范的一些基本规则: 变量名应该小写字母,单词之间使用下划线隔开。 函数名…

    python 2023年5月13日
    00
  • Python计时相关操作详解【time,datetime】

    Python计时相关操作详解【time,datetime】 在Python中涉及到计时的操作很多,比如计算程序运行时间、获取当前日期和时间等,主要用到了两个模块:time和datetime。在本文中,我们会详细讲解这两个模块的常用方法,并给出相应的代码示例。 time模块 time.time() time.time()函数用于获取当前时间的时间戳,返回值为浮…

    python 2023年6月2日
    00
  • 详解python使用递归、尾递归、循环三种方式实现斐波那契数列

    详解Python使用递归、尾递归、循环三种方式实现斐波那契数列 斐波那契数列是一个非常经典的数列,它的定义如下: $$F_0=0,F_1=1,F_n=F_{n-1}+F_{n-2}(n\geq2)$$ 在本文中,将介绍如何使用Python实现斐波那契数列,并分别使用递归、尾递归循环三种方式实现。 递归实现斐那契数列 递归是一种常用的算法思想,它的基想是将一个…

    python 2023年5月14日
    00
  • 在python中实现求输出1-3+5-7+9-……101的和

    要求输出1-3+5-7+9-……101的和,可以使用Python中的循环和条件语句进行计算。下面是实现该需求的完整攻略: 创建一个变量result,用于存储计算结果并初始化为0。 使用for循环遍历1到101之间的所有奇数,步长为2。 对于每个奇数,使用if语句判断该奇数的下标(从1开始计数)是否为奇数。 如果下标为奇数,说明需要使用加法,将该奇数累…

    python 2023年6月5日
    00
  • Python中可以用三种方法判断文件是否存在

    在Python中,可以用三种方法判断文件是否存在,分别为: os.path.isfile() 这是Python自带的一个库,判断某个路径是否为文件。可以使用以下语法: import os # 检查文件是否存在 if os.path.isfile(‘/path/to/file’): print(‘文件存在’) else: print(‘文件不存在’) 其中,/…

    python 2023年6月2日
    00
  • wxPython窗体拆分布局基础组件

    下面我将为您详细讲解如何使用wxPython的窗体拆分布局基础组件。 什么是窗体拆分布局基础组件? 在wxPython中,窗体拆分布局基础组件指的是能将一个窗口或面板分为多个子窗口或子面板的组件。常见的拆分布局组件包括分割窗格(Splitter),面板拆分器(Panel Splitter)以及网格布局(GridBagSizer)等。 如何使用窗体拆分布局基础…

    python 2023年6月13日
    00
合作推广
合作推广
分享本页
返回顶部