怎么制作自己的头像logo南宁百度推广seo

构建测试知识体系,点击关注
“ 测试数据的准备,是软件测试工作中非常重要的环节,无论是手工测试还是自动化测试都避不开测试数据准备工作。今天我们就来聊一聊测试工作中常用的测试数据准备的方法,深入了解各自的优缺点和使用场景,以及测试数据准备工作未来的发展方向。”
正文字数 5256
我曾经用过的生成测试数据的方法,主要有以下几类:
使用GUI界面生成测试数据
使用API生成测试数据
插入或更新DB生成测试数据
写Kafka生成测试数据
使用pypi上的库生成测试数据
综合运用上述方法生成测试数据
接下来,我们一起详细分析一下各种方法的优缺点以及适用场景。并对测试数据什么时候准备,是测试前准备还是测试执行时准备做些讨论。
01
—
使用GUI界面生成测试数据
基于GUI界面进行测试数据准备,是最原始的创建测试数据的方法,这种方法其实是采用E2E的方法来执行业务场景,然后得到测试数据。
比如,测试用户登录功能,那么需要准备的测试数据就是用户账号,为此我们可以通过APP或者WEB端的GUI页面注册新用户,然后用这个用户完成用户登录功能的测试。
这种方法的优点是简单直接,创建的数据来自于真实的业务流程,最大程度保证了数据的正确性和完整性。在很多手工测试的场景中,这种方法被普遍采用。
但是,这种方法的缺点也非常明显,主要体现在以下几个方面:
创建测试数据的效率低,不适合批量生成测试数据。 因为通过GUI操作每次只能创造一条数据,而且通过手工操作GUI的过程也是比较耗时。
基于GUI的测试数据生成方法不适合为自动化测试提供数据。 由于自动化测试往往是通过代码来准备测试数据,而GUI方法生成测试数据的方法不太适合封装成代码被自动化测试用例调用。因为封装GUI方式生成测试数据的方法,本质上是在开发GUI自动化测试用例,而我们知道无论是开发工作量还是执行效率,亦或是稳定性方面,这种方法都不是最佳的选择。
会引入不必要的测试依赖。 比如测试用户登录功能,如果依赖GUI先注册一个用户,那么就意味着注册功能必须是没问题的,引入了依赖。这种情况,从数据库中找到一个已注册的账号来测试登录功能才是最佳选择。
在前后台配合的手工测试中,比如内容管理系统CMS和手机APP的测试,如果要手工测试手机APP的文章列表功能,那么就可以采用这种方法。除此之外,基于GUI操作生成测试数据的场景并不多。
基于GUI生成测试数据的方法,有一个非常重要的价值是帮助我们在创建测试数据的过程中,找到创建数据的过程中都调用了哪些API以及修改了哪些DB的表。只有了解了这两个方面,我们后续通过API或者修改DB方式创建测试数据时,才能保证数据的完整性。
02
—
使用API生成测试数据
通过调用API生成测试数据,是目前测试数据生成的主要方法。由于后台接口一般比较稳定,大大提高了测试数据构造的效率、准确性和成功率。另外,由于我们直接给API传递参数,通过参数的组合可以构造成某些GUI方法不能构造出来的测试数据。
那么,我们如何获取到这些API呢?通常推荐按照下面的顺序,来查找API相关的信息。
API接口文档。 通常成熟的开发团队,都会编写API的接口文档,接口文档中会详细描述接口的URI和调用参数,这是最直接有效的办法。
通过抓包。 抓包在测试中是非常常用的辅助手段,我们可以在操作APP或者WEB页面的时候,对操作进行抓包,通过对抓取到的请求包,分析接口的各种参数。这也是相对高效的办法。
查看日志文件。 对于已经上线的接口,我们可以通过服务的日志,来查看接口调用过程中的URI和参数等内容。
阅读源码。 如果前面三种方法都不能用,那么可以在Gitlab上查看开发人员的项目代码,通过阅读代码的方法,找到接口请求的各种参数。
通过API构造测试数据的方法也不是完美的,主要有几个方面:
不是所有的数据创建都有对应的API。
有时候需要顺序调用多个API。 有时候测试数据之间是有关联关系的,为了保证测试数据的完整性和一致性,需要依次调用多个API,无形中增加了测试数据准备的复杂性。
调用API创建测试数据,天生适合与自动化测试相结合,在实际的测试实践中,我们往往会把API封装成测试数据准备函数供自动化测试用例使用。当API内部逻辑有修改时,我们依旧可以通过封装函数来准备测试数据,对测试用例来说,是完全透明的。
这里所说的API指的是基于HTTP协议的Restful API。但是可以扩展到其他协议的各种调用接口,比如MQTT协议、RPC协议等。
03
—
插入或更新DB生成测试数据
往数据库中插入或者更新数据,也是非常常用的构造测试数据的方法。具体做法是,将创建测试数据的SQL语句封装成一个个测试数据生成函数,当我们创建数据时,直接调用这些封装好的函数即可。这种方法有一个非常大的优点是生成测试数据的效率非常高,可以短时间内往数据库中插入大量的测试数据。
以用户登录功能测试为例,当我们调用API进行用户注册时,这个API会将用户的详细的信息插入到user表和role表两个数据库表中。如果我们采用数据库方式创造数据时,给user表和role表分别插入对应的数据就完成了用户的注册。我们还可以直接使用DB中已有的数据作为我们的测试数据,从而省去了很多操作。
这里的前提是,你必须知道进行新用户注册时,到底涉及到了哪些数据库的表。最直接的办法就是跟开发同学索要SQL语句,或者查看源代码。
这种构造测试数据的方法也不是完美的,主要体现在以下几个方面:
有的测试数据准备涉及到的数据表太多。 导致封装和维护测试准备函数的成本比较高。
容易出现数据不完整和不一致。 比如服务A某一个业务,实际会在服务A的数据库表A和数据库表B中分别插入数据,并且同时会给kafka的某个topic发送数据供服务B消费处理后持久化到服务B的数据库表C中。如果我们漏掉了某个数据库表的插入操作,可能会导致数据的不完整和不一致。
基于DB准备测试数据的方法,通常作为API方法的补充。
04
—
写Kafka生成测试数据
在微服务架构中,通常会存在通过消息中间件、或者流处理平台将多个服务进行解耦,为了减少测试工作的依赖,通常会往kafka中构造测试数据。
比如,两个服务是通过Kafka进行消息传递的,两个服务分别作为Kafka的生成者和消费者。当我们测试作为消费者的服务时,就可以编写Kafka的producer代码,往Kafka中生产测试所需要的测试数据。具体的做法与通过DB构造测试数据的方式类似,将Kafka的producer代码封装成测试数据生成函数,当我们创建数据时,直接调用这些封装好的函数即可。
这种做法和操作DB并没有本质不同,其优点和缺点也是类似的。
05
—
使用pypi上的库生成测试数据
测试实践中,经常会需要生成很多随机的数据,对于这类需求,直接使用代码封装成函数生成数据。拿python为例,可以自己结合random()之类的函数随机生成数据,还可以使用Faker(https://pypi.org/project/Faker/)这样的第三方库来实现:
from faker import Fakerfake = Faker()fake.name()# 'Lucy Cechtelar'fake.address()# '426 Jordy Lodge# Cartwrightshire, SC 88120-6700'fake.text()
这类生成测试数据的方法适用的场景是,对数据本身的数值不关心但是测试中又必须需要这些参数的情况。
06
—
综合运用上述方法
在实际工作中,很少使用单一的方法就能满足测试的需求,往往是综合运用上述各种方法、一个典型的应用场景是,通过API生成最基础的测试数据,比如车辆的vid,然后使用数据库和Kafka的方法生成符合测试需要的车辆状态数据。
比如我们要测试车联网云端对车辆上报的报警数据的处理是否符合要求。首先,我们需要通过调用注册Vechile ID的接口来注册一台车并且获得车辆证书,通过调用这个接口我们可以得到一个车辆的ID以及证书数据。再结合MQTT协议产生车辆的报警数据。
为了构造测试数据的更加便捷,我们往往是对上面的操作进行封装。用封装后的方法产生测试数据。
07
—
何时创建测试数据
前面介绍了准备测试数的方法,那么应该在什么时候创建好所需要的测试数据。是在测试用例执行中创建测试数据(On-the-Fly方法)还是在测试执行前就准备好测试数据(Out-of-Box方法)。
其实,创建测试数据的时机要根据实际的需要来。主要参考一下几个因素:
创建测试数据所需要的时间。 如果创建数据需要花很长时间,那么最好采用Out-of-Box方法,在测试执行之前就准备好,以减少整个测试执行的时间。
测试数据是否需要经常变动。 如果测试数据不需要经常变动,那么最好采用Out-of-Box方法。如果事先生成数据在测试用例中会失效,比如具有有效期的数据,那么就适合采用On-the-Fly方法,在测试执行中创建。
测试数据是否存在于很多系统。 如果测试数据需要在很多系统中都要创建各自的部分,各自又有很多依赖关系,那么就适合Out-of-Box方法。因为在测试用例执行中创建,会导致测试代码比较臃肿,不够清晰。
构造测试数据的服务是否稳定。 在不太稳定的服务中构造测试数据,会产生大量构造测试数据失败的情况。这种情况下采用Out-of-Box方法还是比较明智的。
接下来,我们详细看一下On-the-Fly方法和Out-of-Box方法各自的特点,以及适用场景。
08
—
实时创建(On-the-Fly)
实时生成测试数据的方法,指的是在测试用例代码执行过程中即时创建测试数据。比如,测试车辆驾驶中,不能执行远程控制命令的场景。在测试执行中,可以通过封装的MQ方法设置测试车辆的车辆状态处于驾驶中,接下来就可以测试远程执行命令了。
实时创建的测试数据通常是对某一个或一些测试用例起作用的,不同的测试用例都有自己专属的测试数据。像这种车辆状态数据就适合采用实时创建方法创造,这种状态数据通常是每个测试用例都不同。这种构造测试数据的好处是,避免测试数据在测试用例执行前被修改而产生非预期的测试结果。这样的测试数据使用完之后,通常在测试用例结束之后,恢复成原始数据,避免影响其他测试用例。
在测试中,只能被使用一次的测试数据,也通常会采用实时创建的方法。
实时创建解决了测试用例之间数据之间干扰的问题,也避免了测试完之后的脏数据问题。但是随着软件架构的发展,以及测试频率的提高,这种方式的弊端也逐渐显示出来了,主要有以下几个方面:
首先,有的测试数据比较耗时。 在测试用例执行过程中实时创建测试数据,会导致测试用例执行的时间被拉长。如果测试用例特别多,测试频率又特别高,那么测试时间就变得特别长。
其次,测试数据本身之间复杂的关联性导致构造困难。 很多时候,你为了测试某一个场景,需要构造一堆相关联的测试数据,也是偏向业务链后台的测试数据,这个问题越明显。
比如,要测试被授权人对车执行远程控制命令的场景。会需要车主账号、被授权人账号、车辆ID、车辆ID与车主账号绑定,车主给被授权人授权车辆等前置数据。如果在测试用例执行中准备这些测试数据,那肯定是崩溃的。如果每一个测试用例都这么做,一定会导致测试时间变得非常长。为了解决这个问题,可以考虑将一部分稳定的数据事先创建好,比如车主账号、被授权人账号、车辆ID以及授权关系等数据。
微服务架构的流行导致成功生成测试数据的稳定性降低。现在大量互联网应用采用微服务架构,不同功能划分为更多的微服务独立开发和部署,很多时候测试环境里面,这些微服务并不是100%可用的。也就是说,不是任何时候构造测试数据都能成功。比如你测试的微服务B,需要依赖微服务A构造数据,而这时候正好微服务A不可用,这就block了微服务B的测试。
09
—
提前创建
为了解决上面的问题,在测试之前准备测试数据的方法,也是比较常用的。
事先准备测试数据,指的是在测试用例执行前,就已经准备好了所用的全部或者部分测试数据,而不是在测试用例中实施创建。因此,执行测试用例时候,可以节省不少准备测试数据的时间,同时也避免因为依赖的测试数据准备服务不可用导致测试被block的情况。
事先准备测试数据,可能遇到以下几个问题:
最主要的问题是有效性问题,就是有测试执行中发现测试数据不可用的风险。比如,测试被授权人远程执行车控命令的场景,当你执行测试时,发现被授人的身份已经被车主账号删掉了,这样就导致测试用例执行失败,也就不能顺利完成测试了。
由此可见,这些提前创建好的测试数据,有可能在测试用例执行时已经不可用了,因为这些数据有可能已经进行了非预期的修改。比如,在其他测试用例执行时,使用了这个测试数据,并修改了这些数据的状态。
为了解决这个问题,我们通常采用优化测试管理流程,让不同的测试人员、测试业务都有自己独立的测试数据,并且统计在confluence、jira或者其他公共平台上,大家严格遵守,不要乱用测试数据。
实际工作中,我们通常是采用实时创建和提前创建这两种方式相结合的方式来准备测试数据。我们可以根据测试目的的不同,将测试数据划分为”固定数据”和“易变数据”。
比如某些测试场景中,车辆ID、车辆Profile、车主账号等信息是相对稳定、不经常变化的数据,那么我们可以将这些测试数据称为“固定数据”,这类数据适合采用提前创建的方式创建。
但是在某些测试场景中,比如车辆ID的注销,车辆Profile的变更测试,那么车辆ID、车辆Profile就不能叫做“固定数据”而是应该叫做“灵活数据”,这类数据适合采用实时创建方式准备。
综合运用这两类方法,可以满足大部分测试数据准备的场景。可以解决准备测试数据耗时长、准备测试数据成功率不高等问题。
10
—
总结
本文介绍了6种常见的准备测试数据的方法,并说明了各自的优缺点,大家可以根据测试工作的实际情况选择或者组合使用。根据测试数据的特点不同,可以提前创建,也可以实时创建。实际的工作中,提前创建相对固定的测试数据,实时创建相对灵活的测试数据。
参考资料
这门课,对于开拓测试思路,搭建适合自己业务场景的测试策略很有帮助的。
点个在看,多发现一个Bug