鉴源论坛 · 观模丨基于软件性质的自动化测试技术

news2024/9/30 13:20:29

作者 | 熊一衡 华东师范大学软件工程学院博士

         苏亭 华东师范大学软件工程学院教授

版块 | 鉴源论坛 · 观模

社群 | 添加微信号“TICPShanghai”加入“上海控安51fusa安全社区”

在软件开发的生命周期中,测试是至关重要的一环。为了确保软件产品的质量,开发团队需要进行全面的测试,以发现和修复软件中潜在的缺陷和问题。传统的人工测试虽然有效,但却耗时耗力,且成本较高。为了提高测试效率和准确性,自动化测试已经成为一个重要的研究领域。

图片

图1 自动化测试技术

图1介绍了现有的几种自动化测试方法 [1]。X轴表示Feature compliance,即测试是否覆盖测试人员想要测试的功能,而Y轴表示 Input scope covered, 表示测试输入的覆盖程度。可以看出,在图的右上角缺了一块,即同时满足high feature compliance和full input scope covered 的测试技术。这个技术就是接下来要介绍的基于性质的测试技术(property-based testing)。

01

什么是基于软件性质的自动化测试技术

基于软件性质的测试(property-based testing)是一种很受欢迎的自动化测试技术,其原理是测试人员编写适用于待测软件的真实逻辑语句(即性质),然后使用自动化测试工具生成大量的测试输入,以充分测试待测软件,并验证测试人员编写的性质是否得以满足 [2]。如果性质被违反,则表明软件可能存在错误(bug)。例如,下图是一个待测程序`my_sort()`,其功能是对输入的序列进行排序,并返回排序后的序列。

图片

图2 待测程序

为了测试`my_sort()`, 通常测试人员会编写单元测试用例。编写传统的单元测试需要人工指定测试输入和预期输出。如下图所示,有6个测试用例来测试待测程序。然而,这种方法的缺点在于它非常耗人力,因为对于每一个测试输入,我们都需要手动去指定相应的测试输出。此外,测试的输入有限,依赖于测试人员的知识,因此难以充分测试待测程序。

图片

图3 单元测试用例

然而,如果使用property-based testing,我们仅仅编写一个测试方法就可以覆盖所有的测试输入。一开始,我们根据待测程序的理解,给出待测程序应该有的性质(property)。比如,my_sort()应该满足的一个性质为:返回list中的每一个元素都不应该大于它们之后的一个元素。根据这个性质,我们就可以编写出一个测试用例。注:我们以面向python语言的property-based testing 框架hypothesis为例来编写。

图片

图4 Property-based testing测试用例

如上图所示,代码的第一行 `@given(st.lists(st.integers())` 是一个装饰器,表示一旦测试开始,Hypothesis 将生成大量随机的list作为`test_prop_ordered()`函数的输入。每一个生成的list都将作为参数xs传递给`test_prop_ordered()`函数,并执行函数体,然后验证assert 语句是否为真。这样,我们就可以自动化生成足够多的list来验证待测程序是否满足我们设定的性质,而不用人为地去指定具体的测试输入和输出数据,大大提高了测试效率。

02

如何进行基于软件性质的自动化测试

上节介绍了Property-based testing的概念,这节介绍如何进行基于软件性质的自动化测试。我们用一个通用的模板来解释如何进行property-based testing:

图片

图5 property-based testing模板 

第一步:确定你想要测试的程序性质。如图5中第三行所示,测试人员通过对待测程序的理解来确定想要测试的程序性质。例如,在图4中,该测试用例旨在验证以下程序性质:排好序的list中每一个元素都不应该大于其后的元素。如果在测试过程中违反了这个性质,那么表明待测程序可能出现了一个Bug。

第二步:确定测试输入类型及范围。在完成第一步后,测试人员应该确定将要传递给待测程序的测试输入的类型和范围,如图5中第一,二行所示。例如,在图4中,由于待测程序的功能是对list中的元素的大小进行排序,那么测试输入应该是list。同时,由于排序涉及到元素的大小比较,因此列表中的元素应该是数字。在这里,我们选择了整数(integer)作为元素类型。

第三步:编写并运行测试用例。目前,针对不同的软件或者程序语言,开发人员已经开发出了多种基于性质的测试框架(Java: QuickTheories, Python: Hypothesis, C++: RapidCheck, Scala: ScalaCheck, JavaScipt: fast-check, Ruby: Rantly, Swift: Swiftcheck等等)[3-9]。一旦选择了适合的测试框架,我们就可以利用测试框架编写出相应的测试用例并且运行它们。

03

何选择合适的软件性质

前两节介绍了property-based testing的概念以及如何进行property-based testing,我们可以看出property-based testing是一个非常高效的测试技术。然而,当测试人员真正开始编写测试用例的时候,他们经常会碰见一个问题:应该选择什么样的性质来进行测试?因此,在本节中,我们将介绍一下比较通用的性质 [10],希望可以启发到测试人员如何选择合适的软件性质。

性质1:对称性(Symmetry。如下图所示。如果能够将某些值转换成其他值,然后再转换回来,那么它应该和原值保持一致。例如,序列化(Serialization)就是一个典型的例子。将文本转化成一个对象,然后将该对象转换回来,则文本应该保持不变。

图片

图 6 对称性

性质2:交换性(Commutativity。该性质指的是改变执行操作的顺序,但是最终结果不会变化。例如,如下图所示,将一个list头部加入一个元素,再将其尾部加入一个元素,如果将这两个操作的顺序交换,最终得到的list应该是相同的。

图片

图 7 交换性 

性质3:不变性(Invariants。该性质指的是执行某些操作后,并不会改变测试对象的某些性质。例如,如下图所示,将一个数组排序后,该数组的长度应该保持不变。

图片

图 8 不变性 

性质4:幂等性(Idempotence。该性质一般指多次执行某种操作和执行一次某种操作带来的效果应该是一样的。例如,如下图所示,对于一个列表,对其进行一次排序和多次排序,最终结果应该是相同的。

图片

图 9 幂等性

性质5:推导性(induction。该性质通常指的是,如果一个大的对象可以分成更小的对象,并且对于某些性质来说在这些小的对象上成立,那么可以证明这些性质在大的对象上也成立。例如,如下图所示。如果黑色集合中含有某个元素,那么红色、蓝色、绿色、黑色的大集合中也应该有某个元素。

图片

图 10 推导性

04

总结

基于性质的测试在近些年已经成为了一个非常受欢迎的测试技术,并且开发者们已经开发出了多种基于性质的测试框架。这种技术有非常多的优点,例如,理论上它可以覆盖所有的可能的测试输入,更充分地测试用户关心的功能,以及降低测试成本。然而,由于其特性,也存在一些挑战。例如,由于其只关心想要测试的性质,那么就导致对于某个性质测试得很充分,对于其他性质就根本没有测试到。此外,测试人员需要足够了解待测软件,以抽象出应该保持的性质,这对测试人员的要求比较高。另外,开发一个高效的基于性质的测试框架对于开发人员来说也是一个大的挑战。开发人员需要思考如何使测试人员更轻松地编写性质,以及如何才能开发出更好的数据生成器等。最重要的是,基于性质的自动化测试技术并不意味着取代其他测试技术(例如,单元测试),而是可以与其他测试技术共存。测试人员应该根据测试的需求,选择合适的测试技术,使其更好地服务于软件测试。

参考文献:

[1]https://medium.com/criteo-engineering/introduction-to-property-based-testing-f5236229d237

[2] Claessen, K., Hughes, J.: QuickCheck: a lightweight tool for random testing of Haskell programs. In: Proceedings of the Fifth ACM SIGPLAN International Conference on Functional Programming (ICFP’00), ACM, pp. 268–279 (2000). https://doi.org/10.1145/ 351240.351266

[3] QuickTheories. https://github.com/quicktheories/QuickTheories

[4] Hypothesis. https://hypothesis.works/

[5] RapidCheck. https://github.com/emil-e/rapidcheck

[6] ScalaCheck. https://github.com/typelevel/scalacheck

[7] fast-check. https://github.com/dubzzz/fast-check

[8] Rantly. https://github.com/rantly-rb/rantly

[9] SwiftCheck. https://github.com/typelift/SwiftCheck

[10] https://fsharpforfunandprofit.com/posts/property-based-testing-2/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1072869.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MOM与MES管理系统有哪些本质上的区别

随着企业业务的不断发展,许多制造企业开始面临车间管理失控、生产不透明等问题。这时候,很多企业选择上线MES生产管理系统来提高生产管理水平。然而,随着企业业务的不断拓展,MES系统也逐渐暴露出其局限性。于是,MOM平台…

详解CAN通信的标识符掩码和标识符列表两种过滤机制

CAN 通信的应用非常广泛,本文不涉及CAN通信的基础配置,重点分析一下STM32和GD32的CAN通信两种ID过滤方式。 首先,不管是STM32还是GD32,实现CAN通信ID过滤的机制和原理一定是一样的,只是用到的寄存器有差别。 1. ID过…

TensorFlow入门(十四、数据读取机制(1))

TensorFlow的数据读取方式 TensorFlow的数据读取方式共有三种,分别是: ①预加载数据(Preloaded data) 预加载数据的方式,其实就是静态图(Graph)的模式。即将数据直接内嵌到Graph中,再把Graph传入Session中运行。 示例代码如下: import tensorflow.compat.v1 as tf tf.disabl…

超好用的IDEA插件推荐!

大家好,Apipost 最新推出IDEA插件V2版本!V2版本主要是Apipost 符合更多用户的需求而推出,支持在插件中获取 token、支持代码完成后在插件中进行 API调试 ,同时也保留了1.0版本部分功能如上传选择目录功能等。 V1版本还会继续保留…

韦东山D1S板子——xfel工具无法烧写bin文件到spi norFlash问题解决

1、早期问题排查 (1)参考博客:《韦东山D1S板子——烧录spi norFlash失败问题排查过程》; (2)早期排查到xfel工具烧写spi norFlash显示成功,但是实际没有烧写进bin文件,怀疑是norFlas…

“揭秘淘宝店铺所有商品接口:一键获取海量热销宝贝信息!“

淘宝店铺所有商品接口可以通过shop id或店铺主链接获取到整店商品,数据包括:商品ID,图片地址,店铺标题,优惠价,价格,销量,宝贝链接等整个店铺的商品。 要使用这个接口,需…

Linux 系统性能瓶颈分析(超详细)

Author:rab 目录 前言一、性能指标1.1 进程1.1.1 进程定义1.1.2 进程状态1.1.3 进程优先级1.1.4 进程与程序间的关系1.1.5 进程与进程间的关系1.1.6 进程与线程的关系 1.2 内存1.2.1 物理内存与虚拟内存1.2.2 页高速缓存与页写回机制1.2.3 Swap Space 1.3 文件系统1…

9个最常用的人体姿态估计模型

“姿态估计?”……“姿态”一词对于不同的人来说可能有不同的含义,但我们不是在讨论阿诺德经典、奥林匹亚或选美表演。 那么,姿态估计到底是什么? 那么,让我们深入探讨这个话题。 推荐:用 NSDT编辑器 快速搭…

【git】git命令行

首先要了解git整个流程的一个分类: workspace:工作区staging area:暂存区/缓存区local repository:版本库或本地仓库remote repository:远程仓库 创建仓库 git clone gitgithub.comxxxxxxxxxxxx//拷贝一份远程仓库 …

笔记34:转置卷积 Transposed Convolution 的由来

注:该文章为视频课的笔记补充 视频课:转置卷积(transposed convolution)_哔哩哔哩_bilibili 更详细的推导在:抽丝剥茧,带你理解转置卷积(反卷积)_逆卷积-CSDN博客 a a a 补充1…

3D模型轻量化工具HOOPS Communicator在3D打印行业中的应用分析

3D打印技术自问世以来,已经在制造业、医疗领域、航空航天和建筑等行业中产生了革命性的影响。随着3D打印技术的不断发展,对3D模型的需求也在不断增加。 随着3D模型复杂性的增加,模型文件的体积也不断膨胀,这对计算资源和数据传输提…

当zk某个节点坏掉如何修复

2.1 当zk某个节点坏掉如何修复 当发生zk数据文件丢失(误删或者磁盘损坏节点损坏都可能出现)时,cdh会出现如下告警

CoreData + CloudKit 在初始化 Schema 时报错 A Core Data error occurred 的解决

问题现象 如果希望为 CoreData 支持的 App 增加云数据备份和同步功能,那么 CloudKit 是绝佳的选择。CloudKit 会帮我们默默处理好一切,我们基本不用为升级而操心。 不过,有时在用本地 CoreData NSManagedObjectModel 初始化 iCloud 中的 Schema 时会发生如下错误: Error …

产品工程师工作的职责十篇

一、岗位职责的作用意义 1.可以最大限度地实现劳动用工的科学配置; 2.有效地防止因职务重叠而发生的工作扯皮现象; 3.提高内部竞争活力,更好地发现和使用人才; 4.组织考核的依据; 5.提高工作效率和工作质量; 6.规范操作行为; 7.减少违章行为和违章事故的发生…

菜单子节点的写法

菜单子节点的写法 1.测试数据2.实现代码3.获取父ID层级 1.测试数据 1.表结构SQL CREATE TABLE test (id int DEFAULT NULL,u_id int DEFAULT NULL,p_u_id int DEFAULT NULL ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_general_ci;2.数据SQL INSERT INTO test (i…

解决maven骨架加载慢问题(亲测解决)

1、下载archetype-catalog.xml 网站 : https://repo.maven.apache.org/maven2/ 2、放在这个文件夹下面 3、setting–>build–>Runner : -DarchetypeCataloglocal

访问Apache Tomcat的manager页面

配置访问Tomcat manager页面的用户名、密码、角色 Tomcat安装完成后&#xff0c;包含了一个管理应用&#xff0c;默认安装在 <Tomcat安装目录>/webapps/manager 例如&#xff1a; 要使用管理页面的功能&#xff0c;需要在conf/tomcat-users.xml文件中配置用户、密码及…

学习Consul中踩过的坑

一、杀不死的consul 通过mac的homebrew安装了consul以后&#xff0c;手动启动consul报8300端口已被占用&#xff0c;通过lsof -i:8300和lsof -i:8500查看端口占用情况&#xff0c;发现consul已经启动了。然后手动kill -9对应的进程id&#xff0c;再启动consul&#xff0c;还是…

springboot 如何更新json串里面的内容

我的需求是这样的 如果新字符串中的key在原字符串中存在&#xff0c;则更新原字符串的对应key的value。如果新字符串中的key在原字符串中不存在&#xff0c;则将新字符串中的key和value添加到原字符串中。如果原字符串中存在&#xff0c;新字符串中不存在的key&#xff0c;则不…

亚马逊买家号怎么评论?快速留评软件有哪些?

对于亚马逊买家留评&#xff0c;其实是很简单的&#xff0c;首先亚马逊买家号账号上找到你购买该产品的订单。可以点击页面上的“我的账户”或类似的链接&#xff0c;然后选择“我的订单”或“订单历史记录”。然后选择要评论的订单&#xff1a;在订单历史记录中&#xff0c;找…