伯乐共勉

讨论。NET专区
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

测试这东西[转]

Posted on 2007-03-09 13:16  伯乐共勉  阅读(505)  评论(0编辑  收藏  举报
来自17testing论坛的Wily
关于测试这东西,玩了四年,仍然没有摸透它的脾气。
       有人说,测试是为了发现更多的缺陷,也有人说,测试是为了保证产品的质量。都没错啊,一个是从职责的角度来看,一个是从控制的角度来看。
       测试,其实就是一个验证的过程,测试人员竭尽所能的折腾一套软件,看它是否符合客户要求的标准,是否能经得起折腾,借以评价产品的质量好不好。不就是这样吗?:-)
       常规的测试理论是遵循了V模型中的V&V过程,也就是Validation and verification。Validation是对客户需求的验证,比如通常所说的验收测试、Beta测试。Verification指的是软件过程中每一次确认活动,包括客户需求确立以后的每一阶段关键产物的评审与测试。
      按照V模型的概念,我们将软件过程分为了客户需求、需求规格、概要设计、详细设计、编码、系统测试这几个关键的阶段。每一个阶段都会有相关的评审与测试,因此,以客户需求为主要依据的测试,我们称之为验收测试,着重于用户需求的验证,通常由客户来做;以需求规格为主要依据的测试,被称为系统测试,着重于对产品综合能力的验证,通常由专业的测试人员来做;以概要设计为依据的测试叫做集成测试,着重于对各级别的接口所进行的验证,通常会由编码人员与测试人员一起完成;以详细设计为依据的测试就成为了单元测试,着重于对代码的最小级别进行验证,通常由编码人员实现。看到这样的一个规则,我们很容易理清,每一个测试阶段,所要测试的对象是不同的,而相应的依据一旦通过了评审,便可以着手进行该项测试的准备。
      相对于之前的每一个关键阶段而言,测试阶段的执行顺序刚好相反。编码阶段只能执行单元测试,只有单元测试通过了,才可以对单元与单元之间进行集成,测试它们之间的接口,这被称之为集成测试。当软件所有的模块完成之后并且通过了集成测试,那么就可以进入系统测试阶段了。这个时候,测试人员摩拳擦掌,跃跃欲试,不找出Bug不罢休。
      然而,到底每一个测试阶段的测试工作是怎样开展的呢?这样的一个过程,我们称之为测试管理过程。每一个测试阶段,都会包括测试计划、测试设计、测试执行这三部分,有些人会把它划分得更细,比如获取测试需求、测试实施、搭建测试环境等。
      测试计划并不是单纯的写一个时间表,它是当对应的作为测试依据的文档定格之后(通常我们叫做基线化)就开始做的,最主要的目的是要告诉你的项目组成员,你要做什么(明确测试目的)?对什么来做(明确测试对象及测试需求)?怎么做(制定测试策略)?要使用什么来做(确定测试资源)?何时做(安排测试进度)?需要注意跟控制什么(估计测试风险,使用规避手段)?
      测试设计是要在测试计划通过了评审之后才做的,主要的产物是测试用例,是将你的测试策略升级为详细的步骤,对你确定的测试对象进行验证,应该要出现的理想结果是什么。当执行测试的时候,人们依据这份文档,会发现实际的结果与预期的不一样,于是便把它判定为缺陷。辅助的测试设计产物还包括测试环境的搭建、测试脚本、测试使用的数据等。关于测试脚本,是要衡量开发成本与预期收益的,不可以为使用了自动化的测试就是测试高手,这是个极其严重的误区。测试脚本的目的是要提高你的测试效率,怎样设计还是依赖于一个人的测试水平,如果片面的追求编程技能,把这认为是测试技能的提高,那么你不用做测试了,去做开发吧。在单元测试跟集成测试过程中会使用较多的测试脚本,是因为这些代码的复用率极高,几乎编码过程中的每天都会执行N遍。而系统测试阶段,由于测试重点不同,测试脚本的复用率也远远达不到前两个阶段的效果,自然就更要慎重了。要知道,一个常规的80/20法则,描述了一个事实,就是80%的缺陷是手工测试出来的,只有20%的缺陷是使用自动化测试得到的。你花费了两个月的时间去做了一套测试脚本,却只需要执行四五遍,发现的缺陷也寥寥可数,毕竟测试中的很多验证点是程序无法实现的。那么,如果使用两个月的人工测试,收到的效果会是天壤之别。你会选择哪一种方式呢?
      测试执行是在必备的代码实现之后才可以做的。拿着文档做设计,却不在真正的环境中执行,就变成了纸上谈兵的赵括。因此,你可以说测试设计是最重要的,我毫不反对,但是,测试执行却是最关键的。只有这个时候,你才能了解软件的质量如何,存在多少问题,需要怎样修复。在这时,才是我们经常说的测试阶段(单元测试阶、集成测试阶段、系统测试阶段)。测试阶段中,缺陷管理变成了重中之重,缺陷的追踪与控制成为弥补软件缺陷、控制产品质量的最直接有效的手段。
      在测试的每个环节都会产生相应的文档:测试计划、测试用例、测试报告,这三份文档成为最基本的资源。一份文档的好坏,关键不在于文笔怎样,而是能否清晰的表达你的意图,并让所有的人员能够了解,使得你所做的工作是可见可控的,不会出现较大的偏差。因此,写文档不是随便完成任务那么简单,它融入了你全部的思想、你的技能、你的沟通水准,是站在一定的高度上来完成的。即使你是个捉虫能手,但你不会写文档,不会把自己的思路清晰的表达出来,这至少能表明你不是个优秀的测试人员。
      我绝对不赞同一个测试新手去写什么测试计划、测试用例。他能把测试报告、缺陷描述写清楚就不错了。试想,谁也不是天生的文档高手,必然是经过千锤百炼、日益积累而成的。先要学会测试,能从测试中找到很多的缺陷,知道测试应该是怎样一种过程,再开始进行文档的修炼。
      我并不认为一个测试人员一开始写测试计划/用例的时候,就能够根据用户需求/需求规格/概要设计/模块设计这类的文档,写出好的东东。毕竟在国内,大多数技术类文档并不是很过关的。因此,我觉得要练习写,就要从一个你比较熟悉的已经成形的软件开始练起。此时你不需要去假想一个软件应该是怎样,而是针对一个实际的软件开始操作,记录你的操作跟你的结果,把它变为你的测试用例。测试计划更不消说,自然是要在你熟悉这套软件,知道怎样去测它的基础上来完成的。
      经过了这样一个锻造,你会明白要怎样展现自己的思路,在新项目中,根据分析或设计文档,你只要考虑它具体实现的是什么,然后根据你的测试思想,你的撰写经验,来完成一份较高质量的测试文档。

任何一种理论都有着它存在的意义,任何一种开发模式也有它生存的理由。对于测试,也是相同。理论上,测试的设计一定会在它所依据的文档通过了评审以后才开始,可是,到那时你又该如何确定这些文档能为你所用呢?
      当我们从一片混乱,到开始一个正规的测试流程时,我们或许并没有可以借鉴的经验,只能凭着理论带给我们的指导,一步步摸索前进。那么,在实际的过程中,我们如何来进行这场软件过程的革命呢?
      以系统测试用例的设计为例。
      理论上,当一份需求规格评审通过后,你才开始写系统测试计划、系统测试用例。为了保证需求规格的可测性,测试设计人员一定会参加该文档的评审。可是评审完成后,你会发现,当初明明看得很清晰的文档,现在忽然变成了一个让你迷惑不解的东西,你大致知道了软件要实现的功能是什么,可是你有好多测试思路无法实现,你发觉需求规格根本不能够提供给你所要的信息。于是,你义愤填膺:这标准的过程怎么会是这样?我明明已经评审过,我觉得上面表达的意思很清晰呀,为什么我不能够以它为主要依据来写测试用例?看样子,软件工程一点也不实用!
      那么,先不管软件工程是否实用,我们诊断一下为何不能够设计测试用例的原因。当我们首次看到一份需求规格时,我们关注的是他描述是否清晰,是不是已经让我们了解了软件大致要实现的功能。可是我们并没有从测试的角度来考虑,去测试这份文档存在的问题。当评审时间不充分、评审内容过多的情况下,我们没有余力去做充分的考虑,这就导致了我们的后续工作无法展开。因此,分析到这种情况的产生是因为我们生搬硬套了理论,自然不会收到良好的效果。这就需要对我们预定的测试管理过程进行第一步改进了。
      作为需求规格评审委员会的成员之一,在项目计划制定时,你就可以要求将各部分文档评审的时间尽量放长,评审的内容尽可能小的切割出来进行评审。这样,你有足够的时间去评审文档是否符合你的要求。你可以在脑中形成一个大致的测试框架,明白在这段内容中,你要测试什么,需要这份文档提供给你哪些信息。最实际的做法,就是在评审的时间就着手写测试用例,当你开始动手时,你的测试思路就会源源不断地运作起来,你才能了解这份需求规格是否真的描述清晰,是否存在二义性,是否考虑到了你所考虑的所有状况的处理。如果没有,你就可以把这些作为缺陷提交出来,请需求规格的分析人员做修正。此时,你发现的缺陷价值远远比你在系统测试阶段要大得多,因为,所有的弊端在初开始时就已经被发现,并及时作了修正,防止了下一环节继续出现偏差,大大节省了开发成本。而此时的测试用例并不能作为你真正发布的版本,因为评审阶段会有大量的缺陷被提出,只有在完全修复后再通过了评审,根据需求规格修复了你的测试用例,才能转化为真正的用例价值。对于这种方式,我们并不能说软件工程的理论跟实际不相符,不是吗?
      然而真正作为基线管理的测试用例,并不一定是根据需求规格写完了就被评审的。尽管作为公司灵魂的软件需求规格要求尽可能的详细,但在实际设计与编码中仍然或多或少的会有偏差与变更。系统测试用例就是在这个过程中不断的完善、细化的。
      当编码阶段开始时,为了缓和系统测试阶段出现的缺陷过多、有可能延误发布日期的风险,也为了降低缺陷修复的成本,系统测试用例的执行通常是在这个阶段就介入了。此时,测试用例并不能被基线化,在不断的编码单元集成时,测试人员(在此时,我认为最恰当的测试人员是测试设计人员)会抽取相应的测试用例来对集成的产物执行测试,验证测试设计思路是否存在偏差,测试覆盖率是否足够的高,一边执行测试,一边修改与补充测试用例,一边提交测试得到的缺陷。当编码基本结束时,系统测试用例已基本被完善。此时的用例文档便可提交评审。当然,我坚决不鼓励所有的测试用例完成之后才一起评审,同需求规格一样,他也应该是在实际过程中使用迭代的方式进行评审内容的分割,以使评审委员会成员有充分的时间跟精力进行评审。
      评审通过后,系统已经集成完毕并通过了集成测试,此时就可以进入系统测试阶段。在系统测试阶段中,测试执行人员从头执行系统测试用例,并根据测试中出现的问题提交缺陷。可能有人说,系统测试都被提前到编码阶段做了,这个时候还能发现缺陷吗?当然可以!缺陷是发现不完的,关键是看你设计的思路,测试的覆盖率只是个相对数,它永远都不可能达到百分之百。因此,我们会在不断的测试过程中发现缺陷,并把缺少的测试用例通过变更流程补充进去,以使测试用例更为完善。在客户验收测试阶段、实际使用阶段,我们仍然会收到用户发现的缺陷,并把这些漏掉的测试用例也补充进去。而这些漏测率也可以作为评估测试用例设计质量的指标。
      需要注意的是:测试计划跟测试用例的设计过程是有差别的,评审过程中介入测试设计,也必须介入测试计划,因为你测试设计的思路就是计划中测试策略的一部分,你不能够忘记测试计划的指导意义。当需求规格评审完成时,你首先要做的一件事,就是完成你的测试计划,评审通过后才可去完善测试用例。否则,你不能够让评审委员们接受你的测试策略,又怎么可能越过这一关,执行错误的设计呢?
      在测试管理过程中,以上的过程并不是唯一的实用过程,每个企业的环境不一致,采用的方法也不相同,仍然需要灵活的运用。这种方法只适于参考,让相关人员了解实际的状况,识别这些风险,采取更有效的方式来缓和或规避。
      作为本文章的终结篇,我并不对缺陷的管理过程作过多描述,缺陷管理是一个相对独立的过程,着重于对评审或测试中出现的缺陷进行严格的追踪与控制。每个企业的环境不同,所使用的管理流程也不同,但目的是一样的,就是使缺陷尽可能的得到修复。
      测试、质量控制、质量保证这三个概念通常会被混用,有些测试人员称为QA,却做的只是测试的工作,有些测试人员称为QC,却不明白QC跟QA又有何区别。
      测试是通过各种方式来验证软件是否达到规定的要求,他只负责发现缺陷、追踪缺陷,却并不负责产品的质量。而QC是要对软件产品的质量进行控管的,他要考虑缺陷修复的方式、产品发展的方向、软件变更的合理性等等。从广义上来说,QC应该是QA的一部分。但从实际情况考虑,最了解软件产品状态的是测试人员,由他们来负责产品的质量控制无疑是最合适的,可以节约人力资源成本以及独立的测试与QC的沟通成本。狭义的QA指的是对软件开发的过程进行跟踪,发现过程中出现的问题,及时汇报与处理,收集项目中必备的度量数据,使软件过程变得透明化,可控制。QA会分析数据背后的不合理性,找出原因,提出解决方案,促使软件过程的改进,同时汇总历史项目的度量数据,作为下一个项目的参考。
      总之,无论是测试,还是QC,或是QA,他们存在的最终意义都是为了软件产品的质量得到保证,不会因为在各个环节中出现了较大的偏差却无法识别,最终造成巨大的成本损失或项目失败。      
       综上所述,测试这东西说神秘不神秘,说简单不简单,它的理论也就那么一点,毫不复杂,复杂的只是具体的测试工作是如何做的,做得如何。因而测试理论的灵活应用,测试人员的经验值,却成为衡量测试水平的关键。可见,一个测试人员需要具备敏捷的反应,发散的思维,良好的沟通技巧,高度的责任心,深厚的应用领域的业务知识,软件工程理论,以及尽可能多的编程经验。测试人员能力的提高取决于以上因素。
       关于程序员与测试人员的评价是:一个有过编程经验的测试人员不一定是优秀的测试人员,但是一个有过测试经验的程序员一定会是优秀的程序员。原因只有一个,就是测试很重要!