You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
12 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 17元数据模型小Job模型构建大蓝图
你好,我是柳胜。
在价值篇我们学习了3KU整体最优分层模型。而到了策略篇又结合一个具体的订餐系统为你提供了一个测试设计实现案例演示具体如何应用3KU法则。
不过推演下来你有没有隐约感觉到事情有点不对劲了以前我们是先分层再在每个层上设计自己的TestCaseUI上的TestCase的功能定义和粒度大小可能和API层上的TestCase完全不一样。
现在不同的测试需求可能会落到不同的分层截面上去做自动化。甚至一个测试需求的不同部分也可以放在不同截面上。比如你可以在API上测试createOrder在UI上测试verifyOrder只要这样做ROI最高。
所以在3KU法则下自动化测试设计是先定义TestCase然后再判断它应该落在哪个层面。这跟我们以往熟悉的自动化测试设计大相径庭需要我们在设计方法论上有新的突破。没错现在我们的挑战是需要找到一种新的概念指导我们做任务建模和设计从而跨越各层的“TestCase”。
因为内容比较多,为了让你跟得上,我安排了两讲内容,带你**找到一个测试设计的元数据模型,将各种类型和层次的测试纳入到这同一个模型里。一生二,二生三,三生万物,从这一个模型里,衍生出我们自动化测试中所需要的设计方法和策略、执行计划,效益度量甚至生死定夺等等一切**。
“好大的口气”,看到这里,我猜你会这么说,不过,你不妨耐心看完后面的内容,相信会改变你以往的认知,换一个新的角度来审视自动化测试,能抓住最关键的东西做好设计。
## TestCase的设计态和运行态
设计新模型前,我们有必要先分析一下,原有自动化测试设计有什么问题。我们可以从设计态和运行态复盘一下,自动化测试的产生过程是怎样的,借此发现问题。这里,我们延续之前那个订餐系统的例子讲解。
先看**设计态。**设计态下自动化测试表现为测试案例一个测试集合TestSuite包含了多个测试案例TestCase。TestCase测试案例里的信息包含以下元数据测试名字、测试环境、测试步骤、测试结果等等。
对于订餐系统里“订餐”这个测试案例,就会这么写。
* 测试名字:下单
* 测试环境Web终端
* 测试步骤:第一步,登陆订餐系统;第二步,选择餐品、收货地址;第三步,下订单
* 预期结果:下单成功,产生物流配送记录
然后,我们对应到运行态。在**运行态**下,也就是自动化测试跑起来,就成为了一个运行的程序功能。这个程序功能有自己的运行环境、对外依赖和数据交互,我们可以用微服务的六边形架构方法(参看[第七讲](https://time.geekbang.org/column/article/502863)描述订餐Job的运行态结构。
![图片](https://static001.geekbang.org/resource/image/df/69/df80f398d588e6084b23445934d4db69.jpg?wh=1920x1285 "自动化测试案例:六边形模型架构")
看到了没有运行态的Job相比设计态的测试案例多了不少信息包括输入Inbound、输出Outbound、DAO我们依次来看看。
* **Inbound**本Job运行开始之前接收的外部输入Input。
* **Outbound**本Job运行结束之后对外的输出Output。用户在订餐系统完成下单后会产生一个物流单号比如123456。
* **DAO**Data Access Object, 本Job运行中需要持久化的信息。本次订餐测试运行结果的序列化存储到数据库或文件里。
## 原本的设计存在什么问题?
分析完自动化测试的设计态和运行态长什么样,从内部和外部两个角度,我们很容易发现问题。
从内部看传统的测试案例里的元素和自动化测试Job里的信息差别较大。用咱们现在流行的“元”概念来说就是两者的元数据不一致。在基因上它们是两个物种。
从外部看传统测试案例之间关系比较松散即使刚开始测试人员遵循规则来产生案例但时间长了也很难维护案例设计逻辑的一致性和完整性。而自动化测试Job从一开始就互相咬合在生命周期中遵循软件扩展和持续重构的规律腐化或是优化。
这些问题导致了,自动化测试从设计态转化成运行态困难重重。反映到现实中,我们看到就是,测试案例设计和自动化测试实现脱节,貌合神离、各玩各的。造成的结果也很明显,就是自动化测试缺失了设计。代码一旦没有了设计,它的功能、效率、维护性、投产比都失去了追踪和控制。
那怎么解决这些问题呢?咱们开个脑洞,从软件设计的角度,重新审视一下自动化测试应该怎么做。
面向对象设计里有Interface和Class概念Interface定义行为表现Class负责具体实现Abstract Class提供代码重用。一个Interface可以有多个实现如果修改了Interface那么Class也需要修改。
设计和实现解耦,但又保持一致,这个机制使得代码有内建生命力,有扩展能力而不会垮掉,对不对?
其实,我们可以把这个设计思路引入到测试模型里测试案例设计就相当于定义Interface暴露契约要提供什么样的功能、达成什么目标但是Interface不能实例化更不能运行。
自动化测试Job就是实现了Interface的Class有血有肉能实例化也能跑。对一个测试案例可以有不同的自动化实现手工测试也相当于是测试案例的另外一个实现。如何定义这个Interface就是我们要找的测试元数据模型。
好,说到这里,我们简单总结一下到现在的观点。
1.自动化测试和手工测试共用一套案例模型和设计方法。TestSuite和TestCase这些概念已经过时了需要找到新的模型。
2.自动化测试设计本质是软件设计精髓在于对测试场景的抽象和建模。这就像开发软件先设计Interface一样而自动化测试工具和框架属于实现层面用哪个取决于需求而不能削足适履。
## **初探微测试Job模型**
有了前面的推导,我们现在试图找到一个大一统的测试元数据模型,用它描述一个测试案例的设计态和运行态。为了区别于传统的测试案例,还有自动化测试脚本的叫法,我们管它叫**自动化测试Job**。
回顾一下运行态里的六边形其实它已经初步勾勒出一个Job模型但它还是像一个开发的通用模块现在我们继续丰富它**添加更多的自动化测试基因,这个基因满足自动化测试的基本原则**(你可以回顾[第一讲](https://time.geekbang.org/column/article/496857)让它成为一个针对自动化测试的Job。
为了对齐自动化测试的术语习惯我们把Inbound重命名为Input把Outbound重命名为Output。
![图片](https://static001.geekbang.org/resource/image/e9/eb/e92bdfde99ffc5e5ca03c81f8f1214eb.jpg?wh=1920x1285 "自动化测试Job六边形模型架构")
### 模型属性
先说结论我们的自动化测试Job模型除了上面的Input、Ouput和DAO 三个属性下面还要加上Dependency、TestData、TestConfig、Document四个属性一共七个属性。
这七个核心属性其实是你在设计自动化测试案例时需要考虑的七个方面也是后续开发中要去实现的Interface接口
这么多属性“扑面而来”,你也许有点应接不暇。别慌,下面我结合订餐系统例子,逐一给你解释。
对于自动化测试我们需要创建一个依赖的概念目的是通过阻断错误在Job链条上的传递、扩散来缩短自动化测试的执行时间。Depedency的Job如果失败了那么后续的Job没有必要再去运行。因此我们要在后面的模型示意图中用一个红色菱形描述这个**Dependency。**它的数据表达类型是List存放1个或n个前置Job的名字。
结合具体例子Depdency的使用场景更好理解。在下图我们有2个Job一个是登陆的Job另外一个是下单的Job让下单Job的前置依赖是登陆Job登录成功后才要运行订餐案例登陆失败则不必运行订餐案例。
![图片](https://static001.geekbang.org/resource/image/d7/66/d7d533dee50603f28b6a7d4a59f38166.jpg?wh=1920x702 "自动化测试Job模型Dependency")
除了可以引入Dependency概念帮我们缩短测试执行时间要想提升测试ROI还有什么着手点呢
早在[第四讲](https://time.geekbang.org/column/article/499382)我们就说过要提高自动化测试的ROI一个方法就是增加自动化测试的运行次数。所以从设计的角度来看我们的期望是一份代码运行多次。这里的“多次”可以是多个场景、多个语言、多个客户端、多组数据不管哪种都是数据驱动的循环迭代。
所以每一个自动化测试Job应该有一个自己的**数据源TestData**它的数据表达类型是Hashmap存放相似特征的N条KVKey Value数据记录每一条KV记录触发一次Job运行。
看到这里可能你会产生这样的疑问在TestNG和Junit框架里都有DataProvider机制不就有了你说的TestData功能么也不是我们这里谈的是自动化测试Job的特征提取和建模各个框架的DataProvider也好DataValue也好都是对模型的实现。
很好我们又完成了一个TestData机制让1份代码的产出效益翻n倍。
## 课程小结
为了设计一个更科学的模型****我们从传统自动化测试设计入手,通过传统自动化测试的设计态和运行态对比,看到了设计与实现之间的鸿沟。类似的鸿沟举不胜举,比如手工测试与自动化测试之间,测试分层之间。
从测试整体看我们投入了这么多资源和精力初心是编一张大网来捕捉bug的但实际上却是各个小网工作有重复、有遗漏而这些问题不能度量也无法提升。
为了编好大网我们找到了一个统一的Job模型用这个模型来设计我们各种类型各个层次的自动化测试那我们不仅能明确大网有没有重复和遗漏甚至网眼密度也可以统一。
这个Job模型包含七个属性你在设计自动化测试的时候需要把这七个属性想清楚。今天我们讲到了其中的5个属性Input、Output、DAO、Dependency和TestData。
Input和Output要声明测试Job输入和输出是什么DAO要解决自动化测试报告和Log的格式和持久化怎么做的问题Dependency要回答的问题是测试Job依赖的前置条件是什么谁来提供而TestData要回答的问题是测试Job需要的测试数据是什么结构有多少组
![图片](https://static001.geekbang.org/resource/image/3d/10/3da443024e8facbd7d7a6b160c16a710.jpg?wh=1920x1003 "模型属性速记图")
在下一讲,我们会介绍剩下两个属性,并继续分析自动化测试设计中你必须关注的其他问题。比如,怎么保证自动化测试健壮性,你可以自己先想一下,我们下一讲一起探讨。
## 思考题
说一下你设计自动化测试任务的时候,有哪些比较好的实践,怎么在团队里推行的?
欢迎你在留言区跟我交流讨论,也推荐你把这一讲分享给更多朋友。