开发者学堂课程【ALPD 云架构师系列:云原生 DevOps 36计-阿里云云效出品:基于测试的质量守护:分层测试、测试自动化、单元测试】学习笔记,与课程紧密连接,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/772/detail/13518
基于测试的质量守护:分层测试、测试自动化、单元测试
内容介绍:
一、整体测试策略
二、质量与成本的平衡关系
三、常见的分层策略
四、基于预防角度的单元测试的选择性策略
一、整体测试策略
1、服务结构讲解
举个例子,基于外普服务端的开发,现在都在采用微服务的方式,打开一个服务的结构查看,
从结构上看,存在资源层,更多的是对领域对象的映射,此外存在服务层和相应的网关,与外面进行通信,最后就是持久化的存储。
这是典型的微服务的一个例子,如果进行相应的保障,整体的测试策略,如下
2、整体策略结构
打了红色斜线的为做单元测试来保证质量,因为只对小框测试,可能是内部的模块进行测试,比如说:仅测试设备的某一个接口,或者某一个函数,某一个方式,在这个基础上将框变大一点,也就是组件之间的接口是否可以交互是正确的,也可以在大一点,也就组件里面排除外部的依赖,外部依赖分两个:一个是数据依赖,一个是网络的消息依赖,排出完成后,里面的测试是什么样的,此时接口部分偏外部一层,更多是和网关结合的结构,是数据持续化接口的一个测试,完成后,将外部进行交流,如应用a,之间存在协议,为2个应用的交互基于一个协约或者契约,两者之间的契约是work的,称之为契约测试。
完成后,在更大的框外面,多个应用组合在一起,端到端的应用,不仅是一个应用而是完整的系统组合在一起,一个完整的系统,在整个用户和整个业务的请求的角度,去看这个测试,从整个测试的策略来看,发现是否完成了整个测试服务,只需要测试端到端的指令即可,是最完成的最贴近用户的真实场景的,所以仅需进行端到端的测试。
二、质量与成本的平衡关系
但是站在主链开发的角度来说,那些是对来说没有关系,只负责修改,仅需要进行单元测试即可,此时发现,现在不同的角色和时间段所选择的角色是不一样的,在这个过程当中你选择的测试,最终为了保证质量,需要进行成本因素的考虑,纵轴表示成本,横轴表示质量,碗一样的曲线即成本与质量之间关系的曲线,成本与质量之间的关系会随着自身的需求进行相应的变化,也就是说最开始成本的很高,质量很高,随着开始的过程中,碗底可以看到,在成本很低的时候造成质量的标准。来看往上走的这条线,不做相应的测试的话,在一开始,不做跟质量相应的手段,不做任何保障,出现问题就改,但随着后面的出现的问题越来越多,此时管理质量的成本越来越高呈指数集向上长,就是刚才钱的变化,还有另外说法,这条线往下走,追求极致的质量,在一开始就投入相当高的成本追求质量,但这时会起到一个平衡点,此时可以给质量的成本简单分类。
一个为低质量的成本,会导致内部缺陷的成本,在研发过程中,因为缺陷带来的成本,这个一直留到了客户,此时便会产生业务上的损失,但是有些其实可以不做,若缺陷成本很低很低,就可以不做,不需要投入,不如做puc,做了不再用,就不需要担心质量上的问题。
另外就是说,需要得到很高的质量需要投入的成本,一个为预防成本,一个叫验证成本,验证成本在教科书中叫做评估成本,需要进行质量的预估,而预防成本,即在研发阶段就需要做的很好,如同编确的大哥,此外在写代码也需要极致,需要花费的成本。验证的成本为如何知道我交出去的成品是非常好的,需要知道定义相应验收的用例,验证他,执行它,是否存在预期没有想到的问题。
基于这些成本,选择相应的测试或某个时间节点是基于成本选择的,比如说测试的某个阶段是不需要考虑的,在某个极端需要很多测试机器,需要很多测试用例,写很多自动化测试的脚本,甚至像有些测试的成本很高,某个测试就几十万,此时成本很大,对他来说是不经济的,选择测试的策略是从经济学的角度考虑的。
三、常见的分层策略
1、分层测试
常见的测试策略分为
分层测试一种平衡质量的成本手段,认为单元测试成本最低,金字塔的顶端为ui测试成本最高,要不为接口服务测试,上面为少量的ui测试,实际上效果可能并不理想,实际上系统运行很久,单元测认构建的成本很高,比如说现有模骨框架,代码结构,做各种各样的事情才能进行单元测试,所以此时金字塔并不成立,可以照自身实际画,如同三只小猪的故事,即如果说你觉得现在投入的成本只能做简单的测试,就采用分层测试,就如同猪大哥一样,先盖的茅草屋,保证房子石油行,如果存在相应的成本即可盖一个小木屋,但真的想要做到极致,你可能要把每一个墙、地基的材料都用到最好的,如同猪小弟单元测试一样,但是取决于现在你的成本有多高,你如果做了一个砖房子,可大灰狼没有来,那么对你而言成本太高了,若临时的搭帐篷过几天就要走了,那仅需要草房子即可,这便是基于所选择的。
整个发布过程即从特性预集成到整个线上发布的过程,是一个简单的从发布到集成,再到代码评价的过程,静态检查,单元测试的成本很低,但有些团队来说新增单元测试很麻烦。在这个过程中越向右质量越高,对于分级的流水线是基于品质流转的,越往后品质越来,并成本越高,希望投入少量的成本得到好的反馈,此时制品才有资格去享受最高的成本验证
2、测试自动化
在原来的成本之上多一个测试自动化的成本,该成本投入的目的是为了减低验证成本,所以测试自动化如果每次写完仅跑个一两次是不合理的此时便不需要写。
测试自动化存在非常基本的思想,它是另一种形式的开发活动,在做的不好的情况下,不将其当成一种开发形式看待则会将自动化变成手工形式的自动化,即简单的翻译过来,但事实上并不是一个划等号的过程,这里四个场景:
首先不是所有场景都是适合自动化,是进行了筛选和取舍,有些场景并不适合,比如说并发的设定特殊数据的此时进行是非常困难的。
其次自动化是分层的,并不是所有东西放到一起跑的,此外测试自动化是准确的不管是它给的结果,并不是给的结果大概率是失败的,可能是95%他并不是有意义的,因为剩下95%需要靠人去判断。
3、自动化测试的分层
针对测试自动化的分层可从不同的角度分析
首先从实现的角度,测试自动化本身分两类,一、测试用到的资源,library或者工具,都可以作为资源,二、为用例的测试本身因为面向的是用户的业务或者场景,业务和场景本身是有分层的,在对于测试自动化一般的最大区别,是在于它是有层级的 和存在说实话的阶段和清理回收阶段也就是实现方面。
另外,从需求上,测试自动化本身是不可避错,即测试自动化本身对所有的需求,用例需要去实现,本身是分层的比如说最基础的一层,基本的功能,之间显示是做用户认证的,第二个存在扩展需求,比如说不同的认证方式,在往上比如说常规的需求,比如说特殊的很少用到的方式。
从优先级来说,先满足基础,在扩展,最后到常规的需求,刚才讲到测试自动化是准确的,执行完成后需要一个准确的结果需要判断,从我的角度判断,这个软件满足什么样的级别比如说所有软件的基础需求满足过了,比如说满足国家kla的级别,验证完成后即可说为kl1的级别若所有常规验证完成后可为kl5,所以按结果可作分层。
4、测试自动化用例的反模式检查清单
以下基于linp的结构例举出来的,首先是结构的名称不合理
用例,步骤描述不了准备的场景。第二是步骤不合理,非常少,比如说仅存在一个场景,则到底测试的是什么?是不明确的。第三个危险的测试步骤,如某一步将测试结果crash,则此时看不到任何测试结果,第四个缺少tag也就是无法针对案例测试历史需求明确是基础需求还是扩展需求,结果成功的无法表明为suite和test 。第五个测试参数不合理,给多了参数本身含义不明确,对阅读产生困难,第六个不正确的使用比如说stup的步骤在test中被调用,显出占用问题,以下的全局变量污染,数据硬编码和第九个重复问题,会发现有的用例在前面的测试用例用到了,在后面的测试也用到了在不同的目录里存在相似的用例那么显然这类用例是重复的,和重复代码一样后面的耗时,不合理的资源依赖问题,发现整个检查清单,很像对代码的检查清单。
建议自动化落地的具体建议,如下
1. 整个用例与代码放到同一个代码库中,其方向放在同一分支上,保证开发代码的一个修改同步进行,保证在同一版本上。
2. 定好在开发前就定义好验收的用例,并在产品代码完成前实现它们,才能知道代码的实现是否符合预期,开发前的定义为做之前的标准是什么,怎么测量产品完成前实现的用例就是说当产品完成后即可验证
3. 测试可以重复执行且和执行顺序无关为原则性东西,不会因为重复执行和顺序依赖导致不同的顺序和不同的时间产生不同的结果,此时顺序是稳定的。
4. 只将稳定有效的测试自动化用例集成到流水线中,并不是越多的测试化越好,而是将稳定有效的测试化加入进来,形成稳定有效的测试结果。
5. 测试自动化人工验证的使用的不用环境,不同的环境分开,否则的话,两种方式在同种环境之间会偶合,产生冲突。
6. 不要用验证测试自动化的验证环境进行问题定位和排查,测试自动化执行后,存在错误需要排查所有用户执行的日志,而不是用户分到一些环境上,再去做一些定位,排查,会导致资源的降低,因为自动测试化的资源环境相对来说,比较有限需要最大程度上,保证运行和基础设施可以高效的运行,如果进行问题的排查便会中断它,而且做了一些修改还会破坏掉整个技术环境,此时带来的成本非常高的,。
7. 利用simulator和mock技术来验证各种异常场景为测试自动化的优势,在遇到异常情况下比手工测试更容易验证
对为上述测试化为面向接口多的测试化,还存在ui自动化,面向流量流量的回放的自动化,针对这种测试机制是由非常多的。可以通过自动测试化的方式降低成本,但同时也作为一种成本的增加,并且做的不恰当的话,可能是极致的增加,可能不如不做。
四、基于预防角度的单元测试的选择性策略
另外基于预防角度的单元测试的选择性策略,可进行有选择性的单元测试的自动化,原因是作为一个开发的实践,并不是一个测试的实践,更多是开发工程师针对自己的代码实现的工作
代码可以做简单象限的分类,根据代码之间的依赖,一个函数依赖其他的函数,依赖越高,成本越高,比如在开发环节中,函数的依赖关系,进行测试时要做相应的打桩,做表格单独的做测试,进行隔离需要成本,比如说依赖越高成本越高,另外从单测的方法,从其收益的角度越复杂的内线,复杂度越高,做单元测试获得的收益就越高,所以可以做简单的分类依赖少复杂度高的叫做算法代码,里面较多为偏原生的数据类型对其他相对来说,依赖很少,都是鼻儿依赖他,对其做相应的测试时起码收益很高,本身比较复杂,被别人用的特别多,所以其质量好坏是十分重要的,影响面广,并且由于依赖少,成本低,所以对其测试很有必要,所以针对算法类的测试是必要的。
下面 trivial code 为很简单的代码一个函数存在一两行,对系统的调用,打日志,依赖少,复杂程度低,即可不用做测试。因为在做的过程需要成本.
另外,COODDINATORS 类型叫做协调性,像妹函数,做相应场景的封装,把其他的方法封装里面。复杂程度低,仅一两个场景,但依赖别人很多,基本上都是调用其他类的方法与类型,逻辑本身很简单,所以要做很多的mork隔离,针对其可以不做单元测试仅需做功能型测试。
此外最上面 rafactoring 的复杂度高,同时依赖较多,数据类型更多为其他的自动义的数据结构,此时将所有数据偶合在一起,他的数据很多,此时,发现在做功能性检测发现逻辑复杂,单元测试依赖很多,建议重构,选择合适时机,当需要进行如功能性叠加时则进行在需要重构的时间进行时非常危险的此时同样适合遗留代码的测试,不要一味的使单元测试达到100%的覆盖率,所以要将所有的函数补上去
因为单元测试存在很重要的概念,单元测试使黑核测试因为白核测试使逻辑,每一行代码的逻辑是什么,而单元测试是针对需求,针对输入和输出,对于代码的实现每个程序员的实现方式不同,写成白核,针对一个程序可以,但是如果被另一个程序员修改,此时原本的单元测试便没用了,实际的需求并未发生变化,则是编码的发生变化。说明单元测试为黑核测试。