软件测试策略模式_第1页
软件测试策略模式_第2页
软件测试策略模式_第3页
软件测试策略模式_第4页
软件测试策略模式_第5页
已阅读5页,还剩43页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

_软件测试面试必备第18章测试策略模式18.1 记录测试(也称为记录与回放测试、机器人用户测试、捕获/回放测试)如何准备软件的自动化测试?通过记录与应用程序的交互并使用测试工具回放它们来自动化测试。图18-1 记录测试示意图自动化测试有几个目的。在回归测试软件更改之后,它们可以用于这些软件。它们有助于归档软件的行为。在写软件之前,它们可以指定其行为。如何准备自动化测试脚本,对可以将它们用于什么目的、它们对SUT中的变更有多健壮以及准备它们需要多少技能与努力等产生影响。记录测试使得能够在构建SUT之后、改变它之前迅速创建回归测试。18.1.1 运行原理我们使用一种工具,它会监控我们与SUT的交互。这种工具记录大多数SUT对我们的通信以及我们对SUT的响应。录音会话完成之后,可以将它保存在文件里以便稍后回放。准备运行测试时,可以从工具的“回放”部分开始,并让它指向录音会话。它启动SUT,并给它提供响应SUT输出的记录输入。在录音会话内,它也可以比较SUT的输出及其响应。错误匹配可能导致测试失败。有些记录测试工具允许调整录音会话内SUT表现与回放过程中SUT表现之间比较的敏感性。大多数记录测试工具通过用户界面与SUT交互。18.1.2 使用时机如果应用程序正在运行,但不希望对它进行太多变更,就可以使用记录测试进行回归测试。现有应用程序需要重构(预计修改功能性)而没有可用的脚本测试用作回归测试时,也可以使用记录测试。通常,生成一组记录测试比准备具有相同功能性的脚本测试更快。在理论上,任何知道如何运行应用程序的人都可以完成测试记录,几乎不需要专业技术。实际上,许多商业工具都值得深入学习。同时,需要一些专业技术来添加“检查点”,以便调整回放工具的敏感性,或者调整测试脚本(如果记录工具记录了错误信息)。大多数记录测试工具通过用户界面与SUT交互。如果SUT的用户界面不断发展,这种方法特别容易让它们变得脆弱(接口敏感性,参见“脆弱测试”)。甚至是小的变更(例如改变按钮或字段的内部名称)也足以让回放工具产生错误。这些工具也倾向于在低级别详细记录信息,这样会让测试难以理解(参见“模糊测试”)。因此,如果对SUT的变更中止了这些工具,也很难手动修复它们。所以,如果SUT不断发展,就要准备有规律地再记录测试。如果要使用作为文档的测试或者要使用这些测试驱动新的开发,就应该考虑使用脚本测试。使用商业记录测试工具难以实现这些目标,因为大多数工具不允许定义用于测试记录的高级语言。将记录测试性能构建到应用程序本身之中或者使用重构的记录测试可以解决这个问题。变体:重构的记录测试这两种策略的混合是,使用“记录、重构、回放”1 名称“记录、重构、回放”是Adam Geras提出来的。顺序从最新记录测试中提取一组“动作组件”或“动词”,然后通过测试用例来调用这些“动作组件”(而不是使用详细的内联代码)。大多数商业捕获/回放工具提供将字面值转换为参数的方法,主要的测试用例可以将这些参数传递到“动作组件”。屏幕改变时,只需再记录“动作组件”,所有测试用例自动使用新的“动作组件”定义继续运行。这种策略在效能上与使用测试实用程序方法与单元测试中的SUT交互相同。它允许使用重构的记录测试组件作为脚本测试中的高级语言。像Mercury Interactive的BPT2 BPT是“业务进程测试(Business Process Testing)”的缩写。这样的工具以自顶向下的方法将这一范式用于脚本测试。开发完高级脚本并指定了测试步骤所需的组件之后,更多的技术人员就可以记录或手动编码单个组件。18.1.3 实现方式说明使用记录测试策略时,有两种基本选择:可以获得第三方工具,它记录与应用程序交互时发生的通信;可以将“记录与回放”机制内置于应用程序。1. 变体:外部测试记录在商业上有许多测试记录工具可用,每种工具都有自身的优缺点。最好的选择取决于应用程序用户接口的性质、预算、要验证的功能性的复杂性以及其他可能的因素。如果要使用测试来驱动开发,就需要挑选使用测试记录文件格式的工具,这种格式可以手动编辑且易于理解。需要手动编写内容,如果使用“记录与回放”工具来执行测试,这种情况也还是脚本测试的示例。2. 变体:内置测试记录也可以将记录测试性能内置于SUT。在那种情况下,可以用相当高的级别定义测试脚本“语言”,级别足够高,就可以在构建系统之前手动编写测试。实际上,有报告说Microsoft Excel电子数据表的VBA宏性能是Excel自动化测试机制的开端。18.1.4 示例:内置测试记录从表面上看,提供记录测试的代码样本没有意义,因为这种模式处理生成测试的方法,而不是表示它的方法。回放测试时,实际上就是数据驱动测试。同样,通常不重构到记录测试,因为它经常是项目尝试的第一种测试自动化策略。而且,如果发现有过多遗漏的测试,还可以在尝试脚本测试之后引入记录测试,因为手动自动化的成本太高。在那种情况下,不应该试图将现有脚本测试转换为记录测试,应该记录新测试。下面是应用程序本身记录的测试的示例。该测试用来回归测试安全关键的应用程序,并且在它从OS2上的C移植到Windows上的C+之后。请注意,记录的信息如何形成用户易于理解的域专用高级语言。 5566 SOUTH SOUTH NORTH SOUTH NORTH 该样本表示回放测试的输出。内置回放机制插入了actual元素。status属性表示这些元素是否匹配expected值。将样式表应用于这些文件来格式化它们,就像具有彩色编码结果的Fit测试一样。然后项目的商业用户可以进行记录、回放和结果分析。在软件的表示层插入挂钩可以记录用户和用户响应提供的选项列表。其中一个挂钩的示例如下所示:if (playback_is_on() choice = get_choice_for_playback(dialog_id, choices_list); else choice = display_dialog(choices_list, row, col, title, key); if (recording_is_on() record_choice(dialog_id, choices_list, choice, key); 方法get_choice_for_playback检索used-value元素的内容,而不是要求用户从选项列表中选取。方法record_choice生成actual元素并“断言”expected元素,记录各元素status属性的结果。注意,当处于回放模式时,recording_is_on()返回true以便记录测试结果。18.1.5 示例:商业记录与回放测试工具几乎有所商业测试工具都使用“记录与回放”隐喻。每种工具都定义自己的记录测试文件格式,其中大多数都非常冗长。下面是使用Mercury Interactive的QuickTest Professional QTP工具记录的测试的“简短”摘要。它显示于“专家视图”中,该视图表示真正记录的内容:VbScript程序!该示例包括手动插入的注释(前缀为)来说明测试在做什么,如果改变导致测试不再运行的应用程序之后记录测试,那么就会丢失这些注释。 GoToPageMaintainTaxonomy()Browser(Inf).Page(Inf).WebButton(Login).ClickBrowser(Inf).Page(Inf_2).Check CheckPoint(Inf_2)Browser(Inf).Page(Inf_2).Link(TAXONOMY LINKING).ClickBrowser(Inf).Page(Inf_3).Check CheckPoint(Inf_3)Browser(Inf).Page(Inf_3).Link(MAINTAIN TAXONOMY).ClickBrowser(Inf).Page(Inf_4).Check CheckPoint(Inf_4) AddTerm(A,Top Level, Top Level Definition)Browser(Inf).Page(Inf_4).Link(Add).Clickwait 4Browser(Inf_2).Page(Inf).Check CheckPoint(Inf_5)Browser(Inf_2).Page(Inf).WebEdit(childCodeSuffi x).Set ABrowser(Inf_2).Page(Inf).WebEdit(taxonomyDto.descript).Set Top Level Browser(Inf_2).Page(Inf).WebEdit(taxonomyDto.definiti).Set Top Level Definition Browser(Inf_2).Page(Inf).WebButton(Save).Click wait 4Browser(Inf).Page(Inf_5).Check CheckPoint(Inf_5_2) SelectTerm(A-Top Level) Browser(Inf).Page(Inf_5).WebList(selectedTaxonomyCode).Select A-Top Level AddTerm(B,Second Top Level, Second Top Level Definition)Browser(Inf).Page(Inf_5).Link(Add).Click wait 4 Browser(Inf_2).Page(Inf_2).Check CheckPoint(Inf_2_2)infofi le_;_Inform_Alberta_21.inf_;_hightlight id_; _Browser(Inf_2).Page(Inf_2)_;_ and it goes on, and on, and on .注意,测试依据应用程序用户界面描述所有输入和输出的方法。这样主要会产生两个问题:模糊测试(由记录信息的具体性质所导致)和接口敏感性(导致脆弱测试)。18.1.6 重构说明让该测试作为文档可以使之更有用,能够降低或避免高测试维护成本,支持使用一系列提取方法Fowler重构组成使用高级语言的其他测试。18.1.7 示例:重构的商业记录测试下面的示例显示重构来交流意图的相同测试:GoToPage_MaintainTaxonomy()AddTerm(A,Top Level, Top Level Defi nition)SelectTerm(A-Top Level)AddTerm(B,Second Top Level, Second Top Level Defi nition)注意,该测试的意图变得非常明显。提取的测试实用程序方法如下所示:Method GoToPage_MaintainTaxonomy()Browser(Inf).Page(Inf).WebButton(Login).Click Browser(Inf).Page(Inf_2).Check CheckPoint(Inf_2) Browser(Inf).Page(Inf_2).Link(TAXONOMY LINKING).Click Browser(Inf).Page(Inf_3).Check CheckPoint(Inf_3) Browser(Inf).Page(Inf_3).Link(MAINTAIN TAXONOMY).Click Browser(Inf).Page(Inf_4).Check CheckPoint(Inf_4)EndMethod AddTerm( code, name, description)Browser(Inf).Page(Inf_4).Link(Add).Clickwait 4Browser(Inf_2).Page(Inf).Check CheckPoint(Inf_5)Browser(Inf_2).Page(Inf).WebEdit(childCodeSuffi x).Set code Browser(Inf_2).Page(Inf).WebEdit(taxonomyDto.descript).Set name Browser(Inf_2).Page(Inf).WebEdit(taxonomyDto.defi niti).Set description Browser(Inf_2).Page(Inf).WebButton(Save).Click wait 4Browser(Inf).Page(Inf_5).Check CheckPoint(Inf_5_2) endMethod SelectTerm( path )Browser(Inf).Page(Inf_5).WebList(selectedTaxonomyCode).Select pathBrowser(Inf).Page(Inf_5).Link(Add).Clickwait 4 end我将这个示例编在一起是为了说明与xUnit中做法的类似之处。不要随便运行该示例,因为在语句构成上它可能不正确。18.1.8 高级阅读论文“Agile Regression Testing Using Record and PlayBack”ARTRP介绍了将记录测试机制内置于应用程序以利于将它导出到其他平台的经验。18.2 脚本测试(也称为手写测试、手动编码测试、程序测试、自动化单元测试) 如何准备软件的自动化测试?通过手动写测试程序来自动化测试。图18-2 脚本测试示意图自动化测试有几个目的。在回归测试软件更改之后,它们可以用于这些软件。它们有助于归档软件的行为。在写软件之前,它们可以指定其行为。如何准备自动化测试脚本,这将影响可以将它们用于什么目的、它们对SUT中的变更有多健壮以及准备它们需要多少技能与努力。脚本测试允许在开发软件之前准备测试,以便它们有助于驱动设计。18.2.1 运行原理通过写测试程序来自动化测试,这些测试程序为了执行其功能性而与SUT交互。和记录测试不一样,这些测试可以是客户测试或单元测试。这些测试程序通常称为“测试脚本”,以便与它们测试的产品代码区分开来。18.2.2 使用时机准备软件的单元测试时,通常使用脚本测试。因为它更容易从用相同编程语言写的软件中直接访问单个单元。它也允许执行所有代码路径,包括“不合理的”。客户测试稍微有些复杂。当使用自动化故事测试来驱动软件开发时,应该使用脚本测试。记录测试不能很好满足这种需要,因为没有用来记录它们的应用程序时它难以记录测试。准备脚本测试可以使用编程经验以及测试方法中的经验。项目上的大多数业务用户不可能对学习如何准备脚本测试感兴趣。在编程语言中进行脚本测试的方法之一是,定义测试SUT的高级语言,然后作为数据驱动测试解释程序GOF实现该语言。一种定义数据驱动测试的开源架构是Fit及FitNesse。Canoo WebTest是支持这种类型测试的另一种工具。在现有遗留应用程序3 在测试驱动程序中,遗留应用程序是缺乏自动化测试安全网的系统。中,可以考虑使用记录测试作为快速创建一组回归测试的方法,这些回归测试在重构代码引入易测性时可以起到保护作用。随后可以准备可测试应用程序的脚本测试。18.2.3 实现方式说明传统上脚本测试写作“测试程序”,通常使用特定的测试脚本语言。现在,我们更喜欢使用测试自动化架构来写脚本测试,例如,用与SUT相同的语言写的xUnit。在这种情况下,通常以测试用例类上测试方法的形式捕获各测试程序。要最小化手动干预,各测试方法应该实现自检测试(也就是可重复的测试)。18.2.4 示例:脚本测试下面是用JUnit写的脚本测试的示例:public void testAddLineItem_quantityOne()final BigDecimal BASE_PRICE = UNIT_PRICE;final BigDecimal EXTENDED_PRICE = BASE_PRICE;/ Set Up FixtureCustomer customer = createACustomer(NO_CUST_DISCOUNT);Invoice invoice = createInvoice(customer);/ Exercise SUTinvoice.addItemQuantity(PRODUCT, QUAN_ONE);/ Verify OutcomeLineItem expected =createLineItem( QUAN_ONE, NO_CUST_DISCOUNT,EXTENDED_PRICE, PRODUCT, invoice);assertContainsExactlyOneLineItem( invoice, expected );public void testChangeQuantity_severalQuantity()final int ORIGINAL_QUANTITY = 3;final int NEW_QUANTITY = 5;final BigDecimal BASE_PRICE =UNIT_PRICE.multiply( new BigDecimal(NEW_QUANTITY);final BigDecimal EXTENDED_PRICE =BASE_PRICE.subtract(BASE_PRICE.multiply(CUST_DISCOUNT_PC.movePointLeft(2);/ Set Up FixtureCustomer customer = createACustomer(CUST_DISCOUNT_PC);Invoice invoice = createInvoice(customer);Product product = createAProduct( UNIT_PRICE);invoice.addItemQuantity(product, ORIGINAL_QUANTITY);/ Exercise SUTinvoice.changeQuantityForProduct(product, NEW_QUANTITY);/ Verify OutcomeLineItem expected = createLineItem( NEW_QUANTITY,CUST_DISCOUNT_PC, EXTENDED_PRICE, PRODUCT, invoice);assertContainsExactlyOneLineItem( invoice, expected ); 18.2.5 关于名称自动化测试程序通常称为“测试脚本”,可能是因为继承了这些测试程序,这些程序最初在解释性测试脚本语言(例如Tcl)中实现。称它们为脚本测试的不利之处是,该术语容易将手动测试过程中应遵循的脚本与不用脚本的测试(例如探测测试)相混淆。18.2.6 高级阅读许多书籍介绍了写脚本测试以及使用它们驱动SUT设计的过程。最好可以从TDD-BE 或TDD-APG开始。18.3 数据驱动测试 如何准备软件的自动化测试?如何减少测试码复制?将各测试所需的信息存储在数据文件里,并写阅读文件和执行测试的解释程序。图18-3 数据驱动测试示意图测试可能有很多重复,不仅因为必须多次运行相同测试,而且因为许多测试只是略有不同。例如,要运行本质上相同但系统输入略有不同的测试,并验证实际输出是不是具有相应改变。每个测试都由相同的步骤组成。拥有这么多测试是确保完好功能性覆盖率的好方法,但对于测试可维护性而言它却不是好方法,因为对某个测试算法的变更一定会传播给所有类似测试。数据驱动测试可以获得好的覆盖率同时又能最小化需要编写和维护的测试码的数量。18.3.1 运行原理写数据驱动测试解释程序,它包含测试的所有公共逻辑。可以将随着测试改变而改变的数据放置到数据驱动测试文件中,解释程序读取该文件来执行测试。对于每个测试而言,它实现相同系列的动作来实现四阶段测试。第一阶段,解释程序检索文件中的测试数据,然后使用文件中的数据建立测试夹具。第二阶段,它执行具有文件指定参数的SUT。第三阶段,它比较SUT生成的实际结果(例如返回值、测试后状态)与文件的预期结果。如果结果不匹配,它将测试标记为失败;如果SUT抛出异常,它捕获异常并相应地标记测试然后继续。第四阶段,解释程序进行必要的夹具拆卸,然后继续执行文件中的下一个测试。需要一系列复杂步骤的测试可以简化为数据驱动测试文件中的一行数据。Fit是写数据驱动测试架构的普遍示例。18.3.2 使用时机数据驱动测试是记录测试和脚本测试的可选策略。然而,它也可以用作脚本测试策略的一部分。实际上,回放记录测试时,它们就是数据驱动测试。数据驱动测试是让业务人员写自动化测试的理想策略。保持数据文件格式简单,就可能让业务人员用数据填充文件并执行测试,而无需要求技术人员写各种测试的测试码。当有许多不同的数据值,同时又希望使用这些值来执行SUT(其中每个数据值都要执行相同系列的步骤)时,可以考虑使用数据驱动测试作为脚本测试的一部分。通常会发现这种相似性会随着时间的推移而变化,因此要先重构到参数化测试,然后重构到数据驱动测试。也可能在具有不同数据值的不同序列中安排一组标准步骤,和在递增的表格测试(参见“参数化测试”)中一样。这种方法具有最好的覆盖率,同时需要维护的测试码数量也最少,如果需要,还可以很方便地添加更多测试。决定是否使用数据驱动测试的另一个因素,是配置数据是不是硬编码或驱动要测试的行为。如果使用脚本测试自动化用于数据驱动行为的测试,当配置数据改变时,就必须更新测试程序。这种行为很不正常,因为它表示,当改变配置数据库中的数据时,必须将变更提交给源代码库SCM4 当然,也应该管理在版本控制库里的测试数据,但这个主题在另一本书中讨论,详情请参见RDb。让测试变成数据驱动,对配置数据或元对象的变更就由对数据驱动测试的变更驱动,这是一种更正常的关系。18.3.3 实现方式说明实现方式选择取决于是否使用数据驱动测试作为不同的测试策略或作为基于xUnit策略的一部分。使用数据驱动测试作为独立的测试策略通常使用开源工具(例如Fit)或商业记录测试工具(例如QTP)。使用数据驱动测试作为脚本测试策略的一部分可能要实现xUnit内的数据驱动测试解释程序。不管选择哪种策略,如果可能,都应该使用相应的测试自动化架构。这样做可以有效地将测试转换为两个部分:数据驱动测试解释程序和数据驱动测试文件。这两个部分都应该保持在版本控制之下,以便可以知道它们随着时间推移如何演变,同时还允许收回所有错误的变更。将数据驱动测试文件存储在某种类型的库中至关重要,虽然这种概念与业务用户不相关。给用户提供数据驱动测试文件授权工具(例如FitNesse)可以让这种操作透明,或者可以建立“用户友好”库,例如刚好支持版本控制的文档管理系统。作为持续集成过程的一部分运行这些测试,以便确定曾经通过的测试没有突然失败,这样至关重要。没有这样做可能导致缺陷进入未检测到的软件,一旦检测到缺陷,就要付出更多努力来检修。在持续集成过程中包含客户测试要求能够记录通过的客户测试,因为提交所有代码之前不能确保所有客户测试都通过。一种选择是保持两组输入文件,将通过的测试从“仍是红色”文件迁移到“都是绿色”文件中,该文件作为自动构建过程一部分用于回归测试。1. 变体:数据驱动测试架构(Fit)使用数据驱动测试作为测试策略时,应该考虑使用预制数据驱动测试架构。Ward Cunningham最初将Fit这种架构作为在自动化测试中包含业务用户的方法。虽然Fit通常用于自动化客户测试,但如果测试数量授权构建必需的夹具,它也可用于单元测试。Fit由两部分组成:架构和用户创建的夹具。Fit架构是通用数据驱动测试解释程序,该解释程序读取输入文件并找出其中的所有表。它在每个表的左上单元查找夹具类名,然后搜索该类的可执行测试。当它找到类并读取该表的行和列时,它会创建该类的实例并将控件传递给该实例。可以重写架构定义的方法来指定表中各单元出现的情况。因此,Fit夹具是适配器,Fit调用它来解释数据表并调用SUT上的方法。Fit表也可以包含SUT的预期结果。Fit将指定的值与SUT返回的实际值进行比较。然而,与xUnit中的断言方法不一样,Fit在遇到第一个不匹配预期值的值时不会终止测试。相反,它给表中的各个单元涂上颜色,绿色单元表示与预期值相匹配的实际值,红色单元表示错误的或意料之外的值。使用Fit有几个好处:q 与构建自己的测试解释程序GOF相比,要写的代码更少。q 输出对业务人员也有意义,而不只是对技术人员有意义。q 测试不会在遇到第一个失败的断言时停止。Fit可以用一种能够很容易看出失败模式的方法传达多种失败/错误。q 照现在的样子,有大量夹具类型可以用来子类化或使用。那么,为什么不在所有单元测试中都使用Fit取代xUnit呢?使用Fit的主要不足如下所述:q 在构建Fit夹具之前,测试场景必须非常易于理解。因此需要将各种测试逻辑转换为表格表示法,这不太合适,特别是对习惯于从过程思考的开发人员而言尤其如此。它适合拥有可以为客户测试写Fit夹具的测试者的情况,但这种方法不适合于真正的单元测试,除非测试者与开发人员的比例为11。q 这些测试在每个测试中都要采用相同的SUT交互逻辑5 表格数据必须在夹具建立或执行SUT阶段注入SUT,或者在结果验证阶段从SUT中检索。要运行几种不同类型的测试,很可能就必须为每种类型的测试构建一个或多个不同的夹具。构建新的夹具通常比写一些测试方法更复杂。虽然现在有许多不同夹具类型可以用来子类化或使用,但这种使用方法与要求开发人员学习以便完成任务的方法不同。尽管这样,也不是所有单元测试都要使用Fit来进行自动化。q Fit测试通常没有集成到开发人员通过xUnit运行的回归测试中。相反,这些测试必须单独运行,这样每次检入时它们有可能不运行。有些团队将Fit测试作为其持续集成构建过程的一部分,以部分解决这个问题。有的团队报告已经拥有辅助“客户”构建服务或运行所有客户测试的服务器。当然,这些问题都是可以克服的。总的来说,xUnit架构比Fit架构更适合于单元测试;Fit架构比xUnit架构更适合于客户测试。2. 变体:天真xUnit测试解释程序当需要作为基于xUnit的脚本测试策略的一部分运行的数据驱动测试的数量较小时,最简单的实现方式是写包含循环的测试方法,该循环从文件读取一组输入数据值以及预期结果。这与将单个参数化测试及其所有调用者转换为表格测试(参见“参数化测试”)具有相同意义。和表格测试一样,这种构建数据驱动测试解释程序的方法会产生具有许多断言的单个测试用例对象。它有以下几种结果:q 整组数据驱动测试将计算为单个测试。因此,将一组参数化测试转换为单个数据驱动测试会减少执行的测试数量。q 当遇到第一个失败或错误时会停止执行数据驱动测试。因此,遗漏了许多缺陷定位。有些xUnit变体允许指定失败的断言不中止测试方法的执行。q 需要确保出现失败时,断言失败能说出正在执行哪个子测试。在循环中包含try/catch语句,同时包含测试逻辑然后继续代码执行,这样可以解决最后两个问题。然而,仍然需要能够以一种有意义的方法报告测试结果(例如,“失败子测试1、3和6以及”)。要更方便地扩充数据驱动测试解释程序来处理相同数据文件中几种不同类型的测试,可以包含“动词”或“动作单词”作为数据文件中各条目的一部分。解释程序可以依据动作单词分派给不同的参数化测试。3. 变体:测试套件对象生成器让测试套件工厂(参见“测试枚举”)上的suite方法伪造与测试发现内置机制相同的测试套件对象结构,就可以避免与天真xUnit测试解释程序相关的“第一次失败时就停止”这个问题。要这样做,可以为数据驱动测试文件中的每个条目构建测试用例对象,然后用特定测试的测试数据初始化每个对象6 这与xUnit的内置测试方法发现(参见“测试发现”)机制的运行原理类似,但后者接受的是测试数据和测试方法名称。构建测试套件时,该对象知道如何执行具有加载数据的参数化测试。这样即使第一个测试用例对象遇到断言失败,也可以确保数据驱动测试能够继续执行。因此,可以让测试运行器以正常方式计算测试、错误及失败。4. 变体:测试套件对象模拟器构建测试套件对象的方法之一是创建像一个对象那样运行的测试用例对象。要求运行时该对象会阅读数据驱动测试文件并重新执行所有测试。它必须捕获参数化测试抛出的所有异常,然后继续执行后面的测试。完成后,测试用例对象必须给测试运行器报告测试、失败和错误的准确数量。它也要实现测试运行器依赖的标准测试接口上的其他方法,例如返回“套件”中测试的数量、返回套件中每个测试的名称和状态(关于图形测试树探测器,参见“测试运行器”)。18.3.4 启发示例假设有一组测试如下所示:def test_extrefsourceXml = expectedHtml = abcgenerateAndVerifyHtml(sourceXml,expectedHtml,)enddef test_testterm_normalsourceXml = expectedHtml = abcgenerateAndVerifyHtml(sourceXml,expectedHtml,)enddef test_testterm_pluralsourceXml = expectedHtml = abcsgenerateAndVerifyHtml(sourceXml,expectedHtml,)end如下定义参数化测试可以简化这些测试:def generateAndVerifyHtml( sourceXml, expectedHtml,message, &block) mockFile = MockFile.new sourceXml.delete!(t)handler = setupHandler(sourceXml, mockFile )block.call unless block = = nil handler.printBodyContents actual_html = mockFile.output assert_equal_html(expectedHtml, actual_html, message + html output) actual_html end这些测试存在的主要问题是,这些测试还是用代码写的,而实际上它们之间的唯一不同是用作输入的数据。18.3.5 重构说明当然,解决方案是将参数化测试的公共逻辑提取到数据驱动测试解释程序中,并将所有参数集合到任何人都可以编辑的单个数据文件中。需要写“主”测试,它知道从哪个文件阅读测试数据,知道阅读和分析测试文件的一些逻辑。该逻辑可以调用现有的参数化测试逻辑,并让xUnit记录测试执行统计。18.3.6 示例:使用XML数据文件的xUnit数据驱动测试本示例中,使用XML形式文件。每个测试都由test元素组成,它有三个主要部分:q 告诉数据驱动测试解释程序要运行哪种测试逻辑的动作(例如,crossref)。q 传递给SUT的输入,这里是sourceXml元素q 希望SUT(在expectedHtml元素中)生成的HTML这三个部分包装在testsuite元素里: crossref abc crossref abc crossref abcs 所有拥有XML编辑器的人都可以编辑这个XML文件,而不必担心引入测试逻辑错误。数据驱动测试解释程序封装用来验证预期结果的所有逻辑,使用的方法与参数化测试使用的方法相同。出于查看的目的,通过定义样式表对用户隐藏了XML的结构。另外,许多XML编辑器会将XML转换为基于表格的输入以简化编辑。为了避免处理操作XML的复杂性,解释程序也可以使用CSV文件作为输入。18.3.7 示例:使用CSV输入文件的xUnit数据驱动测试使用CSV文件,前面示例中的测试则如下所示:ID, Action, SourceXml, ExpectedHtml Extref,crossref,abc TTerm,crossref,abc TTerms,crossref,abcs这个解释程序相对简单,并且建立在为参数化测试而开发的逻辑之上。它阅读CSV文件,并使用Ruby的split函数分析各行。def test_crossrefexecuteDataDrivenTest CrossrefHandlerTest.txt enddef executeDataDrivenTest filename dataFile = File.open(filename) dataFile.each_line do | line |desc, action, part2 = line.split(,) sourceXml, expectedHtml, leftOver = part2.split(,) if crossref= =action.stripgenerateAndVerifyHtml sourceXml, expectedHtml, desc else # new verbs go before here as elsifsreport_error( unknown action + action.strip ) end end end除非将generateAndVerifyHtml的实现方式改变为捕获断言失败和增加失败计数器,这种数据驱动测试才会在遇到第一个失败断言时停止执行。而回归测试可以接受这种行为,虽然它没有提供很好的缺陷定位。18.3.8 示例:使用Fit架构的数据驱动测试如果要进一步控制用户的行为,可以创建Fit“列夹具”,其中有id、action、source XML和expected Html()各列,让用户编辑HTML Web页面(如表18-1所示)。表18-1 使用Fit架构构建的数据驱动测试Com.xunitpattens.fit.CrossrefHandlerFixtureidactionsource XMLexpected HtrnlOExtrefcrossref?abc?TestTermcrossref?abc?TestTerm Pluralcrossref?abcs?使用Fit时,测试解释程序是测试专用的Fit夹具类扩充的Fit架构:public class CrossrefHandlerFixture extends ColumnFixture / Input columns public String id;public String action; public String sourceXML;/ Output columnspublic String expectedHtml() return generateHtml(sourceXML); Fit架构依据列标题,为Fit表中每一行的每一个单元调用这种夹具类的方法。简单的名称解释为夹具的实例变量(例如id、source XML)。以()结尾的列名称表示Fit调用的函数,然后将其结果与单元格内容作比较。结果输出如表18-2所示。这种带阴影的表格非常便于总结运行测试文件后的结果。表18-2 执行Fit测试的结果com. xunitpattems.fit.CrossrefHandlerFixtureidActionsource XMLexpected HtrnlQextrefcrossref?abc?TestTermcrossref?abc?TestTerm Pluralcrossref?abcs? 预期?abc? 实际18.4 测试自动化架构 如何让编写和运行不同人写的测试更方便?可以使用架构,该架构提供运行测试逻辑所需的所有机制,因此测试作者只需要提供测试专用逻辑就行了。写和运行自动化测试包含几个步骤,但对于每个测试而言其中许多步骤都相同。如果每个测试都必须包含这些步骤的实现方式,写自动化测试就变得很单调、很耗时间、容易出错并且成本很高。使用测试自动化架构是一种最小化写全自动化测试努力的方法。图18-4 测试自动化架构示意图18.4.1 运行原理可以构建一种架构,它实现运行测试套件和记录结果所需的所有机制。这些机制能够找出单个测试、将它们组合为测试套件、依次执行每个测试、验证预期结果、收集和报告测试失败或错误以及发生失败或错误时能够清除它们。这种架构提供了一种方法来插入并运行测试自动化人员写的测试专用行为。18.4.2 这样做的原因构建可重复且健壮的全自动化测试,该过程比写调用SUT的测试脚本更复杂。需要应付成功情况和错误情况,以及预期结果与意外结果。需要建立和拆卸测试夹具,需要指定运行哪个(哪些)测试,运行一组测试后还要报告结果。构建全自动化测试需要的努力可能是测试自动化的严重阻碍。只提供实现最常见功能性的架构,可

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论