软件测试回顾(9)准备测试数据 35章:如何准备测试数据?测试数据准备方法主要可以分为四类:
1.基于GUI操作生成测试数据优点:
缺点:
在实际的测试过程中,我们很少直接使用基于GUI的操作生成测试数据。基于GUI操作生成测试数据的方法一般只用于手工测试 2.基于API调用生成测试数据通过API调用生成测试数据,是目前主流的测试数据生成方法。 为了规避在创建测试数据时过于在乎实现细节的问题,在实际工程实践中,我们往往会把调用API生成测试数据的过程封装成测试数据准备函数。 怎么才能知道到底调用了哪些后端API呢?这里,我推荐三种方式:
优点:
缺点:
3.通过数据库操作生成测试数据通过数据库操作生成测试数据,也是目前主流的测试数据生成方法。 常见的做法是,将创建数据需要用到的SQL语句封装成一个个的测试数据准备函数,当我们需要创建数据时,直接调用这些封装好的函数即可。 这样做的前提是,你需要知道前端用户通过GUI操作注册新用户时,到底修改了哪些数据库的业务表。这里,我也推荐三种方式:
缺点:
4.综合运用API和数据库的方式生成测试数据最典型的应用场景是,先通过API调用生成基础的测试数据,然后使用数据库的CRUD操作生成符合特殊测试需求的数据。 36章:测试数据创建的时机要分为On-the-fly(实时创建)和Out-of-box(事先创建测试数据)两类方法。 1.On-the-fly(实时创建)在测试用例的代码中实时创建要使用到的测试数据。 采用On-the-fly方式创建的数据,都是由测试用例自己维护的,不会依赖于测试用例外的任何数据,从而保证了数据的准确性和可控性,最大程度地避免了出现“脏”数据的可能 缺点:
2.Out-of-box(事先创建)为了解决上述三个问题,Out-of-box(即事先创建测试数据)的方式就应运而生 Out-of-box方法,又称开箱即用方法,指的是在准备测试环境时就预先将测试需要用到的数据全部准备好,而不是在测试用例中实时创建。 缺点:Out-of-box最致命的问题是“脏”数据。 那到底什么是“脏”数据呢?这里的“脏”数据是指,数据在被实际使用前,已经被进行了非预期的修改。 这些事先创建好的测试数据,在测试用例执行的那个时刻,是否依然可用其实是不一定的,因为这些数据很有可能在被使用前已经发生了非预期的修改。 这些非预期的修改主要来自于以下三个方面:
为了解决这些“脏”数据,我们只能通过优化流程去控制数据的使用。业内有些公司会将所有事先创建好的测试数据列在一个Wiki页面,然后按照不同的测试数据区段来分配使用对象。 更糟糕的是,如果自动化测试用例直接采用硬编码的方式,去调用那些只能被一次性使用的测试数据(比如订单数据、优惠券等)的话,你会发现测试用例只能在第一次执行时通过,后面再执行都会因为测试数据的问题而失败。 Out-of-box方法不适用于只能一次性使用的测试数据场景。 3.综合运用On-the-fly和Out-of-box实际的工程实践中,往往是采用综合运用On-the-fly和Out-of-box的方式来实现测试数据的准备的。 在实际的测试项目中,我们可以根据测试数据的特性,把它们分为两大类,用业内的行话来讲就是“死水数据”和“活水数据”。 “死水数据”是指那些相对稳定,不会在使用过程中改变状态,并且可以被多次使用的数据。比如,商品分类、商品品牌、场馆信息等。这类数据就非常适合采用Out-of-box方式来创建。 这里需要特别说明的是,哪些数据属于“死水数据”并不是绝对的,由测试目的决定。 比如,用户数据在大多数的非用户相关的测试用例中基本属于“死水数据”, 但是,对于那些专门测试用户账号的测试用例来讲,往往会涉及到用户撤销、激活、修改密码等操作,那么此时的用户数据就不再是“死水数据”了,而应该按照“活水数据”处理。 “活水数据”是指那些只能被一次性使用,或者经常会被修改的测试数据。最典型的数据是优惠券、商品本身、订单等类似的数据。这类数据通常在被一次性使用后状态就发生了变化,不能反复使用。那么这类测试数据,就更适合采用On-the-fly方式来创建。 个人觉得一定要大家使用一套产生测试数据的脚本,无论是api还是数据库,做到一键配置、恢复测试数据。还有就是死水数据的准备大家最好有统一的平台进行发放,而不是随便写,随便测 37+38章:统一测试数据平台1.测试数据准备1.0时代这个阶段最典型的方法就是,将测试数据准备的相关操作封装成数据准备函数。 利用这种数据准备函数创建测试数据方法的最大短板,在于其参数非常多、也非常复杂。 其实,绝大多数的测试数据准备场景是,你仅仅需要一个所有参数都使用了缺省值的测试数据,或者只对个别几个参数有明确的要求,而其他参数都可以是缺省值的测试数据。 为了解决这个问题,在工程实践中,就引入了如图1所示的封装数据准备函数的形式。 当测试用例中仅仅需要一个没有特定要求的默认用户时,你就可以直接调用这个createDefaultUser函数, 对于那些测试用例只对个别参数有要求的场景,比如只对参数A有要求的场景,我们就可以为此封装一个createXXXUser(A)函数,用默认值初始化参数B、C、D、E,然后对外暴露参数A。 如果是对多个参数有特定要求的场景,我们就可以封装出createYYYUser这样暴露多个参数的函数。 通过这样的封装,对于一些常用的测试数据组合,我们通过一次函数调用就可以生成需要的测试数据;而对于那些比较偏门或者不常用的测试数据,我们依然可以通过直接调用最底层的createUserImpl函数完成数据创建工作。可见,这个方法相比之前已经有了很大的进步。 缺点:
为了可以进一步解决这三个问题,最大程度地简化测试数据准备工作,将测试数据准备推向了2.0时代。 2.测试数据准备2.0时代数据准备函数不再以暴露参数的方式进行封装了,而是引入了一种叫作Builder Pattern(生成器模式)的封装方式。这个方式能够在保证最大限度的数据灵活性的同时,提供使用上的最大便利性,并且维护成本还非常低。 就是之前是代码直接调用生成函数,而现在是生成函数类似使用了生成器设计模式而已 你需要准备一个用户数据,而且对具体的参数没有任何要求。
你现在还需要一个用户,但是这次需要的是一个美国的用户。
你又需要这样一个用户数据:英国用户,支付方式是Paypal,其他参数都是默认值。
在实际工程项目中,随着Builder Pattern的大量使用,又逐渐出现了更多的新需求,为此我归纳总结了以下4点:
为了能够满足上述的测试数据需求,我们就需要在Builder Pattern的基础上,进一步引入Build Strategy的概念。顾名思义,Build Strategy指的是数据构建的策略。 就是在简单的生成器模式下合入了策略模式,,通过策略进行生成 我们引入了Search Only、Create Only、Smart和Out-of-box这四种数据构建的策略。这四类构建策略在Builder Pattern中的使用很简单,只要按照以下的代码示例指定构建策略就可以了:
这里的Builder Pattern是基于Java代码实现的,如果你的测试用例不是基于Java代码实现的,那要怎么使用这些Builder Pattern呢?我们不希望、也不可能为每套基于不同开发语言的测试框架都封装一套Builder Pattern。所以,我们就希望一套Builder Pattern可以适用于所有的测试框架,这也就是我在前面提到的测试准备函数的“跨平台的能力”了。 为了解决这个问题,测试数据准备走向了3.0时代。 3.测试数据准备的3.0时代为了解决2.0时代跨平台使用数据准备函数的问题,我们将基于Java开发的数据准备函数用Spring Boot包装成了Restful API,并且结合Swagger给这些Restful API提供了GUI界面和文档。 就是将测试准备函数 变成了web工具,通过restful api进行统一调用,来实现跨平台 我们就可以通过Restful API调用数据准备函数了,而且由于Restful API是通用接口,所以只要测试框架能够发起http调用,就能使用这些Restful API。于是,几乎所有的测试框架都可以直接使用这些Restful API准备测试数据。 最初,统一测试数据平台就是服务化了数据准备函数的功能,并且提供了GUI界面以方便用户使用,除此以外,并没有提供其他额外功能。如图1所示就是统一测试数据平台的UI界面。 后来,随着统一测试数据平台的广泛使用,我们逐渐加入了更多的创新设计,统一测试数据平台的架构也逐渐演变成了如图2所示的样子。 接下来,我和你分享一下统一测试数据平台的架构设计中最重要的两个部分:
我看老师的留言下面有个人说怎么一直在科普概念。我认为老师的这段回复很好 很多时候概念本身比会使用工具来得重要的多,对于测试数据准备的文章中介绍的很多方法和理念都是外面找不到的,都是来自于大项目中的工程实践,如果大家对工具本身的使用更感兴趣,我还是建议通过官方文档进行学习,但是怎么找到适合你的工具,以及学习这些工具设计的思路,还是要能够掌握原理。 |
|