使用Python进行基于属性的测试

2023-10-31

When you write unit tests, it’s hard to find the right test cases. You want to be certain that you covered all the interesting cases, but you could simply not know or forget one of them. For example, if you unit test a function which receives an integer, you might think about testing 0, 1, and 2. But did you think about negative numbers? What about big numbers?

在编写单元测试时,很难找到正确的测试用例。 您想确定自己涵盖了所有有趣的案例,但是您根本就不知道或忘记其中一个案例。 例如,如果您对接收一个整数的函数进行单元测试,您可能会考虑测试0、1和2。但是您是否考虑过负数? 大数字呢?

We were just thinking about a testing strategy for integers. A strategy is a generator of data. The property testing framework hypothesis offers a lot of strategies for many types. You can install it with pip install hypothesis .

我们只是在考虑整数的测试策略。 策略是数据的生成器。 属性测试框架hypothesis为多种类型提供了许多策略 。 您可以使用pip install hypothesis进行pip install hypothesis

One thing we can do with those inputs — those tests strategies — is to check if the runtime is acceptable and if the tested function/method does not crash.

我们可以使用这些输入(即测试策略)来做的一件事是检查运行时是否可以接受以及所测试的函数/方法是否不会崩溃。

It would be better if we compare the output of our function against something. A check for equality is likely not possible, so we need to know a property of our function. An invariant which we always expect to hold. We need to base our test on an inherent property of the function.

如果我们将函数的输出与某些东西进行比较,那会更好。 可能无法进行相等性检查,因此我们需要知道函数的属性。 我们一直希望保持不变的不变式。 我们需要基于函数的固有属性进行测试。

To whet your appetite for property-based testing even more:

进一步激发您对基于属性的测试的兴趣:

示例:整数分解 (Example: Integer factorization)

We have a function factorize(n : int) -> List[int] which takes an integer and returns the prime factors:

我们有一个函数factorize(n : int) -> List[int] ,它接受一个整数并返回素数:

An integer n is called a prime number if it is positive and divisible by exactly two numbers: 1 and n.

如果整数n是正数并且可以被两个整数整除(即1和n),则称为素数。

We want that the product of returned integers is the number itself. So this is how we design the functions behavior:

我们希望返回的整数的乘积是数字本身。 这就是我们设计函数行为的方式:

  • factorize(0) = [0] — an exception would have been reasonable as well

    factorize(0)= [0]-异常也将是合理的
  • factorize(1) = [1] — strictly speaking, 1 is not a prime.

    factorize(1)= [1] —严格来说,1不是质数。
  • factorize(-1) = [-1] — … and neither is -1

    factorize(-1)= [-1] —…都不是-1
  • factorize(-n) = [-1] + factorize(n) for n > 1

    因式分解(-n)= [-1] +因式分解(n),n> 1

An implementation might look like this:

一个实现可能看起来像这样:

You might feel a bit uneasy about the condition in

您可能会对这种情况感到不安

while i <= int(math.ceil(number ** 0.5)) + 1:

so you write a test to check for the important cases:

因此,您编写了一个测试来检查重要情况:

If the test parametrization is unfamiliar, you might want to read up on pytest.mark.parametrize. It’s awesome and those few lines run 8 tests:

如果测试参数不熟悉,则可能需要阅读pytest.mark.parametrize 。 很棒,那几行运行了8个测试:

Running pytest. Screenshot taken by Martin Thoma.
运行pytest。 屏幕截图由Martin Thoma拍摄。

How would a property-based test look like for factorize?

基于属性的测试对于factorize外观如何?

First, we need to think about the property we want to test. For factorize as we designed it, we know that the product of the returned numbers is equal to the number itself. We can put in any integer, but if the integers become too big, the runtime will be too long. So let’s constrain them in a reasonable range of +/- one million:

首先,我们需要考虑我们要测试的属性。 对于我们设计时的factorize ,我们知道返回数字的乘积等于数字本身。 我们可以输入任何整数,但是如果整数太大,则运行时间将太长。 因此,让我们将它们限制在+/-一百万的合理范围内:

Now we run the tests with pytest :

现在,我们使用pytest运行测试:

Hypothesis found an issue! Screenshot taken by Martin Thoma.
假设发现一个问题! 屏幕截图由Martin Thoma拍摄。

As you can see in the example above, hypothesis discovered that factorize(5) returned an empty list which does not multiply to 5. We can then quickly see that we actually made a mistake for all primes — we need to add the prime number. After adding the following line, the tests run just fine:

如您在上面的示例中看到的, hypothesis发现factorize(5)返回了一个不会乘以factorize(5)的空列表。然后我们可以很快看到我们实际上对所有素数都犯了一个错误-我们需要添加素数。 添加以下行后,测试运行正常:

if number != 1:
factors.append(number)

A curious thing to notice in the failed example is that it is the smallest positive integer where it fails. This is no coincidence. The property-testing framework tries to find a simple example which makes the test fail. This process is called shrinking.

在失败的示例中要注意的一个奇怪的事情是它是失败的最小正整数。 这不是巧合。 属性测试框架试图找到一个使测试失败的简单示例。 这个过程称为收缩

假设产生了什么? (What did hypothesis generate?)

You can have a look at examples like this:

您可以看一下这样的示例:

from hypothesis import strategies as stst.lists(st.integers()).map(sorted).example()

在哪里可以进行基于属性的测试? (Where can I apply property-based testing?)

This kind of pattern works for quite a couple of algorithms where verification is cheap:

这种模式适用于很多验证费用较低的算法:

  • Arg max: Iterate over the list and ensure that no other element is larger.

    Arg max :遍历列表,并确保没有其他元素更大。

  • Solving a set of equations: Verify that the solution is actually a solution.

    解决一组方程:验证解决方案实际上是一个解决方案。
  • Constraint satisfaction: Verify that the solution satisfies all constraints.

    约束满足 :验证解决方案是否满足所有约束。

  • All NP complete problems: This is a set of decision problems where it is hard to find an answer, but easy to verify a found answer. An example is the traveling salesman. Given a set of cities which the salesman has to visit, is there a tour he can take which has a length of at most L? Given such a tour, it is easy to verify. Computing such a tour can be hard, though.

    所有NP完整问题 :这是一组决策问题,很难找到答案,但是很容易验证找到的答案。 一个例子是旅行推销员。 给定销售员必须访问的一组城市,他是否可以进行游览,游览时间最长为L? 进行这样的游览,很容易验证。 但是,计算这样的行程可能很困难。

Weaker, but still helpful are checks which verify if the returned value is in the set of candidates:

较弱但仍然有用的检查是用来验证返回的值是否在候选集合中:

  • Greatest common divisor: Ensure that it actually is a divisor.

    最大除数 :确保它实际上是一个除数。

  • Shortest path: Ensure it is a path.

    最短路径:确保它是一条路径。

  • Sorting and ranking: Ensure exactly the same elements are in the list as before. Maybe you can also test for the sorting/ranking criterion?

    排序和排名:确保列表中的元素与以前完全相同。 也许您还可以测试排序/排名标准?
  • Filtering: Assert that the relevant data is still there / that the other data was removed.

    过滤:确认相关数据仍然存在/其他数据已删除。

生成测试模式 (The Generate to Test Pattern)

Sometimes it is easy to generate a sample to test the function you’re interested in. For the factorization example above, you might have a list of known primes and you multiply random subsets of them. If you write a function that checks if a string is a palindrome, you can easily generate a palindrome first. If you want to check if a text contains a given string, you can add random text around that string and then check.

有时很容易生成一个样本来测试您感兴趣的函数。对于上面的因式分解示例,您可能有一个已知素数的列表,并将它们的随机子集相乘。 如果编写用于检查字符串是否为回文的函数,则可以轻松地首先生成回文。 如果要检查文本是否包含给定的字符串,可以在该字符串周围添加随机文本,然后进行检查。

示例:测试数据结构 (Example: Testing Data Structures)

I’ve implemented an interval data structure which has a method issubset

我已经实现了具有方法issubset的间隔数据结构

字符串验证 (String Verification)

hypothesis can generate some special strings, for example email addresses and IP addresses. This means you can easily check the positive cases for functions which decide if something is an IP address or an email address:

hypothesis可以生成一些特殊的字符串,例如电子邮件地址和IP地址。 这意味着您可以轻松检查功能的肯定情况,这些功能可以确定某些内容是IP地址还是电子邮件地址:

可逆功能 (Invertible functions)

A function and its inverse function. Image by Martin Thoma.
一个函数及其反函数。 图片由Martin Thoma提供。

If you have a function and its inverse function, such as encrypt / decrypt or a serialize / deserialize function, you can test them together. The testing strategy should then just give values within the domain.

如果您具有一个函数及其反函数,例如加密/解密或序列化/反序列化函数,则可以一起测试它们。 然后,测试策略应该只给出域内的值。

For example, if we wanted to test b64encode / b64decode , the test would be:

例如,如果我们要测试b64encode / b64decode ,则测试将是:

This test now also documents that those two functions belong together and are meant to be used in this order.

现在,该测试还记录了这两个功能属于同一类,并且应按此顺序使用。

神谕者 (Oracles)

Photo by Jen Theodore on Unsplash
Jen TheodoreUnsplash上的 照片

In complexity theory, an oracle is a black box which offers a solution to a problem in instant time. In this context, it is just a second implementation which we trust to be correct. If you have a complex algorithmic problem, you might first want to implement a brute-force solution and then test your faster algorithm against that easier to understand solution. The brute-force algorithm is the oracle.

在复杂性理论中,先知是一个黑匣子,它可以即时解决问题。 在这种情况下,这只是我们相信正确的第二种实现。 如果您遇到复杂的算法问题,则可能首先要实施蛮力解决方案,然后针对该更容易理解的解决方案测试更快的算法。 蛮力算法是预言。

使用类型注释! (Use Type Annotations!)

I love type annotations

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用Python进行基于属性的测试 的相关文章

  • Python包不安装子模块

    我在 dev 分支中创建了一个具有以下结构的包 在验证包安装正确之前不会合并到 main mypackage init py setup py requirements txt module py subpackage one init p
  • python中热图的层次聚类

    我有一个 NxM 矩阵 其值范围为 0 到 20 我可以使用 Matplotlib 和 pcolor 轻松获得热图 现在我想使用 scipy 应用层次聚类和树状图 我想重新排序每个维度 行和列 以显示哪些元素相似 根据聚类结果 如果矩阵是方
  • ipdb 和 pdb++ 之间的区别?

    Python 有一个名为 pdb 的默认调试器 但社区创建了一些替代品 其中两个是ipdb https github com gotcha ipdb and pdb https github com pdbpp pdbpp 它们似乎迎合了相
  • 带括号的上下文管理器

    我试图了解新的新内容带括号的上下文管理器Python 3 10 中的功能 新功能中的顶部项目here https docs python org 3 10 whatsnew 3 10 html 我的测试示例是尝试编写 with open f
  • 无法在 mysql 表中的值中使用破折号(-)[重复]

    这个问题在这里已经有答案了 我一直在尝试从 python 将数据插入 MYSQL 表 我的sql表中的字段是id token start time end time和no of trans 我想存储使用生成的令牌uuid4在令牌栏中 但由于
  • Python 小数.InvalidOperation 错误

    当我运行这样的东西时 我总是收到此错误 from decimal import getcontext prec 30 b 2 3 Decimal b Error Traceback most recent call last File Te
  • 使用信号时出现 django TransactionManagementError

    我有一个与 django 的用户和 UserInfo 一对一的字段 我想订阅用户模型上的 post save 回调函数 以便我也可以保存 UserInfo receiver post save sender User def saveUse
  • 创建一个打开文件并创建字典的函数

    我有一个正在处理的文件 我想创建一个读取文件并将内容放入字典中的函数 然后该字典需要通过 main 函数传递 这是主程序 它无法改变 我所做的一切都必须与主程序配合 def main sunspot dict file str raw in
  • 有条件填写 pandas 数据框

    我有一个数据框df列中包含浮点值A 我想添加另一列B这样 B 0 A 0 for i gt 0 B i if np isnan A i then A i else Step3 B i if abs B i 1 A i B i 1 lt 0
  • Pyinstaller --onefile 警告文件已存在但不应存在

    跑步时Pyinstaller onefile 并开始得到结果 exe 会出现多个弹出窗口 并显示以下警告 WARNING file already exists but should not C Users myuser AppData L
  • 在ansible中合并字典

    我目前正在构建一个使用 ansible 安装 PHP 的角色 并且在合并字典时遇到一些困难 我尝试了多种方法来做到这一点 但我无法让它像我想要的那样工作 A vars file my default values key value my
  • 如何使用 python 操作系统更改驱动器?

    我正在尝试更改当前目录C to Y 我试过 import os os chdir Y 但我不断收到错误消息 提示无法找到驱动器 本质上我正在寻找相当于 cd d cmd 中的命令 你确定吗Y 确实是有效的驱动器号吗 Try os chdir
  • InvalidArgumentException:消息:无效参数:“using”必须是字符串

    我对 python 很陌生 试图创建可重用的代码 当我尝试通过传递 Login 类下使用的所有参数来调用 test main py 中的 Login 类和函数 login user 时 我收到错误 InvalidArgumentExcept
  • 管理文件字段当前 url 不正确

    在 Django 管理中 只要有 FileField 编辑页面上就会有一个 当前 框 其中包含指向当前文件的超链接 但是 此链接会附加到当前页面 url 因此会导致 404 因为不存在这样的页面 例如 http 127 0 0 1 8000
  • 如何在matplotlib中基于x轴更改直方图颜色

    我有根据 pandas 数据框计算出的直方图 我想根据 x 轴值更改颜色 例如 If the value is 0 the color should be green If the value is gt 0 the color shoul
  • 如何在 Python 中仅列出 zip 存档中的文件夹?

    如何仅列出 zip 存档中的文件夹 这将列出存档中的每个文件夹和文件 import zipfile file zipfile ZipFile samples sample zip r for name in file namelist pr
  • PyQt - 如何检查 QDialog 是否可见?

    我有个问题 我有这个代码 balls Ball for i in range 1 10 因此 当我说 Ball 时 这将在 QDialog 上绘制一个球 然后当这完成后 我正在移动球QDialog无限循环中 我想说类似的话while QDi
  • Jupyter Notebook 中的多处理与线程

    我试图测试这个例子here https ipywidgets readthedocs io en stable examples Widget 20Asynchronous html将其从线程更改为多处理 在 jupyter Noteboo
  • 在 Tensorflow 2.0 中的简单 LSTM 层之上添加 Attention

    我有一个由一个 LSTM 和两个 Dense 层组成的简单网络 如下所示 model tf keras Sequential model add layers LSTM 20 input shape train X shape 1 trai
  • 如何让你的精灵在pygame中跳跃

    目前我已经制作了一个平台游戏 可以左右移动我的角色 他从地上开始 关于如何让他跳的任何想法 因为我不明白 目前 如果我按住向上键 我的玩家精灵将连续向上移动 或者如果我按下它 我的玩家精灵将向上移动并保持向上 我想找个办法远离他 让我重新跌

随机推荐

  • 一个项目的基本要素都有哪些?

    在规划项目时 必须要慎重考虑项目的五要素 那么项目的五要素是什么 一个成功的项目经理必须对这五个要素有相当程度的了解 才能更好更高效的完成项目 在五个要素中 项目的范围和组织结构为最基本要素 质量 时间 成本是约束要素 1 项目的范围 项目
  • JDBC纯驱动方式连接MySQL

    1 新建一个名为MysqlDemo的Java Project 2 从http dev mysql com downloads connector j 中下载最新的驱动包 这里有 tar gz和 zip两种格式的包 因为在windows下都可
  • 递归删除符合条件的目录,文件, kotlin,java

    package a import java io IOException import java nio file import java nio file attribute BasicFileAttributes fun main ar
  • Linux和华为欧拉系统下安装mysql-5.7.30详细步骤

    大家好 又见面了 我是你们的朋友全栈君 Hello everyone see you again I m your friend Quan Zhanjun Detailed steps to install mysql 5 7 30 und
  • java.sql.array 初始化_Java数组学习

    Java数组学习 数组的定义 数组是相同类型数据的有序集合 数组描述的是相同类型的若干个数据 按照一定的先后次序排列组合而成 其中 每一个数据称作一个数组元素 每个数组元素可以通过一个下标来访问它们 数组的下标从0开始 数组声明创建 首先必
  • 应用程序无法正常启动(0x000007b)

    应用程序无法正常启动 0x000007b 请单击 确定 关闭应用程序 错误代码 0x000007b 是 Windows 操作系统中的一个常见错误代码 它通常与应用程序或操作系统文件的错误 损坏或不匹配相关联 这个错误代码可能会导致应用程序无
  • 正则表达式清理日志

    字段提取中正则表达式的使用 提取日志中的信息格式 lt 字段名称 gt 匹配具体信息的正则表达式 日志样例 lt 78 gt 2019 08 21T17 10 01 461970 08 00 localhost CROND root CMD
  • en结尾的单词_【第24集】en结尾的不规则动词变化

    这一集我们来看一下另一种不规则动词的变化 en 结尾 当然 这里en结尾 并不是说这个单词是en结尾 只是发音是en这样的不规则动词 那么这写不规则动词有哪些呢 我们来总结一下 tear 原形 tore 过去式 torn 过去分词 撕开 什
  • 如何在sublime Text3实时运行js代码?

    安装Node js https nodejs org en 为sublime text3添加编译系统 Tools gt Build System gt New Build System 在打开的界面中添加 cmd node file sel
  • UPnP协议学习

    UPnP架构定义了两种类型的设备 控制设备 controlled devices 和控制点 control points 控制设备扮演服务器的角色 响应控制点的请求 控制点和控制设备都能在各种平台包括个人电脑和嵌入式设备中实现 多个控制设备
  • C#8.0本质论第四章--操作符和控制流程

    C 8 0本质论第四章 操作符和控制流程 4 1操作符 有些操作符以符号的形式出现 例如 或者 等 而另一些操作符则为关键词 例如default和is 4 1 1一元正负操作符 一元正操作符 对值几乎没有影响 它在C 中是多余的 4 1 2
  • 组织机构代码输入测试用例_测试代码以用于过大的输入

    组织机构代码输入测试用例 在编写单元测试时 我们主要关注业务的正确性 我们将竭尽所能 开开心心地走在最前沿 我们有时会进行微基准测试并衡量吞吐量 但是经常遗漏的一个方面是当输入过大时我们的代码如何表现 我们测试了如何处理正常的输入文件 格式
  • MES系统介绍

    MES系统是什么 能解决企业管理中的什么问题 史上最全MES生产管理系统介绍 傲鹏MES供应商内部培训资料 错过了就没有了 一 MES系统介绍1 什么是MES系统 中文全称 制造执行系统 英文全称 manufacturing executi
  • 基于x86架构的CentOS7虚拟机通过qemu安装ARM架构CentOS7虚拟机_centos7 arm 网络配置

    原文连接 基于x86架构的CentOS7虚拟机通过qemu安装ARM架构CentOS7虚拟机 centos7 arm redrose2100的博客 CSDN博客 试过很多版本的在win10系统直接qemu安装arm版linux都失败了 也看
  • vm16安装windows系统

    安装win7系统 网上找到的iso均为ghost镜像 结果发现无法引导 找了个win10镜像可以引导 同时在创建一个cd加载win7的iso 进入win10的镜像PE 格式化硬盘 安装win7镜像 ok 同时 使用win7配置 安装win1
  • [创业之路-43] :复盘与自省 - 创业初感悟(冲动->纠结->忐忑)与“不贪、不赌、不悔”做人做事三原则的成形

    目录 创业冲动 冲动之后是纠结 选择后的忐忑 未来的应对之策 复盘后的体悟 做人做事三大基本原则1 不贪而心安 做人做事三大基本原则2 不赌而敬畏 做人做事三大基本原则3 不悔而未来 收获 创业冲动 虽然对创业进行了很多零散知识上的准备和多
  • 【WEB】关于网页设置 background-image: url死活显示不出来的解决办法

    图片或者背景显示不出来 大部分都是路径的问题 这是我图片所在的文件夹 相信很多有这个问题的小伙伴都是像我下面这样写的路径 那么背景图是不会显示出来的 解决办法如下图 原因是 在img的src中 是以当前html网页做相对文件 来设置引入图片
  • 全网最详细Postman接口测试使用教程(实战干G货)

    目录 导读 一 前言 二 接口测试 三 抓包 四 postman构造请求 五 其他的登录鉴权方式 六 总结 一 前言 测试行业现在越来越卷 不会点接口测试好像简历都已经拿不出手了 但很多小伙伴都会头疼 接口测试应该怎么入门 那么多的接口测试
  • vue axios三层封装

    utils文件下创建request js文件 第一层封装 引入axios文件 import axios from axios import qs from qs 声明公共的地址 axios defaults baseURL 设置超时 axi
  • 使用Python进行基于属性的测试

    When you write unit tests it s hard to find the right test cases You want to be certain that you covered all the interes
Powered by Hwhale