《构建之法》第十三章 软件测试

来源:互联网 发布:攻守道 知乎 编辑:程序博客网 时间:2024/05/16 07:52

摘至 邹欣《构建之法》一书,以作学习之用

基本名词解释及分类

团队统一思想要从基本名词解释开始。

  • Bug:软件的缺陷

  • Test Case:测试用例,测试用例描述了一个完整的测试过程,包括测试环境、输入、期望的结果等

  • Test Suite:测试用例集,即一组相关的测试用例

Bug可以分解为:症状(Symptom)、程序错误(Fault)、根本原因(Root Cause)。

  • 症状:即从用户的角度看,软件出了什么问题
    例如,输入(3211)时,程序出错退出。

  • 程序错误:即从代码的角度看,代码的什么错误导致了软件的问题
    例如,代码在输入为某种情况下访问了非法的内存地址——0X0000000C。

  • 根本原因:错误根源,即导致代码错误的根本原因
    例如,代码对于 id1==id2 的情况没有做正确判断,从而引用了未赋初值的变量,出现了以上的情况

下面是一个关于 Bug的万丈例子

  • 症状:用户宝盖,一个 Windows 应用程序优势会在启动时报错,继而不能运行

  • 程序错误:有时候一个子窗口的 handle 为空,导致程序访问了非法内存地址,此为代码错误

  • 根本原因:代码并没有确保创建子窗口发生在调用子窗口之前,因此子窗口的 handle 变量有时会在访问时处于未赋值状态(为空),导致出现上面提到的代码错误


按测试设计的方法分类

测试设计有两类方法:黑箱(Black Box)和白箱(White Box)

这是每个接触过软件测试的人都会给出的答案,但这只是整个软件测试的入门知识。所谓黑箱/白箱,是指软件测试设计的方法,不是软件测试的方法!注意“设计”二字。

  • 黑箱:指的是在设计测试的过程中,把软件系统当作一个“黑箱”,无法了解或使用系统的内部结构及知识。一个更准确的说法是行为测试设计(Be-havioral Test Design),即从软件的行为,而不是从内部结构出发来设计测试

  • 白箱:指的是在设计测试的过程中,设计者可以“看到”软件系统的内部结构,并使用软件的内部结构和知识来选择测试数据及具体的测试方法。“白箱”并不是一个精确的说法,因为把箱子涂成白色,同样也看不见箱子里的东西。有人建议用“玻璃箱”来表示。

在实际工作中,我们不应画地为牢,严格只用某一种测试设计方法。我们对系统的了解当然是越多越好。所谓“灰箱”的提法,正反映了这一点。有些测试专家甚至希望我们忘记全部的“箱子”及其颜色。

进一步说,我们并不是要禁止懂得程序内部结构的人员来进行黑箱测试设计,只不过是在设计时有意不考虑软件的内部结构。例如,在测试程序内部基本模块时(单元测试),通常要求由对程序结构非常了解的程序员来设计,这是因为内部模块的“行为”和程序的外部功能并没有直接的关系,而且对内部基本模块的“行为”通常没有明确的定义。另一个例子是软件的“易用性测试”,在设计此类测试时,没必要纠缠于程序的内部结构,而是应着重于软件的界面和行为。但是软件易用性测试也需要很多专业知识。这也从一个侧面表明“黑箱”和“白箱”没有简单的难度高低之分。测试用例写出来之后,大家可以忘了它们是从哪种颜色的箱子里出来的,使用就行了。


按测试的目的分类

1.功能测试
所列的测试类别中,测试的范围由小到大,测试者也由内到外——从程序开发人员(单元测试)到测试人员,到一般用户(Alpha/Beta测试)。

2.非功能测试
一个软件除了基本功能之外,还有很多功能之外的特性,这些叫非功能需求(Non-functional Re-quirement),或者服务质量需求(Quality of Ser-vice Requirement)。然而,若没有软件的基本功能,这些特性都将无从表现出来,因此,我们要在软件开发的适当阶段——基本功能完成后再来做这些非功能测试,如下表所示

这里写图片描述


按测试的时机和作用分类

在开发软件的过程中,不少测试起着“烽火台”的作用,它们告诉我们软件开发的流程是否顺畅,这些测试如下表所示。

这里写图片描述

另一些测试名称,则是说明不同的测试方法,如下表所示。

这里写图片描述


各种测试方法

单元测试(Unit Test)

请参看第2章“单元测试”,一节并思考以下问题:

  • 有时单元测试报了错,再运行一次就好了,于是后来大家就不想花时间改错,多运行几次,有一次通过就行了;

  • 单元测试中的好多错都与环境有关,在别人的机器上都运行不成功;

  • 单元测试耗费的时间要比写代码的时间还多,把代码覆盖率提高到90%以上太难了;

  • 单元测试中我们还要测试效能和压力,花了很多时间;

  • 我们都这么费劲地测了,那还要测试人员干什么?


代码覆盖率测试(Code Coverage Analysis)

前面单元测试中提到了代码覆盖率,简单来说代码被执行过,就是被“覆盖过”。如果一段程序运行一组测试用例之后,100%的代码被执行了,是不是意味着再也不用写新的测试用例了呢?答案是否定的。这是因为——

  • 不同的代码是否执行,有很多种组合。一行代码被执行过,没有出现问题,并不表明这一行代码在所有可能条件的组合下都能正确无误地运行。

  • 代码覆盖不能测出未完成的代码(所缺少的逻辑)导致的错误。比如:

    • 没有检查过程调用的返回值;
    • 没有释放资源。
  • 代码覆盖不能测出效能问题。

  • 代码覆盖不能测出时序问题,即由时序导致的程序错误(例如:线程之间的同步)。

不能简单地以代码覆盖率来衡量代码中与用户界面相关的功能的优劣。


构建验证测试(Build Verification Test,BVT)

顾名思义,构建验证测试是指在一个构建完成之后,构建系统会自动运行一套测试,验证系统的基本功能。在大多数情况下,这些验证的步骤都是在自动构建成功后自动运行的,有些情况下也会手工运行,但是由于构建是自动生成的,我们也要努力让BVT自动运行。

问:一个系统有这么多功能点,什么是基本的功能,什么不是基本的功能?

答:基本功能的特点是:第一,必须能安装;第二,必须能够实现一组核心场景。例如,对于字处理软件来说,其基本功能是必须能打开/编辑/保存一个文档文件,但是它的一些高级功能,如文本自动纠错,则不在其中;又如,对于网站系统,其基本功能是用户可以注册/上传/下载信息,但是一些高级功能,如删除用户、列出用户参与的所有讨论,则不在其中。

在运行BVT之前,可以运行所有的单元测试,以保证系统的单元测试和程序员的单元测试版本一致。因为在不少情况下,开发人员修改了程序和单元测试,却忘了将修改过的单元测试同时签入源代码库中。

通过BVT的构建可以称为可测(Testable),意思是说团队可以用这一版本进行各种测试,因为它的基本功能都是可用的。反之,通不过BVT的构建称为“失败的构建”(Failed,Rejected)。

如果构建验证测试不能通过,那么自动测试框架会针对每一个失败的测试自动生成一个Bug(小强)。一般来说,这些Bug都有最高优先级,开发人员要首先处理。大家知道,维持每日构建,并产生一个可测的版本是软件开发过程中质量控制的基础。对于导致问题的小强,我们该怎么办?答案是——

  • 找到导致失败的原因,如果原因很简单,程序员可以立即修改并直接提交。

  • 找到导致失败的修改集,把此修改集剔出此版本(程序员必须修正Bug后再重新把代码提交到源代码库中)。

  • 程序员必须在下一个构建开始前修正该Bug。

方法1和2都可以使今天的构建成为“可测的”,但是有时各方面的修改互相依赖,不能在短时间内解决所有问题,那就只能采用方法3了。

问:有人提到一种“冒烟测试”,是怎么回事?

答:事实上这是一种基本验证测试,据说是从硬件设计行业流传过来的说法。当年设计电路板的时候,很多情况下,新的电路板一插上电源就冒起白烟,烧坏了。如果插上电源后没有冒烟,那就是通过了“冒烟测试”,可以进一步测试电路板的功能了。我们正在讨论的BVT也是一种冒烟测试。


验收测试(Acceptance Test)

测试团队拿到一个“可测”的构建之后,就会按照测试计划,测试各自负责的模块和功能,这个过程可能会产生总共10来个甚至100个以上的Bug,那么如何才能有效地测试软件,同时在这一阶段该怎样衡量构建的质量?

在MSF敏捷模式中,我们建议还是采用场景来规划测试工作。

在“基本场景”的基础上,把系统在理论上目前支持的所有场景都列出来,然后按功能分类测试,如果测试成功,就在此场景中标明“成功”,否则,就标明“失败”,并且用一个或几个“小强”/Bug来表示失败的情况。

当所有的测试人员都完成了对场景的测试后,我们自然就得出了下表

这里写图片描述

这样就能很快地报告“功能测试56%通过”等。如果所有场景都能通过(有些情况下可以将该标准从100%降至90%左右),则这个构建的质量是“可用”的,这就意味着这一个版本可以给用户使用了。在这种情况下,客户、合作伙伴可以得到这样的版本,这也是所谓“技术预览版”或“社区预览版”的由来。

但是,有一个重要的问题要提请大家注意:“可用”,并不是指软件的所有功能都没有问题,而是指在目前的用户场景中,按照场景的要求进行操作,都能得到预期的效果。注意以下两种情况:

  • 在目前还没有定义的用户场景中,程序质量如何,还不得而知。例如:场景中没有考虑到多种语言设置。

  • 对不按照场景的要求进行的操作,结果如何,还不得而知。例如:在某一场景中,场景规定用户可以在最后付款前取消操作,回到上一步,如果一个测试人员发现在多次反复提交/取消同一访问后,网页出现问题,但这并不能说明用户场景失败,当然,对于这个极端的Bug,也必须找出原因并适时修正。

这种测试有时也称为验收测试(Acceptance Test),因为如果构建通过了这样的测试,这一个构建就被测试团队“接受了”。同时,还有对系统各个方面进行的“验收”测试,如系统的全球化验收测试,或者针对某一语言环境、某一个平台做的验收测试。


“探索式”的测试(Ad hoc Test)

“Ad hoc”原意是指“特定的,一次性的”。这样的测试也可以叫Exploratory Test。

什么叫“特定的”测试或者“探索式”的测试?

就是指为了某一个特定目的而进行的测试,且就这一次,以后一般也不会重复测试。在软件工程的实践中,“Ad hoc”大多是指随机进行的、探索性的测试。

比如:测试人员小飞拿到了一个新的构建,按计划是进行模块A的功能测试,但是他灵机一动,想看看另一个功能B做得如何,或者想看看模块A在某种边界条件下会出现什么问题,于是他就“Ad hoc”一把,结果还真在这一功能模块中发现了不少小强。“Ad hoc”也意味着测试是尝试性的,“我来试试,在这个对话框中一通乱按,然后随意改变窗口大小,看看会出什么问题……”,如果没问题,那么以后也不会再这么做了。

探索式测试的测试流程是不可重复的,因为它的测试都是“特定”测试,没法重复。这一原因,使得探索式测试不能自动化,就这一点而言,还达不到CMMI二级——可重复级。

作为管理人员来说,如果太多的小强是在探索式测试中找出来的,那我们就要看看测试计划是否基于实际的场景,开发人员的代码逻辑是否完善,等等。同时,要善于把看似探索式的测试用例抽象出来,囊括到以后的测试计划中。因此,探索式测试太多是团队管理不佳的一个标志,因为探索式测试是指那些一时想到要做但以后并不打算经常重复的测试。


回归测试(Regression Test)

请看第2章“回归测试”一节的介绍。要说明的是,回归测试不仅仅包括单元测试,也包括其他类型的测试。


场景/集成/系统测试(Scenario/ Integration / System Test)

在软件开发的一定阶段,我们要对一个软件进行全面和系统的测试,以保证软件的各个模块都能共同工作,各方面均能满足用户的要求。这类测试叫系统/集成测试。

问:有一种测试叫场景测试,是什么意思?

以一个图像编辑软件为例,这个软件的各个模块都是独立开发的,可是用户有一定的典型流程,如果这个流程走得不好,哪怕某个模块的质量再高,用户也不会满意。用户的典型流程是:

  1. 把照相机的存储卡插入电脑

  2. 程序会弹出窗口提示用户导入照片

  3. 用户根据提示导入照片

  4. 用户对照片进行快速编辑

  5. 调整颜色、亮度、对比度

  6. 修改照片中人物的形象(红眼、美白、美颜等)

  7. 用户选择其中几幅照片,用E-mail发送给朋友,或分享到社交网站上。

其中任何一步出现问题,都会影响用户对这一产品的使用。如果这里面各个模块的用户界面不一致(即使是“确认”和“取消”按钮的次序不同),用户使用起来也会很不方便。这些问题都是在单独模块的测试中不容易发现的。

问:应该什么时候做集成测试?是不是越早越好?

答:原则上是当一个模块稳定的时候,就可以把它集成到系统中,和整个系统一起进行测试。在模块本身稳定之前就提早做集成测试,可能会报告出很多Bug,但是这些由于提早测试而发现的Bug,有点像汽车司机在等待绿灯时不耐烦而拼命地按喇叭——也就是说,有点像噪音。我们还是要等到适当的时机再开始进行集成测试。

问:但是开发人员也想早日发现并修复所有的Bug,软件工程的目标不就是要早发现并修正问题么?总是要等待,听起来好像没有多少效率。

答:对,这就要提到在微软内部流行的另一种测试——伙伴测试(Buddy Test)。


伙伴测试(Buddy Test)

如上所述,在一个复杂系统的开发过程中,当一个新的模块(或者旧模块的新版本)加入系统中时,往往会出现下列情况。

  • 导致整个系统稳定性下降。不光影响自己的模块,更麻烦的是阻碍团队其他人员的工作。

  • 产生很多Bug。这些Bug都要录入到数据库中,经过层层会诊(Triage),然后交给开发人员,然后再经历一系列Bug的旅行,才能最后修复,这样成本就变得很高。

如何改进呢?一个办法当然是写好单元测试,或者运用重构技术以保证稳定性等。我们这里要讲的伙伴测试是指开发人员可以找一个测试人员作为伙伴(Buddy),在签入新代码之前,开发人员做一个包含新模块的私人构建(Private Build),测试人员在本地做必要的回归/功能/集成/探索测试,发现问题直接与开发人员沟通。通过伙伴测试把重大问题都解决了之后,开发人员再正式签入代码。在项目后期,签入代码的门槛会变得越来越高,大部分团队都要求缺陷修正(Bug Fix)必须经伙伴测试的验证才能签入代码库。


效能测试(Performance Test)

用户使用软件,不光是希望软件能够提供一定的服务,而且还要求服务的质量要达到一定的水平。软件的效能是这些“非功能需求”或者“服务质量需求”的一部分。

效能测试要验证的问题是:软件在设计负载内能否提供令用户满意的服务质量。这里涉及如下两个概念。

1. 设计负载
首先要定义什么是正常的设计负载。从需求说明出发,可得出系统正常的设计负载。例如,一个购物网站,客户认为正常的设计负载是每分钟承受20次客户请求。

2. 令用户满意的服务质量
其次要定义什么样的质量是令用户满意的。比如,同一个购物网站,用户满意的服务质量可以定义为:每个用户的请求都能在2秒钟内返回结果。

针对以上两点还可以逐步细化。

1. 设计负载的细化
上面我们只提到“承受20次客户请求”,那么这些客户的请求到底是什么,可以按请求发生的频率来分类。

  • 用户登录(10%)

  • 用户查看某商品详情(50%)

  • 用户比较两种商品(10%)

  • 用户查看关于商品的反馈(20%)

  • 用户购买商品,订单操作(5%)

  • 所有其他请求(5%)

    2. 服务质量的细化
    有些请求,是要对数据进行“写”操作,可以要求慢一些,比如“用户下订单,购买商品”,对这一服务质量,请求可以放宽为5秒钟,甚至更长。

除了用户体验到的“2秒钟页面刷新”目标外,效能测试还要测试软件内部各模块的效能,这要求软件的模块能报告自身的各种效能指标,通过Perf-mon或其他测试工具表现出来。

和别的测试不同,效能测试对硬件要有固定的要求,而且每次测试需要在相同的机器和网络环境中进行,这样才能避免外部随机因素的干扰,得到精准的效能数据。

简单地说,现实的环境有如下两方面。

1. 现实的静态数据
比如上面提到的数据库的各种记录,如果要模拟一个实际运行的商业网站,除了一定数量的用户和商品记录外,还得模拟在运行一段时间后产生的交易记录。

2. 现实的动态数据
这就是负载,现实中总会有一些人在同时使用这一个系统。效能测试中要考虑到“负载”,可以分为:

  • 零负载,即只有静态数据,在这种情况下测试的结果应该是稳定的,可以不断地收集数据进行回归测试;

  • 加上负载,根据具体情况可以分负载等级进行测试。

同时,客户会问,“如果我的系统慢了,怎么办,我是增加机器的数量,还是提高每个机器的处理能力?”这是我们要回答的问题。效能测试的结果应该成为“用户发布指南”的一部分,为用户发布和改进系统提供参考

在进行效能测试的过程中,可以得到系统效能和负载的一个对应关系,这时,就可以看到能维持系统正常功能的最大负载是多少。如果负载足够大,或者过分大,那就成了下一个测试的目标——压力测试。


压力测试(Stress Test)

压力测试严格地说不属于效能测试。压力测试要验证的问题是:软件在超过设计负载的情况下是否仍能返回正常结果,没有产生严重的副作用或崩溃。

怎样增加负载呢?对于网络服务软件来说,主要考虑以下两个方面。

1. 沿着用户轴延长
以刚才的购物网站为例,正常的负载是20个请求/分钟,如果有更多的用户登录,怎么办?那么负载就会变成30、40、100个请求/分钟,或更高。

2. 沿着时间轴延长
做过网络服务的都知道,网络的负载有时间性,负载压力的波峰和波谷相差很大,那么如果每时每刻负载都处于峰值,程序会不会垮掉?这就是我们要做的第二点:沿着时间轴延长。一般要模拟48小时的高负载才能认为系统通过测试。

与此同时,可以减少系统可用的资源来增加压力。

注意,压力测试的重点是验证程序不崩溃或产生副作用。即看看在超负载的情况下,我们的程序是否仍能正确地运行,而不会死机。在给程序加压的过程中,程序中的很多“小”问题就会被放大,暴露出来。最常见的问题是:

  • 内存/资源泄漏,在压力下这会导致程序可用的资源枯竭,最后崩溃;

  • 一些平时认为“足够好”的算法实现会出现问题。

  • 进程/线程的同步死锁问题,在压力下一些小概率事件会发生,看似完备的程序逻辑也会出现问题。


内部/外部公开测试(Alpha/Beta Test)

在开发软件的过程中,开发团队希望让用户直接接触到最新版本的软件,以便从用户那里收集反馈,这时开发团队会让特定的用户(Alpha/Beta用户)使用正处于开发过程中的版本,用户会通过特定的反馈渠道(E-mail、BBS、微博等)与开发者讨论使用中发现的问题,等等。这种做法成功地让部分用户心甘情愿地替开发团队测试产品并提出反馈。

按惯例来说,Alpha Test一般指在团队之外、公司内部进行的测试;Beta Test指把软件交给公司外部的用户进行测试,与之对应地,软件就有Alpha、Beta1、Beta2版本。在网络普及之前,做Beta Test费时费力,成本较高,现在由于网络的传播速度很快,与外部用户的联系渠道很畅通,很多外部用户都想先睹为快。因此,现在开发团队增加了反馈的密度,不必再局限于Alpha或者Beta发布,而是不断地把一些中间版本发布出去以收集反馈。


易用性测试(Usability Test)

“易用性测试”似乎更多地用来描述一套测试软件可用性的过程,这个过程一般不是由测试人员来主导的,而是由对软件设计和软件可用性有大量研究的“可用性设计师”来实行。

苹果公司的Macintosh团队在发布革命性的Mac电脑之后,收到了不少用户的反馈,说用鼠标拖拽文件进行拷贝时,总是要反复操作很多次才能成功,团队内部反复试验,都不能重现这个问题。后来才发现,出现这个Bug的关键是拖拽时手指离开鼠标按钮一会儿,然后重新拖拽。一般用户都是第一次使用这一革命性的设备(鼠标),所以经常会犯错;但是Mac团队的成员使用鼠标都已经非常熟练,所以没有人会犯这个错误,也就找不到这个Bug。


“小强”大扫荡(Bug Bash)

问:我们已经讲了太多的测试了,好像微软还有一个叫“Bug Bash”的活动,是啥意思?

答:Bug Bash,或者叫Bug
Hunt,简而言之,就是大家一起来找小强的活动——小强大扫荡。一般是安排出一段时间(如一天),这段时间里所有测试人员(有时也加入其他角色)都放下手里的事情,专心找某种类型的小强。然后结束时,统计并奖励找到最多和最厉害的小强的员工。

问:这是不是可以看做是“全体动员探索式测试”?

答:一般情况下是的,但是并不是全体人员用键盘鼠标一通乱敲乱点就可以搞定,大扫荡的内容也应该事先安排好。

这种活动,如果运用得当,会带来这样的功效:

  • 鼓励大家做探索式的测试,开阔思路

  • 鼓励测试队伍学习并应用新的测试方法,例如在做完“软件安全性测试”培训后,立马针对“安全性”做一次小强大扫荡,或者为“全球化/本地化测试”做一次小强大扫荡也是很常见的

  • 找到很多小强,让开发人员忙一阵子

当然,小强大扫荡也有一些副作用:

  • 扰乱正常的测试工作

  • 如果过分重视奖励,会导致一些数量至上、滥竽充数的做法

因此,这里有必要提醒两个细节:

  • 一定要让“小强大扫荡”有明确的目标、明了的技术支持。

  • 一定要让表现突出的个人介绍经验,让其他成员学习。要记住,最好的测试,是能够防止小强的出现。


实战中的测试

实战中的测试是在项目的稳定阶段执行的。团队在这一阶段的核心任务是:在满足最低接受条件的前提下,提高各个部分的质量。

似是而非的测试观念

大家对“测试”这一工作还是有很多误解,于是特地列出并纠正了几个似是而非的观点。

1. 测试在项目的最后进行就可以了
这是远远不够的。如果你在项目后期发现了问题,可问题的根源却往往是项目早期的一些决定和设计,这时候,再要对其进行修改就比较困难了。因此,测试人员从项目开始就要积极介入,从源头防止问题的发生。有人会说,我是一个小小的测试人员,项目开始的时候我能做什么?这就是小小测试人员努力的方向。

2. 测试就得根据规格说明书(Spec)来测,所以是很机械的
那不一定,即使你的软件产品功能100%符合Spec的要求,用户也可能非常恨你的软件。这时,就说明测试人员没有尽到责任,因为测试人员要从用户的角度出发来测试软件。

3. 测试人员当然也写代码,但是质量不一定要很高
开发人员的代码没写好,可以依赖于测试人员来发现问题。但是如果测试人员的代码没写好,我们依赖谁来测试和改错呢?这就要求我们测试人员的代码质量特别高,因为测试人员是最后一道防线,如果我们的代码和测试工作有漏洞,那么Bug就会跑到用户那里去。

4. 测试的时候尽量用Debug版本,便于发现Bug
如果你的目的是尽快让问题显现,尽快找到问题,那我建议用Debug版本,“尽快发现问题”在软件开发周期的早期特别重要。如果你的目的是尽可能测试用户所看到的软件,则用Re-lease版本,这在软件开发的后期特别是执行效能和压力测试时很有价值。


测试工作中的文档

A:测试工作是不是有很多文档要写?

B:各类人员都有文档要写,但是在敏捷模式中,我们要坚决避免为了写文档而写文档。要写真正有用的、重要的文档。

在计划阶段,我们就要制定测试计划(Test Plan),特别是测试总纲。然后还要写测试设计说明书(TDS)、测试用例(Test Case)、程序错误报告(Bug Report)和测试报告(Test Report)。它们之间的关系如下图所示。

这里写图片描述

测试计划和测试总纲主要说明产品是什么,要做什么样的测试,时间安排如何,谁负责什么方面,各种资源在哪里,等等。我们不是为了写文档而写文档,写文档的目的是要解决问题。然而,到底这些文档会解决什么问题呢?

1.测试设计说明书(TDS)
正如开发人员有功能设计说明书,测试人员也要有测试设计说明书,告诉测试人员要如何设计测试。

A:我们在哪里可以找到模板?有了模板就好办了。

B:我们不要一味地依赖于模板,不要被模板淹没了。对于一个功能,或者相关联的一组功能,TDS主要要描述这些重要的内容:

  1)功能是什么。

  2)需要测试哪些方面?有没有预期的Bug比较多的地方(对于测试矩阵有没有需要修改的地方)?

  3)如何去测试(采用什么具体方法,如何做测试自动化,准备什么样的测试数据等)?

   4)功能如何与系统集成,如何测试这一方面?

  5)什么才叫测试好了(Exit Criteria)?

A:有些功能还没有写好,我怎么能知道这些功能的具体情况?

B:功能实现之前,应该就要根据功能的Spec写好TDS,并通过同事的复审。

2.测试用例(Test Case)
有了TDS,我们就可以按照TDS的描述,对每一个功能点进行实际的测试了。具体地说,测试用例描述了如何设置测试前的环境,如何操作,预期的结果是什么。一个功能的所有测试用例合称为这个功能的测试用例集(Test Suite)。

A:对于一个功能,用户可能的输入千差万别,我是不是得写成千上万个测试用例?

B:没必要,我们可以把纷繁的情况归纳到几个类型中。例如,用户登录时的情况,我们可以将其归为以下几类。

  1)正确输入(用户输入了合法并正确的用户名和密码),预期结果是用户能够正常登录

   a. 用户名又有多种情况(数字、字母、中文)
  
   b. 用户登录“记得我的账户和密码(Re-member Me)”功能可以正常使用

   c. 用户的密码是否隐式显示,或者在不同模块中转送(明文密码会导致诸多安全性问题)

  2)错误输入,预期结果是系统能给出相应的提示

   a. 用户名不存在

   b. 用户名含有不符合规定的字符(控制字符、脚本语句等)

   c. 用户名存在,但密码错误(具体测试时,可以输入空、超长字符串、大小写错误等)

设计测试用例有好几种方法,这些方法互相补充,帮助测试人员有效地生成测试用例。

  • 等价类划分
    不同的测试数据,如果只是重复触发了同样的处理逻辑,或者可能的错误,那么这些测试数据是等价的,它们属于同一等价类。我们要产生出不同等价类的输入,来有效地覆盖程序的各种可能出现问题的地方。

  • 边界值分析
    程序经常在处理数据的边界时出错,如果我们能产生测试数据,触发各种边界条件,就能有效地验证程序在这些地方是否正确。例如,如果程序期待一个“日期”类型,那我们可以构造包含下面各种边界条件的数据:一年的第一天,最后一天,平年的2月28日,闰年的2月29日,或者它们的前后一天,等等。

  • 常见错误
    根据经验推测程序通常容易出错的地方,从而更有效地第设计测试用例,例如空文件名,在期望数字的字段填入文字

3.错误报告(Bug Report)

在测试中,如果发现了问题,我们就得报告,在TFS的软件过程模型中,“Bug”是第二个工作项类型。在这一阶段,我们主要用Bug进行交流。

在第4章“两人合作与结对编程”的练习中,有些团队成员已经互相找过Bug,但是当时项目相对简单,对Bug的格式并未做严格要求。在一定规模的软件项目中,一份好的错误报告,至少要满足以下几点。

  • Bug的标题,要能简要说明问题

  • Bug的内容要写在描述中,包括:

    • 测试的环境和准备工作
    • 测试的步骤,清楚地列出每一步做了什么
    • 实际发生的结果
    • 根据Spec和用户的期望)应该发生的结果
  • 如有其他补充材料,例如相关联的Bug、输出文件、日志文件、调用堆栈的列表、截屏等,应保存在Bug对应的附件或链接中

  • 还可以设置Bug的严重程度(Severity)、功能区域等,这些都可以记录在不同的字段中

下面是列举的创建的一个Bug:

标题:挂了

内容:我今天在玩购物网的时候,发现移山网站挂了。

这个Bug对问题的描述太过笼统,开发人员根本无从下手。一个好的Bug报告应该是这样的:

标题:购物网站的某个具体页面(URL),在回复中提交大于100KB的文字时会出错

内容有以下几点:

环境

在Windows XP下,使用IE7。允许Cookie。购物网的版本是1.2.40。

重现步骤:

  (1)用[用户名,密码] 登录。这一用户在系统中是一般用户。

  (2)到某一产品页面(链接为:……)。

  (3)选中一个帖子,例如:帖子号为579。

  (4)回复帖子,在内容中粘贴100KB的文字内容(文本内容见附件)。

结果:

网站出错,错误信息为:[略]

预期结果:

网站能完成操作,或者提示用户文本内容过大。

[在附件中加入100KB的文本文件]。

测试人员还可以附上其他分析,团队应该鼓励测试人员追根溯源。如果看到测试人员发来这样的Bug报告,那么开发人员就能够重现这一问题,从而有效地分析和解决问题

4. 测试修复,关闭缺陷报告(Resolve,Test and Colse a Bug)
当开发人员修复了一个缺陷并嵌入代码后,一个新的构建就会包含这一个修复(Bug-Fix)。测试人员索要做的就是验证修复,并且搜寻有无类似的缺陷,验证修复会不会导致其他问题(回归,退化),了解修复的影响(只是修改一个简单的显示文字,还是动了内部算法),并且检查系统的一致性是否受到影响(例如:修改了默认的 /是/否/取消/选择次序,要检查整个产品中其他的对话框是否遵循同一模式)

在完成测试之后,测试人员可以关闭缺陷报告,同时在“历史(History)”一栏内说明验证是怎么做的。

当测试人员验证了一个Bug被正确修复了之后,还要考虑是否将这个Bug变成一个测试用例,保证以后的测试活动中会包括这个Bug描述的情况。这点非常重要。

5.测试报告(Test Report)

在一个阶段的测试结束之后,我们要报告各个功能测试的结果,这就是测试报告。只需简单地列出一些数字即可,例如:对于某一功能,我们要收集下列数据。

  • 有多少测试用例通过?

  • 多少测试用例失败?

  • 多少测试用例未完成?

  • 现多少测试用例之外的Bug?

所有功能的测试报告相加,就能得到整个项目的测试统计信息。这样的信息能帮助我们从宏观上了解还有多少事情没办完,各个功能相对的质量如何。

0 0
原创粉丝点击