65.9K
CodeProject 正在变化。 阅读更多。
Home

具有断言验证的数据驱动 Web 服务测试

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2016年7月7日

MIT

17分钟阅读

viewsIcon

14227

downloadIcon

167

一种用于自动化基于Web服务的组件测试的解决方案模式。

引言

如今,许多组织,尤其是在客户拥有移动设备的商业领域,都在围绕Web服务(WS)组件构建其IT体系结构。这使得业务解决方案的整体运营特性可以与最终能够很大程度上独立更新和部署的各个部分松散耦合。

背景

这篇文章的灵感来自于作者为一家全球性企业提供咨询服务,该公司正在开发一个涉及WS组件的战略平台,因此对断言这些组件的正确操作行为深感兴趣。这里提出的解决方案建立在此经验之上,并提供了一种通用的方法,可用于任何基于XML/SOAP的服务。它还将响应验证视为一个关键方面,在单个字段基础上断言结果,同时保持用户的可访问性。在设计此解决方案时,我脑海中的关键概念是:

  • 可扩展性
  • 可访问
  • 断言式
  • 可维护

概述

这里提出的自动化Web服务测试平台基于SoapUI的使用。该工具被广泛使用,不仅被开发团队使用,也被架构师和精通技术的业务人员使用。为了说明场景,提议的自动化数据驱动平台可以可视化如下:

我们看到一个SoapUi进程,其中包含Groovy脚本和一个专门的Java对象,从左侧的数据驱动电子表格以及每个待测服务的请求(RQ)和响应(RS)示例文件对中读取数据。后者文件按照SoapUI界面中的样子显示,只是RQ中的所有字段值都被替换为特殊表示法。执行SoapUI中的一个测试用例会读取数据驱动电子表格中特定于该测试用例的工作表,并按顺序执行其中定义的测试。在电子表格中,测试的详细信息包括请求和相应的响应字段定义。

详细信息

在许多涉及WS架构的项目中,SoapUI (www.soapui.com) 的使用是例行的。这种使用通常涉及业务和技术参与者。然而,在许多组织中,特别是那些不愿为外部工具购买许可证的组织,SoapUI等产品的版本仅限于“免费”版本,其功能有所减少。就SoapUI而言,免费版本缺少数据驱动的方面。这里的方法为这个问题提供了一个稳健的解决方案,同时保留了免费产品的用户。在考虑Web服务的质量保证时,除了希望进行数据驱动测试之外,我们还需要处理以下具有挑战性的问题:

  • 构建合适的请求,根据正在执行的测试的具体要求设置其内容字段
  • 在字段级别断言,我们获得了测试所需的精确响应
  • 以一种可扩展、灵活且可维护的方式指定请求/响应信息。在后者方面,我们不希望自己参与编写冗长复杂的脚本

设计

为了实现上述目标,这里提出的架构包含两个主要部分:

  • 一组位于测试用例级别的SoapUI Groovy脚本。这些脚本指定了与测试执行相关的基本工作流程。
  • 一个具有类和相关方法的Java对象,由脚本调用并执行“繁重”的操作。这种分离设计的关键优势在于,它使脚本部分的逻辑非常轻量,从而提高了可维护性。编写和维护具有海量复杂编程的脚本将是一场实际的噩梦。

示例概述

为了探讨提议的设计,我将展示一个使用公开可用的Web服务FlightStats (www.FlightStats.com),特别是其机场服务的真实世界示例。由于在旅行领域(Open Travel, IATA NDC/EDIST等)有处理模式和消息的经验,作者很自然地选择使用此类服务来演示解决方案。为了使用此服务,您需要创建一个FlightStats的开发者帐户,然后使用机场服务的已发布WSDL文件URI在SoapUI中创建一个项目(SoaupUI: 文件 > 创建项目,输入项目名称,输入WSDL URI,选择“创建TestSuite”)。当然,您也可以从其他提供商那里获取服务,解决方案中没有任何内容会阻止您这样做,但以下所有细节均基于FlighStats机场服务。下面显示了项目在此初始阶段的视图:

为了描述方法的细节,建议您从下载中获取SoapUI项目(FlightStatsAirport-soapui-project.xml)。

项目配置

我们这里提出的平台要求使用在项目级别指定的属性。这些自定义属性的分配如下表所示:

信号强度 名称
项目 FileRootPath (*) C:\Users\Public\Documents
  ServiceEndpoint (*) Api.flightstats.com:443/flex/flightstatus/soap/v2/airportService

这些属性在SoapUI中的设置如下图所示:

脚本

如上所述,测试自动化设计中的关键部分之一是Groovy脚本。这些脚本定义在TestSuite/TestCase级别,特别是作为单独的脚本测试步骤。下图显示了设置:

TestCase Status_arr中的TestSteps包含四个Groovy脚本元素和一个SOAP请求元素。脚本元素总结如下(注意:脚本TestSteps的名称很重要):

ScriptName 注释
TestSetup 此脚本实例化支持测试自动化的Java对象(Hub)。
ConstructRQ 此脚本调用Hub上的方法来构建合适的Web服务RQ。
ValidateRS 此脚本调用Hub上的方法来验证从服务返回的Web服务RS。
TestFinalise 此脚本调用Hub上的方法来确定是否需要执行更多测试。

使用这些脚本的主要设计目标是清晰地分离不同的关注点。为了本次演示的目的,我们将查看TestCase“Status_arr”的脚本。然而,我们在此详细介绍的脚本解决方案适用于任何TestCase,脚本本身没有任何针对测试特定服务的专门化。如上所示,有一个调用SOAP服务元素的TestStep,其名称为“SOAPREQUEST_Status_arr”。让我们详细查看每个脚本。

脚本 - TestSetup

双击脚本“TestSetup”会显示脚本窗口。脚本首先导入MT.SoapUI.DataDrivenTesting JAR中可用的类型。

它还获取必须在SoapUI项目级别设置的自定义属性(见上文)。然后配置并初始化Hub对象。

这个Hub对象作为一个一等对象运行,并拥有一系列方法,可以在整个测试工作流程中调用以完成繁重的工作。一旦初始化,该对象将被保存在SoapUI的context对象中,以便后续脚本可以获取它并使用提供的方法。设置测试用例时,我们现在需要调用Hub对象的一系列方法,这个过程如下所示:

如果我们要测试一个提供ping操作的服务,那么通过“ping”来确定服务是否确实可用于测试将会很有用。在本例中,我们没有这种可能性,因此第83行的调用仅根据项目serviceHasPing的值返回True。第96行的该方法调用检查继续测试所需的路径和文件是否确实存在。如果这些路径和文件确实存在,那么负责处理示例文件(请求和响应)的Hub方法就会被处理成Hub内的适当数据。如果此处理成功,则通过第104行的调用导入外部驱动数据。此时,所需的所有数据都已驻留在Hub对象中。

脚本 - ConstructRQ

一旦基本测试设置成功完成,处理将移至下一项任务,即ConstructRQ脚本的工作。这里的重点是构建一个请求字符串,该字符串与外部电子表格中定义的测试用例的特定数据要求相匹配。

在设置阶段,Hub已使用测试用例的序数进行了初始化。正如我们将看到的,它拥有由外部电子表格数据定义的总测试数以及“当前”测试用例的“编号”。因此,在第26、27和32行,我们调用Hub方法来检索测试用例名称和描述,以及构建合适的请求文本,而无需引用“当前”测试用例“编号”。这里我们看到一个简单但重要的例子,展示了我们如何将任务委托给Hub对象,并倾向于在脚本中保留工作流程——一种有用的关注点分离。在第32行,我们将服务请求体检索为字符串,该请求体已完全正确地构建并包含必要的字段数据,并在第38行将其保存在SoapUI的context对象中。

脚本 - SOAPRequest_Status_arr

这是实际将特殊请求发送到待测服务的脚本,一个SOAP请求测试步骤。为了提供最大的灵活性,我们按照下图设置TestRequest属性的Endpoint:

这样,我们就获取了在项目级别设置的ServiceEndpoint属性。双击SOAP请求测试步骤,我们看到一个标准的SoapUI XML RQ结构。主体内容需要替换为如下所示的属性扩展:

这与前一步骤中将特殊RQ正文(表示为字符串)保存到SoapUI context中并命名为requestText的步骤相关联。这里的总体结果是,将发送的RQ将具有在ConstructRQ脚本中设置的特殊正文内容的RQ。一旦发出请求并获得响应,处理将移至验证收到的响应的步骤。

脚本 - ValidateRS

一旦发出请求并获得响应,我们就需要验证收到的内容。这在ValidateRS脚本中完成。这里的唯一重点是获取响应字符串并将其传递给Hub进行详细验证,根据数据驱动电子表格中指定的数据进行验证。关键步骤如下:

脚本 - TestFinalise

此脚本的关键任务是决定是否还有更多测试需要执行,其执行由外部数据的范围决定。

因此,在第18行,我们看到Hub从SoapUI context中检索出来,在第20行,通过Hub方法调用确定了当前测试用例的数量,从而使我们能够确定整体测试是否完成(第24行)。如果外部数据定义了更多RQ/RS数据(第24行),我们就递增Hub的测试用例编号并转到名为“ConstructRQ”的SoapUI TestStep。如果没有在外部电子表格中定义更多测试,则整体处理终止(第38行)。

示例文件

除了脚本和Java对象之外,这里提出的设计还需要使用所谓的示例文件。这些是用于构建正确请求(请求示例)和发现响应中的正确命名空间(响应示例)的XML文件。这些文件是按接口操作指定的,并且需要位于如下所示的位置:

这些文件的路径可以用我们之前看到的项目属性来表示:{ FileRootPath}/{InterfaceVendor}/{InterfaceCollection}/{InterfaceVersion}/{test-step-name}。这些文件的名称应为:{InterfaceVendor}_{InterfaceCollection}_{test-step-name}_ExemplarRQ.xml {InterfaceVendor}_{InterfaceCollection}_{test-step-name}_ExemplarRS.xml。RQ示例可以通过将SoapUI中的请求复制粘贴到单独的文件中,并将值部分替换为具有特殊命名形式的元素来创建,如下所示:

请求中的每个“值”部分都必须替换为以下形式的唯一名称:${aaaa.bbbb.cccc…..}。这些名称是在数据驱动电子表格中引用以定义RQ单个字段的名称。RS示例可以从SoapUI的转储文件中构建,或者通过直接从SoapUI响应窗口复制粘贴来构建,使用该操作的任何有效RQ。此示例用于获取用于我们的测试验证步骤的正确响应命名空间集。

数据

如上所述,这个测试自动化平台的一个关键特性是将测试结构(以SoapUI表示)与用于测试的数据(用于构建请求和验证结果)分离开来。现在我们来看看驱动数据。下面显示了一个在(.xlsx)文件中定义的代表性测试:

整个工作簿的布局很重要,关键点是:每个要发出的测试RQ都设置在C&D列中,您可以看到我们要设置数据的字段使用我们之前看到的示例表示法进行引用。值实际上可以在电子表格中进行评估,就像在红色单元格(D5-D7)中所示的那样——API限制了我们可以获取机场到达数据的日期。每个测试RS,我们想要在每个测试中验证的数据都设置在E&F列中。我们想要在RS中验证的位置使用类似XPath的表示法进行引用,以便它代表一个唯一路径。值部分(D列)可以表示为实际文本(例如E5)或正则表达式(例如F13)。后者表示法在实际值会根据测试的日期/时间而变化时很有用。至少我们可以通过测试来确认,在引用的字段中的值的形式符合特定定义。在此数据驱动解决方案中,Excel工作簿中的工作表必须精确地命名为SoapUi TestCases的名称,这一点很重要。这种命名如上图所示。(.xlsx)文件必须保存为97/2003工作簿格式(.xls)格式。如上图所示,数据(在此特定情况下,为单个RQ/RS对)以A列中的“STOP”一词结束。此外,重要的是要注意定义RQ部分的行数可以,并且通常与定义要验证的关联RS字段的行数不同。工作簿的名称很重要;它必须采用以下格式:{InterfaceVendor}_{InterfaceCollection}_{InterfaceVersion}_DataDriver.(xlsx/xls)其中版本号的格式必须与文件名一致,并且工作表必须保存为97-2003工作簿格式(实际读取Hub的是这个)。

代码

完成繁重工作的部分是Java对象MT.SoapUI.DataDrivenTesting.jar。此对象在上面讨论的TestSetup脚本中配置。一旦将其添加到SoapUI的测试执行上下文中(在应用程序启动时加载),任何脚本都可以访问它,并且可以使用其方法来执行必要的任务。使测试解决方案成为现实所需的复杂算法都在该对象中完成,而将通用的测试流程留给SoapUI中的Groovy脚本。本文的下载内容包含(.java)文件和Javadoc描述,我们在此不独立描述代码。

示例

我们用作示例的是Status_arr操作,该操作通常提供有关指定机场的航班到达信息。特别是,我们将请求伦敦希思罗机场(LHR)的信息。测试将涉及一次Web服务调用,如上面“数据”部分所示的电子表格所示,但这里提供的方法可以完全扩展到任意数量的调用以及任意组合的数据,以确保Web服务按预期运行。Status_arr的通用项目布局和测试用例编辑器如下所示:

点击测试用例编辑器中的绿色三角形会启动执行,这会在测试用例日志窗口中产生如下所示的输出:

由于一切都是绿色的,我们应该非常高兴,对吗?也许吧。在这个数据驱动的Web服务测试方法中,通过/失败由ValidateRS TestStep的结果指示,测试用例日志窗口中的绿色实际上只表明没有程序性或执行错误。要获得清晰的结果指示,我们需要查看包含我们脚本所有日志信息的SoapUI日志窗口。对于本例,它看起来如下所示:

在这里,我们清楚地看到,我们在外部数据驱动电子表格中指定的字段级验证已成功(“*** Test Case status: PASSED”)。当然,可以扩展此基本报告,以提供与持续集成场景一致的输出。

结论

拟议的数据驱动Web服务测试方法具有许多关键属性。这些可以总结如下:

  • 关注点分离——测试结构、工作流程和测试的具体数据是分开的。这应该会提高可维护性。
  • 可访问性——测试人员只需要与电子表格进行交互,而无需深入了解脚本的细节。这也允许项目中的业务技术人员使用该平台,从而为整体质量保证流程做出贡献。
  • 断言式——验证由测试人员完全控制,在单个RS字段级别执行,提供了强有力的断言,即从Web服务调用获得的RS,无论与相应的RQ相比是好是坏的结果,都完全符合预期。
  • 可扩展性——对给定(集)接口执行的测试范围仅受测试人员需求限制。

下载

在本文的下载链接中,您将找到一系列资源:

  • Hub的Java源代码
  • RQ和RS消息的示例文件
  • Hub代码库的Javadoc
  • JXL的发行版,用于读取97-2003格式Excel工作簿的类库。
  • 将在SoapUI的TestCase中使用的脚本
  • 包含Status_arr接口操作驱动数据的两个Excel文件——一个代表少量测试,一个代表大量测试。
  • 一个README文本文件,其中提供了一些关于“安装”zip内容的基本信息。

命名约定

在采用此平台进行自己的Web服务测试时,请务必注意所使用的命名约定。这些在下表中总结:

项目 示例 注释
SoapUI中的TestCase名称 Status_arr, Status_dep 名称必须与接口中的操作名称一致。
TestCase中的TestStep名称 TestSetup, ConstructRQ, SOAPRequest_Status_arr, ValidateRS, TestFinalise 脚本会引用这些名称。SOAP请求测试步骤名称必须带有操作名称的后缀部分。
示例RQ文件名 FlightStats_Airport_Status_arr_ExemplarRQ.xml 请参阅上面的“示例”部分。
示例RS文件名 FlightStats_Airport_Status_arr_ExemplarRS.xml 请参阅上面的“示例”部分。
数据驱动XLS文件名 FlightStats_Airport_V2_0_DataDriver.(xlsx/xls) 请参阅上面的“数据”部分。

致谢

这项工作的核心主题源于作者在瑞士苏黎世的瑞士信贷银行(Credit Suisse AG)担任(测试自动化工程师)/(测试开发人员)期间进行的咨询工作。作者承认这一影响,并声明本文档中提供的方法是一项独特的工作。我还想感谢Ludovico Einaudi (www.ludovicoeinaudi.com) 在开发此解决方案期间为我带来的听觉享受。也非常感谢Abby不懈的支持。

© . All rights reserved.