分层测试

近些年来很火的分层测试的概念实际上就是我们以前所说的测试金字塔的概念。两者在我看来基本一样,当然笔者水平有限,如果理解有误还请各位读者多多斧正。分层测试强调的是测试的层次感。大家可能都有这种感觉,有层次感的面包比一般的面包可能口感更好;踢足球的时候如果三条线(前锋,中场,后卫)的距离保持的更有层次的话,那么球队的攻防运转可能会更加有效。同样的道理在做测试的时候,层次感也是非常重要的。对于经常做手工测试的同学来说,我们更关注的可能只是UI级别的测试,也就是UI层的东西。但是对于一个产品/系统/项目来说,UI层仅仅是它的表现层,在UI层下面需要有其他层次对其进行支撑,比如服务层。这个服务层可能分为两种,一种是本地服务,比如本地的数据存储;另一种是远程服务,比如远程的数据获取和存储。从直觉上来说,我们会很自然的认为仅仅测试UI层对于质量保障来说应该是不够的,最好能够将服务层也测试到,这样产品/项目/系统的质量应该会更高。这种将应用/系统/产品的测试任务分层并且对每一层都做针对性测试的测试策略我们可以称之为分层测试。一般来说我们将测试分为三个层次,分别是UI层、service层和unit层。这三层看上去应该是下面这样的。UI层很好理解,无非是负责展示和交互的那一层,也就是测试人员最常打交道的部分。service层可以理解成提供接口和服务,UI层可以从service层获取数据,也可以通过service层将数据持久化保存。unit层往往是最难理解的,因为测试人员可能对接口有一些的认识,但是unit这一层是基本是纯代码层面的,非开发人员往往接触不到。我们来通过一个例子感性的认识一下这三层。假设我们要造一辆汽车,我们先从发动机开始生产。发动机是由零件组成的,可以想到,如果一个零件不合格,那么整个发动机的质量也是不过关的。为了保证发动机的质量,我们必须对每个零件都进行质量检查和监控。unit那一层实际上就相当于制作零件,这一层关注的问题实际上就是每块“零件”代码的质量问题。有编程经验的同学可能会想到在编程领域里什么东西是跟零件相类似的呢?答案就是函数或方法。unit层主要的测试对象是函数或方法。比如开发同学写了一个寻找n以内所有素数的方法,如果n=100,那么该方法返回100以内所有的素数,如果n=10,那么返回10以内所有的素数。这个方法写好之后,我们通过一定的手段可以调用这个方法,通过测试不同的输入和观察相应的输出,我们可以判断该方法是否达到了我们的预期。这种对函数或方法进行的测试一般就是unit层所需要做的事情。有了零件之后我们可以将零件组装成发动机了。这时候我们可以断定每个零件都是合格的,因为我们已经对每个零件做了严格的检测,但此时我们能不能断定这台组装完成的发动机就是合格的呢?答案应该是不能。合格的零件如果进行了错误的装配应该是不能得到合格的发动机的。为了保证发动机的质量,我们需要对发动机进行整体的测试。这就是所谓的模块测试或者也可以称之为组建测试。在做组建测试的时候我们往往需要关注组件和组件之间相互配合工作的情况,比如需要测试发动机跟变速箱之间能不能顺利配合工作,以及发动机提供给仪表盘的转速数据是否准确等等。如果这些测试都等到车辆装配完成之后测试的话,万一那时发动机测出了问题,就需要拆下来修理,一装一拆,浪费了时间和人力成本。所以最好尽量在发动机没有装配到车子之前做这些测试。这时候接口测试就应运而生了。如果发动机能提供一些接口,通过一些专业的工具去读取这些接口的数据,比如发动机提供一个转速接口,通过这个接口我们可以很容易的读到发动机提供给仪表盘的转速,这样一来就可以在车辆整装之间比较完整的测试发动机了。对这种组件暴露出来的接口进行的测试就是接口测试。接口测试和组件测试都是service层关注的内容。发动机测试完成后就要与其他组件一起整体装配成最终的车辆了。装好之后我们需要检查一下车子的整体情况,比如能不能开起来,每一档的转换是否顺畅,行车系统是否正常工作等等。这些测试就是UI层的测试了,主要关注表象及交互。现在我们对于这三层有了一个感性的认识。我们已经解决了测什么的问题,我们已经知道unit层的测试对象是函数或方法;service层的测试对象是模块和接口;UI层的主要测试对象是展示和交互。那么我们应该怎么样去测试这些对象呢?先看unit层的测试策略。我们可以让开发人员自己人工检查一下自己写的代码,这样可以发现一些低级错误以及促进重构,这种方式叫做代码走查。我们也可以让整个开发团队都去人工检查某一些代码,这就叫做code review。这两种方案都是有一定效果的,但前者严重依赖开发者的自觉性,不是所有的开发人员都会自觉的做代码走查的,一般水平高的开发会经常走查代码,水平一般的开发反而往往忽视这个环节;后者则严重依赖团队的整体技术水平,整体技术水平高的团队在做code review的时候往往会发现一些问题并深入讨论,技术水平低的团队反而容易走马观花,形式主义至上。另外从重用性的角度上看,这两种方案的重用性其实并不高。我们也可以使用代码和工具去进行unit级的测试,这种测试就是我们常说的单元测试。单元测试可以非常狭义的理解成用代码和工具去测试代码的一种测试。这种测试重用性好,一次编写,反复执行。另外执行速度比代码走查及code review要快的多。从工程学上看,自动化的单元测试应该是一个很好的质量保证的手段。但是自动化单元测试也是有不足的地方的。首先有一定的入门门槛,这就导致了很多开发人员是不会写单元测试的;其次如果单元测试的覆盖率不高的话其实对质量并没有决定性的促进因素,该测的地方没测到,这样的产品质量始终都是不会太高的。因此对于技术水平高,能够自主把握研发节奏的团队来说,自动化单元测试是质量保障的大规模杀伤性武器;而对一些水平有限或者是疲于奔命的团队来说,单元测试始终是无法大规模推行,最终沦为鸡肋或者是成为某些负面因素的替罪羊。但是相对于service级和UI级的测试来说,单元测试的难度其实是更低的。这是因为单元测试的测试对象往往更加单纯——函数或方法,另外单元测试能够尽量早的进行,越早进行的测试其成本和难度往往会低于后续进行的测试,就像零件的检测要比发动机检测容易一样。基于这些原因,我们认为单元测试是应该鼓励尽可能的多做的。service层的测试也可以手工去做,比如手工调用接口进行预期和实际结果之间的比较,但这样一来效率不高,二来不能重复使用,所以service层的测试也往往以自动化测试为主。一般来说service会做自动化的组件测试,自动化的集成测试以及自动化的API测试。这些测试的测试难度比单元测试略大,运行速度要相对慢一点,而且测试环境的搭建也困难一些,因此这些测试的数量可以比单元测试要少,但不能没有。UI层的自动化测试开发难度应该是最大的,运行速度也是最慢的,测试环境的搭建往往也是困难的。因此很多团队在UI层是没有做自动化测试的。从道理上讲,只要手工测试的数量够多,没有UI层的自动化测试实际上也是可以接受的。但现实的情况是纯手工测试执行速度慢,无法重复使用,而且在一些用例也没办法用纯手工的方式去执行,所以我们可以适量的做一些UI自动化测试,作为手工测试的补充和加强。这样一来,我们的分层测试模型就变成了下面的样子。最下面的Automated Unit Tests代表的是unit层,中间的Automated Component Tests(自动化组件测试)/Automated Integration Tests(自动集成测试)以及Automated API Test(自动化API测试)代表的是service层,最上面的眼睛和Automated GUI Tests代表的是UI层。这张图总的来说也是三层结构,只是UI层上把人工和自动化给区分开了而已。人们形象地将上面这个三角形称为测试金字塔。那么我们该怎么理解这个测试金字塔呢?首先,这个金字塔分三层,也就是ui/service/unit这三层。层级越高就代表这种测试的难度越大。单元测试实施起来相对容易,而UI级的自动化测试实施起来相对困难。另外越往上就代表越接近真实的用户。UI层的测试很多都是站在用户的角度上去测的,而真实用户也基本上感知不到除UI层以外的其它层面。再从面积上看,面积越大就代表该种测试的测试用例数量应该越多,因此从测试用例的角度上去看,单元测试的用例数量应该最多,UI层的测试用例数量应该最少。再从运行时间上看,越往上运行时间往往越长。单元测试的执行速度相对是最快的,而手工测试的执行速度一般是最慢的。从测试金字塔这张图里我们可以得到如下的一些观点: l 单元测试尽量多做,UI级的测试可以少做一点;l UI测试难度相对较大;l UI测试更接近于真实用户;l 手工UI测试只占据了塔顶一点点的位置,而大部分的测试工作是手工测试人员所难以介入的,这让只会手工测试的同学有一定的危机感;l 开发人员是质量保障的最关键因素,因为测试金字塔的大部分测试工作都需要开发或者是具备开发技能的同学去完成;正三角是稳固的,如果按照测试金字塔的模型去组织测试工作的话,在一切相对正常的情况下,产品/项目/系统的质量是处在可控的状态下的。但现实生活中能做到正三角的团队往往是少数,大部分测试同学接触到的团队应该是倒三角的,也就是没有或只有少量的单元测试,随心所欲的做一些接口测试,把大量的人力集中在UI测试。这样的产品质量往往难以控制或者需要花费大量的时间和人力成本才能控制。前文也提到过伟大的产品刚横空出世的时候往往是没有单元测试和UI自动化测试的,但这些产品刚发布时的质量却是可以接受的或者甚至是优秀的,这是为什么呢?这是因为伟大的产品往往由天才的开发者创建或实现,天才的代码在不做单元测试的情况下也是质量可期的,这就等于是测试金字塔的最底层相当牢固,整个产品质量就自然由保障了;另外这些产品发布的初期规模也相对较小,也比较难出现一些在频繁协作过程中会出现的问题(比如修改了不是自己写的代码而造成了缺陷),规模小质量控制起来也相对容易些。总而言之,如果你的产品/项目/系统的开发团队大部分人都不是天才而且需要进行频繁协作的话,按照测试金字塔模型去做可能是一个比较好的方式。另外很多伟大产品刚发布的时候也是没有测试人员的,这是不是说明没有专业的测试人员参与的情况下,产品的质量也是可以很好的控制的呢?我相信各位读者都有自己的答案。

 

posted @ 2016-04-30 22:02  LaMw  阅读(6513)  评论(0编辑  收藏  举报