gitbook/自动化测试高手课/docs/497405.md
2022-09-03 22:05:03 +08:00

194 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 02|3KU法则:如何找出最优自动化实施截面?
你好,我是柳胜。
上一讲我们提出了自动化测试ROI模型,在回归测试中的应用。回归测试是一个笼统的概念,单元测试、接口测试以及UI测试里都有回归测试,甚至性能测试也已经成为回归测试的一部分。
今天我们要关注一个具体场景,给你一个软件系统,作为自动化测试人员,你怎么找出测试截面,制定自动化测试方案?这些事可能你都做过,觉得并不稀奇,但既然我们已经学习了ROI思维,今天要再加上一个小目标,**制定策略,能够让这个自动化测试设计获得尽可能大的ROI**。换句话说,能干还不够,还要干得好,既要马儿跑,又要马儿少吃草。
有挑战不?那就跟我进入这一讲的学习,一起找到最佳策略吧。
## 测试ROI金字塔
在测试设计领域,经常提到的方法是分层。具体就是给定一个系统,结构上划分三个层级,单元在最小圈;服务包含多个单元,在中圈;而系统又包含多个服务,是外部的最大圈。结构图如下:
![图片](https://static001.geekbang.org/resource/image/77/c3/7713a7081ac2723a2cfc35d3277b21c3.jpg?wh=1920x1050 "软件结构圈图")
相应地,我们的测试结构是在代码层做单元测试,服务层做接口测试,系统层做UI功能测试。
在实践中,这三种测试该怎么组合安排呢?迈克·科恩在2009年他的新书《敏捷成功之道》中首次提出了测试金字塔模型。单元测试自动化在金字塔底部,接口测试自动化在中部,而UI测试自动化在金字塔顶部。
![图片](https://static001.geekbang.org/resource/image/bd/68/bdyy34691cc7a36c8e50f13e3bbaca68.jpg?wh=1920x1050 "分层测试金字塔")
迈克·科恩讲到自动化测试工作量配比时,认为应该按照层面积分配。也就是说,单元测试案例的数目应该多于接口测试案例数目,接口测试案例数目应该多于UI测试自动化测试案例数目。
后来,金字塔模型又被业界发展,赋予了不同的测试策略,比如自底向上执行速度减慢,自顶向下业务属性减弱,技术属性增强。
但迈克·科恩没有解释,为什么各层工作量配比要按照测试金字塔分布?按照软件结构图,系统在最大圈,测试案例应该最多,而到了自动化测试金字塔,UI自动化测试案例却最少;单元测试在小圈,测试案例应该最少,但到了自动化测试金字塔,单元测试案例却最多。
为什么是金字塔?要是不去理解规律背后这个“为什么”,你就用不好这个规律。上一讲我们知道了“ROI其实是自动化测试的隐式命脉”,现在我们就利用ROI思维,分析一下测试金字塔规律。
![图片](https://static001.geekbang.org/resource/image/cd/00/cd34280bc70b3633e696a7ba16f9e300.jpg?wh=1920x868 "ROI公式")
下面,我们分别看看每层的ROI。单元测试可以在开发人员每次code commit触发运行,回归频率高;接口测试在每轮集成测试运行,回归频率中;UI自动化测试在用户验收测试,回归频率低。
按照ROI模型,我们可以得出3种类型自动化测试的ROI排序,如下表:
![](https://static001.geekbang.org/resource/image/71/08/713a743c26347d08d561d5a77ab27608.jpg?wh=3363x1379)
对照测试金字塔不难发现,实际上三类自动化测试的ROI是自底向上由高到低的。
![图片](https://static001.geekbang.org/resource/image/7e/af/7ebe91f53e1fc7a84e53a26d68c4baaf.jpg?wh=1920x1050 "分层测试ROI金字塔")
按照第一讲得出的规律“自动化测试顺序从ROI高到低”,我们优先投入精力做ROI最高的单元测试,再做ROI中的接口测试,最后完成UI测试。
现在就可以轻松解释迈克·科恩的金字塔了,因为ROI存在差异,所以按照高ROI大投入,中ROI中投入,低ROI小投入,工作量比例呈金字塔分布,底层面积最大,顶层面积最小。发现没?**根源在于ROI,金字塔是表现出来的形态而已**。
好,到这里,总结一下。各种软件理论学派,大致可以分为两种,一种是理论基础,讲的是做什么,比如软件测试定义、软件过程,另外一种是实践经验,讲的是该怎么做,比如金字塔模型。
实践和理论很大的不同就是在现实商业中,我们不可能完全按照理想来工作,而是要加入很多制约因素,其中最大的制约就是钱。明白这个道理,你就会知道为什么ROI是根源,你也会知道怎么能够在工作中做出业绩了,不是耍两个工具,忽悠一下领导就算成功,而是认认真真地去思考,踏踏实实地去提高ROI,直到边际效应ROI无法提高为止。
## 寻找最优ROI策略
刚才说了分层测试和各层ROI,业界也很认可这种分层理论,但实际落地时却存在问题:一批人做UI测试自动化,另外一批人去做接口测试,然后开发人员做单元测试。三路人马忙得不亦乐乎,都说自己贡献大,等到bug发生了泄漏到生产环境,又开始甩锅。
### 分层测试为啥会“内卷”
很明显,这是一个内卷的场景,让我们结合例子具体看看内卷发生在哪里?
以一个Web登录操作为例,用户在UI上输入用户名和密码,点击“登录”按钮。Selenium UI 自动化会这样实现:
```plain
@Test
public void login() {
WebDriver driver=new ChromeDriver();
driver.manage().window().maximize();
//打开页面
driver.get("https://www.example.com/users/sign_in");
WebElement username=driver.findElement(By.id("user_email_Login"));
WebElement password=driver.findElement(By.id("user_password"));
WebElement login=driver.findElement(By.name("login"));
//输入用户名
username.sendKeys("liusheng@example.com");
//输入密码
password.sendKeys("123456");
//点击登录按钮
login.click();
}
```
上面UI的操作被Web服务转化成Rest请求,进入到API网关,是这样的:
```plain
curl --location --request POST 'http://auth.example.com/auth/realms/Test/users' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'username=liusheng@example.com' \
--header 'password=123456'
```
在单元上执行的则是这样的代码:
```plain
public Future<ResponseData> login(String userName, String password) {
//入口参数检验
if (StringUtil.isBlank(userName)||StringUtil.isBlank(password)){
return new AsyncResult<>(ResponseData.error("账号密码不能为空"));
}
//查询用户是否存在
List<User> userList = baseMapper.getUserInfo(userName);
if (CollectionUtils.isEmpty(userList)){
return new AsyncResult<>(ResponseData.error("账号不存在"));
}
//验证账号密码是否正确
User user = userList.get(0);
String requestMd5 = SaltUtil.md5Encrypt(password, user.getSalt());
String dbMd5 = user.getPassword();
if (dbMd5 == null || !dbMd5.equalsIgnoreCase(requestMd5)) {
return new AsyncResult<>(ResponseData.error("账户密码不正确"));
}
//生成 access token,并返回
String token = JwtTokenUtil.generateToken(user);
return new (ResponseData.success(token));
}
```
可以看到,一个请求,从浏览器页面发起,进入API网关,再传递到服务里的Login函数,经过了UI测试、API测试和单元测试三个测试截面。
![图片](https://static001.geekbang.org/resource/image/0a/ce/0a1af39ca343083b14fe1472c5610cce.jpg?wh=1920x1045 "三个测试截面示意图")
三个测试截面测的是一个请求在不同层面上的形态,那么每一个截面都可以测试全部的案例,也可以测试部分的案例。就像3个人负责1个项目一样,如果没有经过事先的协调和安排,3个人可能做了重复的事情,造成浪费,也可能存在一件事3个人都没干,形成测试盲区。
### 需求/策略矩阵
这种“内卷”是不是一个问题?可能你会说没问题,各层独立测试能够加强质量保障。说这话的底气在于测试上的投入充足,不计内卷成本。实际上,在DevOps风行的今天,趋势是追求效果和效率。所以,在资源有限的条件下,我们需要在整体上看待分层测试的最优ROI。
咱们先看看测试需求是什么,用 [FURPS模型](https://zh.wikipedia.org/wiki/FURPS)来理一下需求。FURPS是用5个维度来描述一个软件的功能需求,FURPS这个单词对应着每个需求的英文首字母:
* F=Function 功能
* U=Usability 易用性
* R=Reliability 可靠性
* P=Performance 性能
* S=Supportability 可支持性
把测试需求和测试类型组合在一起,就整合了后面这个矩阵表格:
![](https://static001.geekbang.org/resource/image/44/21/443b6845a599a19d27704a3f89b44b21.jpg?wh=4000x1410 "3KU测试矩阵")
结合表格,可以看到UI测试、接口测试和单元测试每个截面的测试能力。
* 在UI层面上,功能性最强,所有测试需求都可以做。这个可以理解,因为软件本身就是满足用户需求,没有一个需求不可以从用户层面感受到。如果真的存在一个需求,用户却无法体验到,那根据[奥卡姆剃须刀原理](https://zh.wikipedia.org/wiki/%E5%A5%A5%E5%8D%A1%E5%A7%86%E5%89%83%E5%88%80),这种用户无法体验到的需求就是无效的。
* 接口层面上,功能性减弱,技术性增强。
* 单元层面上,技术性最强,功能性主要体现在数据的处理,算法逻辑上。
### 3KU整体策略
好,有了需求/策略矩阵后,结合上面讲到的自动化测试ROI金字塔,我们的整体最优ROI策略就呼之欲出了。什么是整体最优ROI呢?
有3个Key(关键因素):
* **U**seful: 每个测试需求都是有效的;
* **U**ltimate: 每个测试需求的验证都在优先寻找自动化ROI高的层面去实现,如果不可行,按照ROI高到低回退,直到UI层;
* **U**nique: 每个层面上验证的测试需求都和别的层面都不是重复的。
这样分配的工作,既不重复,又没遗漏,还遵循了ROI的原则。我管它叫**3KU原则。**
![图片](https://static001.geekbang.org/resource/image/7e/af/7ebe91f53e1fc7a84e53a26d68c4baaf.jpg?wh=1920x1050 "3KU测试金字塔")
3KU策略该怎么执行呢?按照3KU策略,我们把表格里的测试需求,对照下面这三个问题,按顺序检查一遍:
1.能在单元测试验证么?
2.能在接口测试验证么?
3.能在UI测试验证么?
这样检查以后,就能得出各个需求的自动化实现截面了。
UI测试关注功能场景测试,易用性测试和可执行性测试;而接口测试关注不同数据的循环,接口的性能和错误恢复能力;单元测试关注算法的正确性和性能。
恭喜你看到这里,最后就是我们收割成果的环节了。我们又得出了一个满足3KU原则的自动化测试实施金字塔,各层有自己的关注点,又在整体上实现了互相配合补偿。
![图片](https://static001.geekbang.org/resource/image/95/a7/950bdb1892c70d0598cd0657e2ca92a7.jpg?wh=1920x1064 "3KU测试金字塔")
在3KU测试金字塔下,每一个测试需求都会选择最大的ROI测试截面,通过这样的安排,实现了整体最优ROI的目标。对不对?
## 小结
这一讲,我们从ROI角度分析了一下分层测试的原理和在实践中的应用。先入为主地,分层理论上的分层测试的特性,必然会造成重叠和错失。这给测试从业者带来了挑战。但挑战也是机会,如何解决这个问题?
这就需要我们遵循回归到效益的原则,思考怎么用最少的资源干最多的事,能达到这个效果,就是好的实践。因此,我们提出了分层但协调实现整体最优ROI的解决方案,3KU测试矩阵和3KU测试金字塔。
![](https://static001.geekbang.org/resource/image/44/21/443b6845a599a19d27704a3f89b44b21.jpg?wh=4000x1410 "3KU测试矩阵")
![图片](https://static001.geekbang.org/resource/image/95/a7/950bdb1892c70d0598cd0657e2ca92a7.jpg?wh=1920x1064 "3KU测试金字塔")
沿着这个思路,各层做好自己具有优势能力的测试需求,比起全部需求系于端到端的测试上,更有效率和效益,**分层是追求整体ROI的结果**。之后的课程里我们还会反复提到ROI,最后你也会不由感叹,ROI是背后无形的大手,大道无形,无处不在。
## 思考题
1 软件大师马丁·福勒曾经说过:“在微服务时代,分层测试不再呈现金字塔形状。”这是为什么?试着用ROI来解释一下。
2 学完今天的内容,如果你是测试主管,你希望你的团队是全栈(一个人负责一个模块的所有层面测试),还是精细分工(一个人负责所有模块的一个层面测试)?有什么优劣?
欢迎你在留言区跟我交流互动,如果这一讲对你有启发,也推荐你分享给身边更多同事和朋友。