敏捷软件开发是近些年来比较热门的话题,《敏捷宣言》四条主要精神和十二条基本准则概括了敏捷开发的基本思想。围绕着这些基本概念和思想,产生了一系列的轻量级方法,如:极限编程、测试驱动开发、Scrum、特性驱动开发等。虽然具体名称、过程和侧重点不尽相同,但是相对于非敏捷的开发方法而言,它们都更强调面对面的沟通、团队不同角色之间的紧密协作、频繁交付新的可用的软件版本、紧凑而自我组织型的团队等。敏捷开发只是提供了一个思想和方法论,而要在实际的工程中正确运用它,并真正显现出它的优点和产生实际的效果,这对于每个团队而言一开始都是一个挑战,尤其是对那些那些习惯了传统瀑布模式的团队。
敏捷是整个团队的敏捷,不只是团队中某个角色或者某个阶段的敏捷,开发、测试和项目经理等所有角色都要敏捷起来。敏捷方法的采用对团队每个成员都提出了新的挑战,尤其是测试人员。之所以这样说,是因为相对于传统的瀑布模型,敏捷开发所要求的频繁交付,给测试所留出的时间更为紧迫,要求测试人员更早的介入和更及时地完成测试任务。如何在这么短的时间内完成测试的计划和实施呢?如何有效地避免回归问题的出现?手工测试人员如何能更好的融入到敏捷团队?等等问题接踵而至,这都需要需要测试人员不断的思考和尝试。
无论是哪种开发模式,软件的开发过程都可以归结为:人、工具和过程这三个因素,三者的有机结合才能更高效的完成任务。有人会说:《敏捷宣言》四条主旨精神的第一条就是“个体和交互重于过程和工具”,工具还有那么重要吗?回答是肯定的,工具很重要,这条主旨所提到的是“重于”而不是不要。为了支持敏捷开发,Visual
Studio 2010(以下简称为VS 2010)应用程序生命周期管理中引入了MSF for Agile
Software Development v5.0过程模板,用于辅助敏捷团队在实际工程中进行敏捷实践,它支持Scrum敏捷开发过程框架。本文将从工具角度出发,
介绍Visual Studio 2010如何帮助测试人员更胜任敏捷项目中的测试工作。对于工具与人的关系而言,好的工具应该是将人从重复和机械的劳动中解脱出来,让人有更多的精力和时间花在有创造性地劳动上,而由工具去完成将繁琐和冗余的事务性操作;而对于工具和过程的关系,工具是过程能够得到确实落实和准确执行的基石,很多时候我们总是依赖于人去执行某个过程或者流程要求,但人的执行往往带有一定不稳定性和主观性,而工具则可以帮助我们准确客观的执行。
团队有效协作的基石——Team Foundation Server
敏捷开发强调人与人之间的有效沟通和紧密的团队协作。对于测试团队和测试人员而言,首先应该需要考虑的是:如何让测试工作更有效的集成整个敏捷开发的活动中去?而不是将测试工作仅作为一个“附件”或者可有可无的副产品。当然,这会受到团队组织形式和开发过程的限制,例如:采用功能小组模型的团队,所有角色成员(PM、开发人员、测试人员)隶属于同一个功能团队,客观上其沟通就更为方便;而对于采用纵向按职能划分团队的公司而言,测试和开发在隶属关系上是分开的,相对在沟通上障碍就会更多些。无论是哪种组织形式,好的工具能帮助促进和统一各个角色间的信息互通和共享,而不是要让他们彼此之间更为孤立、工作在各自的一亩三分地(Silo)中。Team
Foundation Server 2010(以下简称为TFS 2010)就是这样的工具,作为整个团队协作的核心,它统一了团队不同角色信息、实现了信息之间的有效互联互通、彼此之间的共享和关联,例如:TFS
2010定义6种默认的工作项类型,如下图所示。
图1:TFS 2010定义6种默认的工作项类型
其中,Test Case和 Shared Steps是2010专门为测试新加入的。不要小看这些工作项,它们之间有着丰富的关联关系,这种关系背后所代表是角色之间的关系。对于测试而言,它将测试和团队紧密的结合在一起。例如:Test
Case工作项用来详细定义和管理测试用例,它还可以和User Story相关联,也就是将测试和用户需求进行了关联,用户可以从需求追溯到覆盖的它的测试用例,这背后体现的是测试人员和需求人员/PM的协作;Test
Case还可以与Bug关联,通过这种关联可以挖掘出哪些 Bug被测试用例覆盖,哪些还没有,这种关联体现了测试人员与开发人员的写作,如果是自动化测试用例,则体现了手工测试人员和自动化工程师的协作;Bug还可以可以和签入集(Change-set)关联,可以找到为了修复Bug,开发人员修改过哪些产品代码,这体现了测试人员和开发的关联。
敏捷开发频繁的迭代和较短的迭代周期,对项目管理的精确性、透明性和可见性都提出了更高的要求,
尤其对于那些项目复杂和人员较多的团队。Task是另一个重要的工作项类型,它用于管理开发过过程中的所有任务项,包括:开发、测试以及需求等任务,统一管理开发中的所有任务,统一计算项目的开销和剩余工作量等。例如,项目的燃尽图就是由它产生出来的。现在,人们虽然在理论和概念上已经非常认同软件测试的在工程中的重要地位,但在具体实际操作中,测试却仍然被看作是低于开发和需求分析等的“二等公民”。当然这是由于多方面的综合因素造成的,从管理技术角度讲,这是由于测试工作本身缺乏可度量性和可见性,从导致了测试工作的透明性的缺失,团队往往看不到测试工作的进度和所带来的成果,从而意识不到测试的真正作用。对于测试人员自身而言,缺乏可度量性也让自己无法对工作进度准确把握,进而失去了对自己工作的目标感和认同感。将测试工作同其他工作一样的用Task工作项管理起来,增加了它的可度量性和可见性。将测试工作和其它任务一起统筹,时刻确保测试被作为整体中的一部分进行考虑,所有的测试任务都被作为Task工作项记录下来,例如:编写测试计划、设计测试用例、自动化测试用例等等,每项任务都有三个默认时间估计数据需要填写,它们是:Original
Estimate、Remaining和Completed,分别代表了任务的预估时间、剩余工作量和完成工作量。
为了增强敏捷过程的透明性和可见性,TFS 2010定义了很多的报表和仪表板(Dashboard),它们会自动生成各种报表,以可见的方式描述敏捷项目的健康状况,这其中就有很多反映测试工作的报表,如下面所示。Stories
Overview展示了用户故事的进展情况,包括了每个用户故事的测试用例覆盖数量和执行结果,以及相应的Bug数量;Test
Dashboard显示了测试用例的状态,包括正在设计的用例以及设计完毕可以执行的用例数量,现实当前Bug的状况,包括未被修复和以修复Bug的数量。
图2:Stories Overview展示了用户故事的进展情况
图3:Test Dashboard显示了测试用例的状态
集成测试环境——Microsoft Test Manager
在过去的十几年中,为了适应了软件项目的复杂度和规模的不断膨胀,软件开发工具和框架得到了长足的发展,而测试工具则始终是块短板
,特别是对于那些需要手工完成的测试任务而言,进展就更为缓慢,例如:现在很多团队仍然使用Word或者Excel这样“原始”工具来管理测试用例。通过对业界的调查和分析,我们发现70%的软件测试工作仍然是通过手工或者简单的脚本来完成的,在测试团队中不具备编程能力和仅有基本脚本编写能力的测试人员仍然是测试的主力。
要让你的项目敏捷起来,对于那些仍以手工测试为主的团队而言是一个非常大的挑战,如何提高手工测试工作的效率将是实现敏捷的成败关键。在VS
2010中,微软首次为测试人员设计了一款专用的集成测试环境,称为微软测试管理器2010(Microsoft
Test Manager 2010,以下简称为MTM)。之所以称之为集成测试环境,是因为MTM的功能涵盖了测试计划、测试用例、手动测试用例的执行和录制回放、自动测试用例执行、创建信息丰富的Bug、验证Bug、以及与测试实验室管理相关的对策是自动化相关的功能等。下图展示的是MTM测试计划的操作界面,它以树形的层次结构来组织测试用例。
图4:MTM测试计划的操作界面
《敏捷序言》强调:“可工作的软件重于完备的文档”,那么是不是意味着敏捷测试也不需要测试计划呢?当然不是。敏捷的本质是要去除软件过程所有造成时间浪费地方,不需要的是那些动辄就几十或上百页的文档。敏捷对文档要求是要简明扼要,一两页列出测试要点计划还是必须的,较短迭代周期(1-4周)也不可能要求文档面面俱到。敏捷需要更快的对功能进行验证,是不是不需要编写测试用例直接根据用户故事或者功能需求进行探索性测试就可以了?当然也不是。功能需求和用户故事勾画出的是一棵大树躯干和主要枝杈,而那测试用例则不但要准确描述出躯干和主枝,还要描述出细小的枝杈和绿叶的正确位置。从某种意义上讲,测试用例在敏捷中的作用和地位应该更为加强,它扮演着详细功能文档的角色。功能需求和设计文档可以简单,但测试用例可不是这样,相反我认为敏捷对测试用例的设计和管理要求更高。
每个迭代周期,团队都会专注于实现不同的产品功能,用户故事虽然描述了功能的内容,但并不足以覆盖所有相关的内容。很多由用户故事展开和关联的功能一般在文档中会体现出来,需要测试人员在早期围绕着用户故事测试展开需求文档测试(需求评审),已明确那些未严格定义出来的内容,以测试用例的形式明确和记录下来。由1个简单用户故事就有可能扩展为1+N用户可能执行的执行片段,也就我们测试用例。当你有M个用故事,需要M个迭代周期来完成产品,那么就会有
( M + N1 + N2 … + NM) 个测试用例,不把它们落实到笔头上,很容易就会丢失一些重要的测试细节。此外,在敏捷方法中需求变化比较快,随着多个迭代的深入,文档的变化往往赶不上产品功能的变化,这时唯一能够赶上这个变化的只有测试用例,应为只有它准确地反映了产品的变化,否则测试用例就是无法通过的。
图5:测试用例
在MTM 中,测试用例被分类至各个测试用例集,结构十分清晰。测试用例只是逻辑上从属于某个测试用例集,并没有物理从属关系,即一个测试用例可以同时被分在多个测试用例集内,比如某个测试用例性质上是一个性能测试,但是由于该用户故事的诉求就是性能改进,我们也就很自然得可以将其作为该用户故事的验收测试,此时我们就可以将此测试用例添加到验收测试和性能测试两个测试用例集中;另一个例子是给每个用户故事都定义了不少测试,这些测试用例都应该能在用户故事测试用例集下找到,但是这些测试既可能是手动测试也可能是自动化测试用例,所以它们又会被本别归类至这两个测试用例集。在这种逻辑分类的支持下,我们可以很容易的根据需要指定运行测试集中一部分测试用例。比如,我们可以定义一个签入测试的测试用例集,挑选最基本的若干个测试置入其中,这样在每次签入前通过运行这个测试用例集就能帮助我们确保签入的代码不至于破坏最基本的功能,即保证了版本随时可运行可测试,这无疑为测试带来了更多的方便。具体如何创建测试用例集的结构,团队可以根据自己项目的特点,灵活运用此功能,制定分类规则以提高工作的效率。
很多测试团队仍然在使用Word或者是Excel管理测试用例,有些是使用专门的测试用例管理工具,使用独立的数据库来存储测试用例信息。MTM相对于这些工具的优点在于,它的所有数据都是存储在TFS上,测试用例使用的是Test
Case工作项。由于同存储在TFS 上,所以可以轻松的实现与其它数据项的关联,例如:在上一部分我们介绍的不同类型工作项之间关联,此外还可以把Test
Case与代码关联,即将测试用例与自动化测试代码关联。这样在MTM中,也可以直接管理和运行自动化测试用例,使MTM兼具了管理手工测试用例和自动化测试用例的能力。
探索性测试(Exploratory Testing)是测试人员在对被测试系统的功能进行不断了解和学习的过程中进行测试,包括:设计测试用例、执行测试、以及汇报测试结果。与传统的测试相比,它不需要事先定义好的齐备的测试文档,更强调测试人员在对系统不断地学习中,边了解边测试,它在很大程度上给测试人员更多地自由和想象空间,充分发挥他们的创造力,在不断地学习中找到测试的灵感和快乐。这种测试的灵感和快乐对于组建和培养一支热爱测试的团队是非常非常重要,它会让测试人员觉得自己不是执行重复测试劳动机器,而是一个有着创造力和灵光的团队成员。MTM也支持探索测试功能,用户可以使用MTM创建一个仅有一个测试步骤的测试用例,然后执行它,Test
Runner工具会辅助执行手动测试。它会记录下所有用户的操作,一旦发现有Bug时候,可以直接选择‘Create
exploratory bug’直接创建一个Bug。
图6:创建一个Bug
Bug是测试工作最重要的产出之一,也是测试和开发人员之间重要接触点。每个提交的Bug都应该详细记录下如何重现(reproduce)的步骤,这是衡量Bug质量的重要因素之一。因为不可重现的Bug是没有意义的,只会耽误开发人员和项目经理的时间。偶尔出现不可重现的Bug还是可以理解的,但如果经常出现,那就会引来开发人员的抱怨和不满,久而久之会造成开发和测试之间的不信任。
好的Bug应该是有清晰和详细的重现步骤,期望的结果和实际得到结果,并提供尽可能多的信息,例如:出现问题的产品版本编号、语言、操作系统的版本以及日志信息等。大多数情况下,用文字进行描述的内容就可以了,但如果能配上一张问题现场截图,或者对于更为复杂的Bug,配上一段小的录像,这样的Bug会给开发人员快速诊断和修复产品问题带来很大帮助,大大提升测试和开发人员之间的协作效率,避免了不可重现Bug在开发和测试之间推来推去的“Bug乒乓”现象。然而要收工创建这样一个信息丰富的Bug,是需要很多时间的。MTM提供了这样的功能为帮助测试人员创建这样高质量Bug,它实现了多种诊断数据适配器(Diagnostic
Data Adapters),在测试确认Bug的过程中,这些适配器会在后台运行收集大量的数据,包括:执行操作、系统配置、IntelliTrace已经操作过程的录像等,当测试人员要创建一个Bug时,这些信息会被自动添加的Bug中,如下图所示,测试仅需填写很少的内容就可以创建好一个信息丰富的Bug。
图7:信息丰富的Bug
实现自动化测试用例——自动化测试用例框架
随着需求的不断变化和迭代的深入,代码库不可避免的会有频繁的签入和签出,此时测试人员一项很重要的任务就是要预防回归问题发生。执行手工测试用例可以帮助我们预防及和发现回归问题,但是它的执行效率太低,无法胜任频繁执行的要求。这时就我们需要考虑采用自动化测试用例完成这项工作。决定是否采用自动化测试是有很多因素决定,其中很重要的一条就是自动测试的收益,下面的公式从概念上解释了如何来计算这个收益,当收益值大于1的时候,实施自动化测试就是合算的;否则,就是不合算的。
图1:计算收益公式
这其中,开发和维护自动测试的成本是影响这个收益的重要因素,为此VS 2010提供了一整套的解决方案,帮助测试团队减少这部分成本,这包括前面我们所提到的测试计划和用力管理工具,以及后面将会要介绍的生成和实验室管理。此外,Visual
Studio 提供了多种测试工程模板,帮助测试人员开发自动化的测试用例,如下图所示。
图2:Visual Studio提供的多种测试模板
这些测试工程模板可以帮助测试自动化工程师,在Visual Studio
集成开发环境中创建和管理单元测试、功能测试、Web性能测试、负载测试等等一系列的自动化测试用例。这其中,编码的UI测试(Coded
UI Test,以下简称为CUIT)是首次出现,是VS 2010测试部分一大亮点。测试人员可以通过它使用C#或者
VB.NET语言编写自动化测试用例,从用户界面层驱动Web、Winform或者是WPF的应用。CUIT为测试用例的自动化提供了一个框架、API和可扩展的接口,测试人员可以很轻松地开发出所要的自动化测试用例。其实CUIT背后的测试自动化实现技术对大家并不陌生,下面列出针对Web、WinForm和WPF应用的测试技术基础。对每种技术的支持采用的是插件的形式实现的,VS
2010包括了如下的三种插件:
- Document Object Model(DOM)插件 : IE 7/8 HTML/AJAX
- User Interface Automation(UIA)插件 : WPF
- Microsoft Active Accessibility(MSAA)插件 : Winform,Win32和MFC
。MSAA插件是默认选项,用来支持出其它两者之外的任何应用。
CUIT 现在支持主要的微软平台,详细的内容可以参见MSDN : Supported
Configuration and Platforms for Coded UI Tests and Action
Recordings。对于那些尚不支持的平台或者UI控件,CUIT提供了很好的扩展机制,允许大家针对自己的特殊应用进行扩充,下图就是CUIT框架的体系结构图
。
图3:CUIT框架的体系结构
开发自动化测试用例对于有效预防回归问题的出现时非常必要,在实际应用中应该特别注意它的合理比例关系和灵活的策略,包括:自动化用例和手工用例的比例、UI和非UI测试用例的比例关系。自动化测试用例、执行、分析和维护它们都是需要一定投入的,对于敏捷项目而言时间资源的紧缺尤为突出,所以在任何时候团队都要根据自身的资源,有选择性进行测试用例的自动化,通常情况下应该优先自动化那些高优先级的测试用例。
对于UI和非UI的自动化测试用例而言,应该是以非UI 的单元测试和功能测试为主,UI测试未必要的补充。基于UI自动化测试用例有它独特优点,例如:它从真实用户角度出发进行测试,即涵盖了界面层、逻辑层和数据层,自动化人员不需要了解被测试应用的代码实现细节等;但是相对于非UI测试它也有着先天的不足,包括:执行速度相对比较慢、易受干扰不稳定等。所以在自动化过程中,能用非UI测试覆盖的功能尽可能采用非UI的测试覆盖,如:API单元测试等,UI测试用例只用来实现最基本用户故事的验收测试(Acceptance
Test)。
早测试和经常测试——封闭签入和滚动生成
敏捷开发中最可怕的事情莫过于在迭代最后一两天进行测试,结果发现了严重功能缺陷或者回归缺陷,导致不能按计划发布给用户试用。要想彻底解决这样的问题,一方面要在迭代开发阶段测试人员就要参与进来,从客户的角度出发对功能需求和设计文档进行文档测试,即文档评审。测试人员和开发还有项目经理一起从源头上保障将要实现的功能是用户想要的。另一方面就是要在迭代的早期就开始就开始测试,特别前几个迭代已经实现好的自动化测试用例,尽早的执行它们可以有效地避免回归问题的出现。在TFS
2010上专门提供封闭签入(Gated Check-in)、滚动生成(Rolling Builds)和持续集成(Continuous
Integration)等功能,帮助敏捷团队实现早测试和经常测试。这其中封闭签入和滚动生成是对敏捷团队比较实用的功能。
图4:选择签入方式
封闭签入是TFS 2010提供的一种新的代码签入方式,在配置这项功能后,当用户要签入任何代码时,系统会先将用户本地要签入的代码打包成一个搁置集(shelve-set),然后提交到服务器端,TFS生成(Build)服务先从TFS源代码控制器中同步项目的最新代码,再将提交的代码与之进行自动合并,然后进行编译,如果编译成功,则执行配置的自动化测试用例,如果测试用例全部通过则代码会被自动签入到代码库中,否则返回错误信息给用户,代码是不会进入到代码库。表面上看是与产品测试没有直接关系,但实际上它和测试以及最终产品质量的密不可分。因为代码签入是整个开发过程中发生最为频繁的操作,每次签入代码的质量直接影响着日常的开发活动。对于绝大多数的开发团队来说,check
in代码前不仅要保证编译通过,同时还要最大限度的保证新代码不会破坏已有的功能,也就是要执行测试用例去验证。Gated
Check-in中提到的“Build成功”,实际上包含两部分内容:编译成功和测试用例执行成功,有了它作为保护代码库的第一道屏障,就可以保证它在任何适合都是可编译,并且达到一定质量标准的。
滚动生成是在VS 2008种就有的功能,当TFS检测到在它所监控的范围内有任何新的代码变化被签入后,它就启动对最新的代码库进行生成验证,该验证包括编译和运行指定的自动化测试用例。之所以称之为“滚动”,因为它是在一个生成验证操作完成后再去探测有没有新的签入发生,对这期间发生的所有新签入进行新的生成验证。这里需要再强调一下滚动生成的重要意义:它看似只是一个自动生成代码的功能,但实际上起着协调整个开发团队、时刻监控代码库质量、以及尽早暴露产品问题的作用。因为滚动生成时刻都在不停的运转着,对于任何代码签入它都保持着警觉,会去自动验证编译是否成功,自动化测试用例是否都能通过。它就像一个不知疲倦的“代码守护者”一样监控着代码库,第一时间发现其中的任何问题,将问题通知给整个团队,从而避免了问题的积累和拖延。这非常符合敏捷开发中“今日问题今日解决,不要拖到以后”的原则,它帮你最早的发现问题、报告问题,开发团队则应该建立制度要及时响应滚动生成所报告的问题,把它作为Priority
为0或1的高优先级问题去对待和解决。
封闭签入和滚动生成都是来保护代码库的正确性和产品质量,它们是否在功能上重复反而让我们不敏捷了呢?其实两者并不重复,只是各有侧重,将它们搭配使用才会发挥其最大效能。封闭签入是在代码进入代码库之前进行验证,签入提交者一般希望竟快知道结果,以便决定下一步的工作,所以封闭签入的时间(编译和运行测试用例)不要太长(10-20分钟)。这也就决定了我们加入的测试用例不能太多,只添加那些高优先级的测试用例,保证主要的用户故事不被破坏。滚动生成是在代码签入后在后台执行的,由于不存在着与用户的交互等待,所以它执行时间可以更长(几个小时),可以为它加入更多的测试用例,从而全面验证代码库的质量,一旦有任何问题它可以及时通知团队进行修复,这种验证是在几个小时或者每天都在发生的,保证了敏捷对频繁测试的。
完整的自动化测试解决方案——实验室管理
在谈到软件自动化测试的时候,很多人会误以为实现了自动化测试用例就是自动化测试,其实不然,自动化测试仅是测试自动化的一个重要步骤,绝对不等同于自动化测试。一个完整的自动化测试应该包括:构建、部署、执行测试用例、分析测试结果并作出结论。在前面的自动测试的收益公式中,我们可以看到减少自动测试的维护成本,是提高自动测试收益的重要因素之一。VS
2010的实验室管理(Lab Management)与测试用例管理、生成管理、源代码控制、工作项管理等功能相结合,为自动化测试提供了这样一个完整的解决方案,目标就是要降低了自动测试的运营和非维护成本,下面这张图展示了实验室环境的系统构架图。
图5:实验室环境的系统构架图
实验室管理功能充分利用了微软的虚拟化技术,包括:Hyper-V和 System
Center Virtual Machine Manager (SCVMM),快速创建干净的虚拟测试环境并进行产品生成和部署,然后执行指定的测试用例集,将结果以报表的形式呈现出来,方便对此产品质量进行分析,如下图所示:
图6:虚拟测试环境
图7:测试结果
同时,利用虚拟技术的环境快照功能,对于那些难于复现或者环境相关的Bug,利用虚拟环境的快照技术,可以为开发人员准确的复现Bug出现的环境,从而能够快速的进行诊断和及时修复。
总结
Visual Studio 2010作为Visual Studio系列中一个非常重要的版本,为测试人员和团队提供了一整套解决方案,包括:测试计划和用例管理、创建自动化测试用例、测试用例的自动执行、以及实验室管理等。这些功能强调了测试作为整个软件过程的重要角色的作用,促进了测试人员与其它角色的有效沟通与协作,非常适合于敏捷团队使用来完成测试工作。
工具不是万能的,但没有合适的工具辅助也是万万不能的。对于工具在敏捷开发的作用,应该用辩证的观点来看待。不能片面唯工具论,毕竟软件开发过程是人、工具和过程三者共同作用的结果,工具影响着人和过程,同时人和过程也影响着工具所能发挥的效力。所以这决定了工具的引入和部署应该是一个渐进的和逐步适应的过程,特别是对Visual
Studio 2010这样比较大型和综合性的工具。下面是三个向大家推荐的与Visual Studio测试相关的微软论坛,希望能够对大家有所帮助。
- Testing with Visual Studio Test Manager (MTM)
- Visual Studio UI Automation Testing (includes CodedUI)
Visual Studio Team System - Testing参考文献
1.A different way of presenting the
Visual Studio 2010 testing tools
2.Content Index for Coded UI Test
3.Series on Coded UI Test Extensibility
4.Microsoft Test Runner series – part
7 – Exploratory Testing
5.Testing the Application |