软件测试中的抽象层次系列之二 – 开发和测试

(The Application of Abstraction Level in Software Testing Serials - II- Development and Testing)


发表于四月26, 2014


抽象和抽象层次

 关于“软件测试中的抽象层次”系列文章的介绍部分,您可以点击这里查看。


“开发视角”和“测试视角”

Alex Allian在这篇文章中告诫开发新手们,要学会像“开发人员”一样地思考,考虑问题要达到足够细致的程度,因为电脑只会做你告诉它去做的事情,下面这个例子就体现了开发人员(如非特别说明,本文中提到的开发人员均指的是负责具体编码的人员)思考的细致程度:

 

Walk forward ten feet

Move your hand to the wall

Move your hand to the right until you hit an obstacle

...

Press upward on indentation

 

上面这段描述可以称为一个小的“算法(Algorithm)”,它实现了“如何打开房间内的灯”这样一个功能。这种更面向实现的视角(Implementation Oriented Viewpoint)是开发人员的视角,属于较低层次的抽象(LOA – Lower level Of Abstraction),它呈现了一些“具体事物”,比如该过程涉及哪些具体的角色、有哪些具体的动作、动作的幅度方向等细节:ten feet、your hand、wall、right、obstacle、upward、walk、move、press。。。

 

与之相对,测试人员的视角更多的是面向用户的视角(Business Oriented Viewpoint),属于较高层次的抽象(HOA – Higher level Of Abstraction),测试人员往往会忽略一些细节,而从宏观上考虑用户使用的场景。比如同样的一个功能点,测试人员的视角:

 

Walk to door

Find light switch

Turn on light

 

当然,这里说的“测试人员”,指的是专业的系统测试人员,他们一般不负责单元测试活动(开发人员更擅长也更适合做单元测试)。

 

可见,开发人员和测试人员站在不同的抽象层次,拥有不同的视角,前者更关注微观的实现细节、后者更关注宏观的应用场景。我们知道,软件测试也是分层的,比如传统的分层方法:V模型中的单元测试、集成测试、系统测试、验收测试等等。处于不同的抽象层次上,测试的关注点也应该有所不同,要了解这一点,首先了解下软件研发过程中各种“抽象”的层次体现。


软件研发过程中“抽象”的层次


注:鉴于有些人将“研发”等同于“开发”,这里特别说明,本文中“研发”包括“开发”和“测试”等一系列活动。

 

软件开发完成后交付给测试团队测试,我们不能笼统地说,在软件交接之前的开发过程,属于LOA较低的抽象层次;软件交接之后的测试过程,属于LOA较高的抽象层次。如果按照简单的瀑布模型讨论的话,贯穿于软件研发生命周期中各阶段的抽象的层次大致包含:

 

  • 在软件项目初期,粗糙而模糊的原始用户需求(Original Requirements)体现了一个非常高的抽象层次,我们暂且称之为HOA1;
  • 需求阶段,一条条系统需求(System Requirements)补充了一些更具体的东西进来,称之为HOA2;
  • 设计阶段,High Level的设计需求(Design Requirements)比SR和OR都要更具体些,称之为HOA3;
  • 编码阶段,实际上会有很多细致的、Low Level的微观设计要在编码时考虑,是非常具体的层次,可以称之为LOA;
  • 测试阶段,测试人员更多站在用户的视角开展测试,可以笼统地称之为HOA. (不同的测试分层体现的抽象的层次也是有所差别的。)

 

从另外一个角度说,HOA1/HOA2/HOA3/LOA这些不同的抽象的层次,也体现了在研发各个阶段对不同层次的“算法”的抽象,是一个“概括-具体-概括”的过程。那么,算法的抽象层次具体又是什么呢?

 

算法的抽象层次

J. Glenn Brookshear在《Computer Science An Overview》一书中对算法给予了高度重视,认为算法是计算机科学的最基本的概念,并且把软件认为是程序与程序所表示的算法的组合:“Programs, and the algorithms they represent, are collectively referred to as software.”而Programs就是以一种与计算机兼容的形式来表达算法。

 

那么,我们要测试一个软件,一方面要测试程序,即测试代码与机器的兼容性,这是纯粹代码层面的测试,比如代码本身是否符合相关规范、是否有编译或链接错误、代码的各种测试覆盖情况如何等等,这可以归为面向代码实现的视角,基本对应于LOA的层次,这类测试一般由开发人员完成;另外一方面要测试算法,即测试该程序要解决的实际问题,这是面向用户的视角。根据前面所述,由于软件研发过程中存在不同层次的算法的考虑,这种面向用户视角的测试自然也存在不同的层次,即对应到不同层次的HOA,这类测试一般由开发人员和专业的测试人员共同完成。

 

了解了这些,对如何更好地开展软件测试的工作会有很多启发,以下重点谈两点:测试设计工作、和预防性测试工作。

抽象的层次对测试设计的启发

我在讲测试设计课程时,经常会先抛出一个具体的题目,比如一款叫做大富翁的小游戏软件,让大家分享测试设计的idea。很快地,学员们就想到了很多很多要测试的点,每个人都有自己的一套测试设计思路。仔细分析一下就会发现,这些测试设计思路还是有很多不同的地方的,比如有的人直奔细节、细数他能想到的所有测试点,诸如用户设置是否成功(要考虑2个玩家和4个玩家的情况)、地图显示和更新是否正确、行走功能是否正常、买地卖地是否正常、礼品屋的功能是否正常(要遍历每一种礼品)、以及各种异常输入是能够处理等等;而有的人会想到一些更宏观一些的方面,比如“只有两个玩家,多次行走后,一个玩家资金不足破产,另一玩家获胜,游戏正常结束”、“有四个玩家,多次行走和买地卖地等动作后,3个玩家逐个破产,最后一位玩家获胜,游戏正常结束”、“中途有玩家强制退出的情况”、“一台机器同时启动多个游戏程序的情况”等等;还有的人会想到各种更为复杂的场景或非功能测试,比如游戏各功能在时序上的交互情况、安全性测试、性能等;当然,往往大部分人是既提了一部分细节功能的测试,也提了少量宏观场景的测试,因为在很多人心中,并没有这种明确的宏观概括与微观具体的分别。

 

当然,这个题目本身就是一个陷阱,我并没有给出任何有用的额外的信息,以便帮助测试人员判断他当前所处的抽象层次,以便采取相应的测试策略,开展适合的测试设计。不过,识别测试上下文,明确测试所处的具体抽象层次,这本身也是一项要考察的测试技能。

 

举个例子,对于本文开始提出的那个“开灯”的小算法来说,开发人员小D识别出来当前要对“开灯”这个单功能开展详细的测试设计,那么可能包括的一些测试设计idea有:

  • 每一步动作是否执行正确(Walk、Move、Press。。。)?
  • 是否要走10 feet,多一步少一步如何?
  • 对于“前进”的方向判断是否准确?
  • 墙的位置识别是否正确?
  • 手总是向右边就能触碰到开关吗?
  • 开关的判断是否正确,有没有可能误判?
  • 当前开关的状态是什么,向上拨开关一定能够打开灯吗?
  • 。。。

 

而测试人员小T识别出来,当前要站在用户的角度,针对“开灯”这个功能进行测试(根据上下文,也许此时的被测对象是包含“开灯”在内的一个端到端的特性),那么可能包括的一些测试设计idea有:

  • 以房间不同的位置为起点,触发“开灯”的动作
  • 不同的房型、不同的开关类型测试
  • 不同的房间布局、墙面布局的测试
  • 当前灯的状态的遍历测试(亮、暗、闪烁。。。)
  • “开灯”与其他单功能的交互测试(时序交互、空间交互等)
  • 多次“开灯”之间的时间过短、过长、过于频繁等情况
  • 各类非功能性测试,比如安全性、易用性等
  • 。。。

 

您会发现,开发人员小D采用的是开发的视角,想到的idea都是在LOA层面上以更细致、具体的方式考虑要测试的点;而测试人员小T采用的测试的视角,想到的idea都是在较高的HOA层面上以更宏观、概括的方式考虑要测试的点,小T对“开灯”这个单功能是如何实现的以及应该有什么样相应的测试点考虑就比较少,这是因为他们所处的抽象的层次不一样,一个偏单元测试,一个偏系统测试。

 

试想,如果我们不要求每个人先识别所在的抽象层次,并进行相应层次的测试考虑的话,尤其在大的项目中,有很多开发人员和很多测试人员,针对每个大功能或小功能,每个人都可以想到一些LOA层面的测试、也可以想到一些HOA层面的测试,就像前面提到的大富翁游戏这个例子,结果可想而知,系统中有些部分可能被重复测试多次,而有些部分的测试可能一直无人问津。


抽象的层次对预防性测试的启发

上面提到的“抽象的层次对测试设计的启发”,实际上讨论的是抽象的层次图中的最底下的LOA和HOA两个层次。接下来,我们再看看上面的HOA1,HOA2,HOA3这三个层次。

 

前面提到,测试不仅要测试程序,更要测试程序所代表的算法,而算法从提出到实现是要经历HOA1, HOA2, HOA3这些较高的抽象层次的,这个过程测试可以深度参与,做好预防性测试的工作。

 

一方面,测试思维与开发思考的不同、测试视角与开发视角的不同、以及很多测试人员编码技能的欠缺,都使得测试人员不大擅长LOA层面的需求实现的工作;但另一方面,也正式这些差别使得测试人员很适合参与HOA层面的需求分析和设计的工作。与其让测试人员将他们对需求的考虑用在系统测试阶段、发现缺陷后由开发人员修改bug,不如让测试人员一开始在需求阶段就深度参与,贡献出测试人员对需求的各种理解和质疑,提前预防一些缺陷的发生。测试人员可以与需求和设计人员结对,分析需求、分析用户使用场景、设计需求验收标准、提早验证测试人员的idea。。。从HOA1,到HOA2,再到HOA3,需求的抽象层次越来越低,需求越来越具体,测试人员深度参与需求分析的过程也是一个对需求理解越来越深入的过程,这大大节省了测试人员学习了解需求的时间,也为后期开展HOA层面的系统测试活动打下了良好的基础。

 

当然,上面讨论的这个抽象的层次图是一般而言的,对于不同的项目上下文,这个抽象层次图可能差别很大。比如,有的互联网公司,项目周期非常短,能够识别出来的需求抽象层次可能如右图。

管理者的一两句话的交待可能就完成了需求阶段,开发人员可能也没有搞明白需求是什么,就得赶紧开始编码了,但是“理解需求”这个工作总是无法规避的,否则如何完成编码和测试呢?所以,需求这个阶段的事情变相地滑移到了编码和测试阶段。这个时候其实更需要测试人员使用预防性测试的本领,尽可能地多和相关人员打探了解需求的各种信息,及时提出潜在的风险,否则整个team欲速则不达,产品质量堪忧!

 

相比于上面的“需求分析向后滑移”现象,敏捷项目中的迭代需求澄清会(可能有不同的叫法)就起到很好的预防缺陷的作用。一般由业务分析人员(Business Analysis)、开发人员和测试人员三种角色参与,对接下来要实现的需求(story)进行分析讨论。注意到,由于这三个角色的视角各有不同,BA人员偏用户的视角、开发人员偏实现的视角、测试人员偏用户的视角并且有很多逆向的思考,有关需求的很多问题会在需求澄清会上浮现出来,从而有效地预防一些缺陷的产生。当然,需求澄清会上讨论的需求一般还是偏HOA层次的,所以这时候的缺陷预防也属于HOA层次的预防;待编码实现阶段,如果测试人员能和开发人员结对开发、或者两个开发人员结对编程,那么就会有LOA层次的缺陷预防发生。

 

总结

  • 负责编码的开发人员的视角是更面向实现的视角,属于较低层次的抽象(LOA);
  • 负责系统级测试人员的视角是更面向用户的视角,属于较高层次的抽象(HOA);
  • 较低层次的抽象更关注微观的实现细节;
  • 较高层次的抽象更关注宏观的应用场景;
  • 处于不同的抽象层次,测试的关注点也不同;
  • 软件研发过程中不同的抽象的层次,体现了不同层次“算法”的抽象;
  • 测试一个软件,包括测试程序和测试算法两个部分,前者属于较低层次的抽象(LOA),后者属于较高层次的抽象(HOA);
  • 测试设计工作,首先要明确测试的任务所处的抽象层次,然后开展相应粒度的测试设计,以做到不同测试分层的协调,避免重复测试和漏测;
  • 在需求和设计阶段,测试人员可以深度参与,做好预防性的测试工作,同时尽早理解被测对象;
  • 可以在HOA和LOA层次上开展相应地预防性测试工作。

 

Comment Box is loading comments...