快乐学习
前程无忧、中华英才非你莫属!

Cucumber-java版真正的入门到精通(Day7)

分区功能和方案                                         
 减少Cucumber运行时间最简单的方法之一就是运行更少的场景。标记您的场景,并且您可以选择要运行的场景的子集,覆盖您当前正在使用的区域。一旦工作签入,一个更大的,但仍然是减少的更快的测试子集可能运行在我们的持续集成(CI)服务器。较大的子集可能会在连续交付管道的后续步骤中运行,也可能按预定的时间间隔(如过夜或每周)运行。最后,全套方案可以按需发布,作为发布或质量保证过程的一部分。    
可能的分类       
为了促进这种工作方式,我们需要就一系列标签达成一致,以应用于我们的方案。以下是我们见过的一些典型标签:                  
请记住,标签只是自由形式的文本,所以如果我们拼错的话,黄瓜不会知道,也不会警告我们。
标记表达式                                
正如我们在解释运行方案的子集,我们可以建立的标签逻辑表达式指定我们想要黄瓜执行哪个方案。我们可以在特性,场景,场景大纲或示例块上添加标签,并且我们可以在每个标签上添加尽可能多的标签。例如,看看下面的功能文件:
功能上的标签适用于功能中的每个场景和场景大纲。场景大纲上的标签适用于与其关联的每个示例(除应用于该功能的任何标签外)。示例块上的标签适用于该块中的所有示例(除了应用于该功能和场景大纲的任何标签之外)。                      
如果我们没有任何标签表达式运行这个特性文件,将会运行六个场景(两个场景+四个示例的场景大纲)。如果我们只想运行回归或缺陷场景,我们会告诉Cucumber运行@regression或@defect,并且只运行这个特性的五个场景。相反,如果我们指定我们想要运行高风险回归的场景,我们将使用@high_risk和@regression,并运行这个功能中的四个场景。这是因为整个特性是用@high_risk标记的,但是只有一个场景和三个例子用@regression标记。最后,如果我们只运行未标记为的情况@slow,只有一个场景可以运行。对于合并标签的语法解释运行方案的子集。              使用标签,我们可以在开发过程中的不同时间建立一些场景的子集,以控制开发团队得到反馈所需的时间。随着我们的应用程序的发展,我们可以添加或删除我们的功能文件中的标签。例如,一旦我们解决了所有的技术问题,六个月内被列为高风险的功能可能会被视为风险较小。            现在我们已经探索了这个简单的技术,现在是时候从另一个角度来解决测试慢的问题了。要做到这一点,我们需要回到我们正在测试的基本问题和原因。

环境特定的步骤定义                 
 一个常见的要求是根据运行环境的不同,运行不同的场景。例如,我们可能无法访问CI环境中的外部Web服务或生产数据库,因此我们希望在测试时使用测试双打在那里运行我们的场景 另一方面,当我们在系统集成测试(SIT)或用户验收测试(UAT)环境中运行我们的场景时,我们将使用真实系统。          
我们将通过一个环境变量的Cucumber让我们的步骤定义知道如何表现。我们需要使用标准的软件开发技术来构建实现这种行为的条件逻辑。    
创建Seam                
Michael Feathers 在他的着作“有效使用遗留代码工作”  [Fea04]中介绍了接缝的概念。
他定义了这样一个接缝:       缝是一个地方,你可以改变你的程序中的行为,而无需在那个地方进行编辑。        
引入接缝的一种方法是创建一个工厂,根据环境创建接口的不同实现。我们要做的第一件事就是提取一个AtmInterface,它提供了我们的TellerSteps所依赖的功能:
然后,我们修改AtmUserInterface来实现AtmInterface并更改TellerSteps以使用AtmInterface:
现在,我们需要告诉Spring使用一个工厂来创建实例AtmUserInterface每当实现AtmInterface需要:
最后我们创建一个工厂来创建我们需要的对象:
我们所做的就是创建一个接缝,让我们可以决定要创建什么类型的AtmInterface。目前我们只是像以前一样创建一个AtmUserInterface,但是我们可以添加逻辑到工厂来决定使用不同的实现。
改变实施        
现在我们来创建一个AtmInterface的新实现。这一个不会通过用户界面,但会直接与柜员,CashSlot和帐户交互:
我们决定,当测试运行在具有用DEVELOPMENT值定义的变量CUCUMBER_ENVIRONMENT的环境中时,我们希望工厂创建一个AtmProgrammaticInterface的实例。如果变量具有不同的值,或者没有设置,它将创建一个AtmUserInterface的实例:
现在我们可以修改我们的步骤,取决于我们设置的环境变量:
1、* nix:导出CUCUMBER_ENVIRONMENT =开发                            
2、 Windows:设置CUCUMBER_ENVIRONMENT =开发                
当我们现在运行该功能时,我们会看到这些步骤不会执行UI。这种技术允许我们根据所运行的环境来改变步骤的行为,这在CI管线中是有用的。我们甚至可以使用我们的CI工具来控制场景的行为。

使用标签更改步骤定义            
本节以前一节的技巧为基础,使用Gherkin标签修改步骤定义的行为。使用标签而不是环境变量的优点是,测试所执行的层数被记录在要素文件中供整个团队查看。    
使用标记的钩子                        
在前面的章节中,我们放置了一个接缝,允许AtmInterfaceFactory决定我们的步骤定义是否将通过Web UI或其Java API 与Teller交互。我们将在本节重复使用这个接缝,但是我们将使用Gherkin标签来修改工厂的行为,而不是我们之前使用的环境变量。              
我们要使用的黄瓜的特点是标签挂钩,这是我们在看到标记挂钩。我们将使用标签@bypass_teller_ui来标记我们想要直接针对Java API运行的场景,并编写一个标记的钩子来记录我们做出的这个决定:
我们将修改我们的工厂以考虑这个标签:
而且,由于工厂标志是静态的,我们需要记住在我们运行每个场景之前重置标志:
现在,我们只需使用我们的@bypass_teller_ui标签对选定的功能进行注释,它们将直接针对Java API运行,而不是通过Web UI运行。我们现在可以选择每个场景的多少应用程序堆栈,只需将标签添加到我们的功能文件中,而无需修改场景的文本或步骤定义的Java实现。这项技术是一个强大的工具,它使我们能够控制我们的功能的运行时间,同时保持其全面的性质,并帮助我们建立信任,我们的软件能够满足客户的期望。               
请记住,小黄瓜标签只是自由形式的文本。你可以使用任何你喜欢的文字,所以你应该选择能够传达你的意思的单词。在这个例子中,我们使用了字符串bypass_teller_ui,但是这些单词没有什么魔力。你可以选择使用NO-UI,DirectToTeller或者完全不同的东西。随你便。
建立信任                
正如我们在看到三个朋友,测试人员,程序员,产品所有者合作,以发现,说明应用程序应该如何工作的例子。这些例子成为场景,开发团队使用它们来推动实施。同时,由于它们是使用业务领域语言编写的,因此它们也被测试人员和业务利益相关者用作自动验收测试。我们希望定期运行它们,以确保应用程序仍能提供我们客户所需的功能。这有助于在客户,开发人员和测试人员之间建立我们理解彼此需求的信任。              
我们也希望我们的场景运行得相对较快,以便我们可以经常运行它们并快速得到反馈。我们可以使用前一节中介绍的技术来关注和实施由场景指定的行为实现的应用程序部分。自从场景开始运行整个应用程序之后,我们赢得了客户的信任。以这种方式使用标签使其成为更好的测试,而不会影响规格。              
许多场景将与其他场景一样使用相同的UI元素,因为这是我们通过应用程序的业务逻辑改变路径的唯一途径。因此,我们可以引入标签来减少应用程序的数量,而不会减少我们场景的覆盖范围。我们只需要留下足够的场景,以便每个UI元素都可以运行,但这只是我们所有场景的一小部分。              
当我们首先编写我们的场景时,通过运用整个应用程序,我们建立了应用程序是正确的信任。一旦建立了这种信任关系,我们就可以使用标签和单元测试技术来最小化运行所有场景的成本。如果没有信任,这是不可能的,所以重要的是要记住失去组织其他部门的信任是多么容易,并继续专注于提供可靠地为客户提供价值的软件。                                            
在本章中,我们已经看到了可以帮助您控制场景运行时的技巧。我们使用的例子侧重于绕过UI来减少所需的Web自动化的数量。这些技术不限于我们的用户界面,可以在我们的应用程序的任何地方使用。与其通过网络调用服务,我们可以使用这些技术切换到使用本地测试加倍,可以返回罐头数据来加速场景。或者我们可以在使用持久存储的真实数据库和内存数据结构之间进行切换。可能性是无止境。我们的可执行规范保持全面,我们的方案提供始终如一的高覆盖率,但是它们继续快速运行并提供快速,可靠的反馈。

控制黄瓜
我们已经尽了最大的努力,使黄瓜工作没有复杂的配置框。它不要求我们提供一个配置文件或传递大量复杂的命令行选项。然而,有时我们想调整黄瓜的行为。      有时默认的输出可能太冗长了,或者我们需要一个更容易与其他人共享的格式。我们可能只想运行一个场景的子集,或者可能将我们的Goughkin特征和步骤定义的位置稍微有所不同。在本章中,我们将仔细研究Cucumber提供的选项以及它们如何帮助我们实现这些目标。      运行黄瓜最基本的方法是使用cucumber.api.cli.Main类。我们在本书第一部分的例子中开始使用这个类。我们可以通过向Main.main传递参数来控制Cucumber的一些方面。我们已经看到了其中一些,但让我们看看有什么可用的。
黄瓜的运行时间选项            
我们先来看看运行时选项。Cucumber提供了一个--help选项,你可以从命令行调用(你需要在你的类路径中有cucumber-core.jar和gherkin.jar):
 $ java的cucumber.api.cli.Main --help
这是相当多的选择,当每一个都有用的时候可能并不明显。让我们看看你使用其中的一些情况。          
黄瓜如何找到我们的步骤定义                                        
黄瓜称为我们的步骤定义胶水代码,因为他们粘贴功能的应用程序。挂钩(@Before和@After挂钩和我们所有的标记挂钩)也被认为是胶水代码。              
我们使用--glue选项来告诉Cucumber我们的胶水代码在哪个包中,如果在它们(或钩子)中有步骤定义,它们将被加载。重要的是要明白,Cucumber把你指定的包作为一个根来扫描胶水代码。一旦你明白了这一点,你将会从一个共同的困惑和挫折中解脱出来。我们用一个例子来说明。假设我们已经组织了我们的功能和步骤定义如下:
我们可以通过以下方式运行我们的功能中的所有场景:
然后,有一天,我们添加一个新的场景到我们的stuff.feature,并发现我们需要创建一个钩子:
现在当我们运行相同的命令时,Cucumber告诉我们,我们所有的钩子定义都是未定义的。我们可以将新包step_definitions.hooks添加到我们的命令行中:
这将工作得很好,但命令行变长了,有一个更紧凑的方式获得相同的结果:
现在,Cucumber将搜索类路径,以查找根包下的所有胶水代码step_definitions。如果我们需要在step_definitions下添加更多的包,我们在运行Cucumber时不需要改变glue选项。                              
运行情景的一个子集                
随着功能和场景数量的增长,我们会经常遇到只想运行一个(或者几个)场景的情况,以获得更快的反馈。如果我们正在开发一个新的场景,或者如果我们打破了现有的场景,这可能就是这种情况。让我们仔细看看这是如何工作的。      使用标记表达式进行过滤                                                  
使用--tags选项最简单的方法是给它一个标签来运行。这是一个例子:
这会导致Cucumber只运行标记为@focus的场景。为了过滤的目的,使用像这样的唯一标签临时标记场景或功能是相当常见的。                 
在某些情况下,我们可能需要对标签过滤进行更多的控制。想象一下,我们已经对发送电子邮件的应用程序进行了一些更改。如果我们想运行所有使用@focus或@email标记的场景呢?就是这样:
逗号被解释为逻辑OR语句。
拥有快速运行的场景和运行缓慢的场景并不罕见。如果我们已将标记应用于快速场景或功能(例如@fast),则可以应用逻辑“与”(AND)来表示我们想要运行标记为@fast的场景以及@focus或@email:
这里我们使用--tags两次。它们中的每一个将被逻辑“与”在一起。理想情况下,我们的大部分场景都很快,而且只有少数场景很慢。所以,不要用@fast来标记我们大部分的场景,而是使用@slow来标记那些很慢的场景。如果我们想运行不慢的场景(同时@focus或者@email),我们可以使用否定(波浪号):
让我们看看另一种运行场景行数的子集的方法。                           
 在线上过滤          
您不需要标记自己的场景或功能,只运行它们的一部分。黄瓜还提供了一个方便的方式来指定您想要运行的场景的行号。正如您可能已经注意到的那样,Cucumber在错误消息中打印出带有行号的功能文件的位置。                   
如果您想重新运行失败的场景,请选择文本并粘贴:
如果要素文件具有多个场景,则它将只运行第45行中的行号。行号可以在要素的任何位置,从注释行到最后一步(包括步骤表或文档字符串)。                  
冒号表示还允许您指定多个行号,以允许您指定几个要运行的场景:
过滤名称                    
如果标签过滤不符合您的需求,则可以根据名称过滤场景。比方说,你想运行所有的文本注销名称的情况下,他们分散在几个功能文件没有一个特定的标签来识别它们。运行它们只是一个问题:
--name选项 的参数是一个正则表达式,所以你可以使用通常的特殊字符。                                      
改变黄瓜的产量                        
黄瓜的默认行为是使用progress插件输出结果,每个步骤都会产生一个单个字符的最小报表(正如我们已经看到的那样):
每个字符代表每个步骤的状态:     
1、意味着通过。
2、U表示未定义。
3、-意味着跳过(或方案大纲步骤)。
4、F意味着失败。        
黄瓜还可以生成一个类似于小黄瓜源文本的更详细的报告 - 带有一些额外的信息,如颜色,匹配的步骤定义的位置,参数的突出显示等等 - 使用漂亮的插件:
黄瓜也有内置的插件,输出html,json和junit。如果您在CI环境中运行Cucumber,则后者非常方便,因为大多数CI服务器都知道如何解释JUnit报告。更多的在一分钟内。      
其他插件          
除了到目前为止我们已经看到的插件外,Cucumber还包含了一些创建输出的输出,这些输出不应该被看作是运行的报告。这些插件是一个发展援助。                            
在使用插件列出我们项目中的所有步骤中的定义,以及正在使用它的步骤。它向您显示未使用的步骤定义,并按其平均执行时间对步骤定义进行排序。usage插件的输出对于快速查找代码中的缓慢部分非常有用,同时也是获取步骤定义概述的好方法。                            
最后是重新运行的插件。这是一个特殊的插件,可以像这样创建输出:
这看起来很熟悉吗?当您想要使用线路过滤(我们之前描述)运行您的场景的一个子集时,这是您给黄瓜的相同种类的信息。                  
如果所有场景都通过了,重新运行的插件根本不输出任何内容。但是,如果一个或多个方案失败,则会输出其位置,以便您可以复制和粘贴输出以仅重新运行这些方案。能够做到这一点,为您解决破损的情况,节省了大量的时间。        输出到文件并使用多个输出插件                    
默认情况下,所有捆绑的插件将打印输出到STDOUT。那么,如果你想看到通常的漂亮的输出,而且还有一个html和重新运行的报告,你会怎么做?这是你必须告诉Cucumber将输出指向文件而不是STDOUT的地方。这是一个例子:
这会告诉Cucumber将HTML报告写入文件cukes.html,将重新运行的输出写入rerun.txt,并在控制台中显示漂亮的插件输出。                            
杂项选项        
还有其他一些我们认为值得一提的选项。      
片段名称格式                                                  
您的变量名的格式会导致大量的摩擦在一些开发团队,所以黄瓜可以让你选择是否产生与驼峰片段[69]或下划线[70]的方法名称(默认为下划线):
彩色或单色输出                    
默认情况下,捆绑插件将产生彩色输出,以帮助强调每一步的结果。这是通过在输出中插入控制字符来完成的,但有时这不是你想要的。只需提供--monochrome选项,输出将是纯文本。

覆盖黄瓜选项            
有几种方法可以设置用于控制Cucumber如何运行您的功能的选项。学习如何交互是非常有用的,如果你想黄瓜行为有所不同,取决于你如何调用它。让我们看看你可以给黄瓜提供选择的各种方式,以及它们如何相互作用。     
如何黄瓜覆盖                
Cucumber选项最初由您提供给跑步者的参数设置 - 直接在cucumber.api.cli.Main的命令行上,或者为JUnit或TestNG跑步者使用@CucumberOptions注释。                                                       
黄瓜然后看看是否有任何选项覆盖已提供。它看起来在以下三个地方:                       
OS环境变量CUCUMBER_OPTIONSJava系统属性cucumber.optionsJava资源包cucumber.properties和一个cucumber.options属性                        
覆盖是在名为cucumber.options或CUCUMBER_OPTIONS的变量(或属性)中提供的。黄瓜以这里显示的顺序搜索这个变量,并使用它找到的第一个值。一旦发现覆盖,它将不会继续搜索其他位置。               除插件参数外,在覆盖中找到的值将替换已设置的任何值。覆盖中未提及的参数不会影响已经为该参数提供的任何值。                              
 
该插件选项稍有不同的处理。覆盖指定的插件列表与已经指定的插件组合在一起。这可能会导致一个问题,如果Cucumber结束了多个插件试图输出到STDOUT,在这种情况下,你会得到这个错误:只有一个插件可以使用STDOUT。              该插件选项也是其中黄瓜提供了一个默认的只有一个。如果没有指定插件,则Cucumber将始终使用progress插件输出到STDOUT。      
格式化覆盖        
当重写黄瓜的选项,使用完全相同的格式,你没有在命令行上黄瓜的运行选项。例如:
可以重写为Java系统属性:      
这也可以在OS环境变量中设置:    
 
或者,您也可以选择将其放在cucumber.properties资源包中:       
正如你所看到的,要覆盖选项,只需复制你在命令行上写的内容即可。

黄瓜自动化      
在本书中,我们使用Maven和JUnit从命令行运行Cucumber。尽管这很常见,但您可以使用其他单元测试或构建框架。在下面的章节中,我们将看看一些最受欢迎的选择。即使你选择完全使用另一个框架,这些例子也会让你理解你需要将Cucumber和你的环境整合在一起。           
黄瓜与单元测试框架的整合        
我们已经看到如何从命令行调用Cucumber,但我们大多数人将使用现有的框架来运行我们的自动单元测试。Cucumber集成了JUnit [71]和TestNG [72],以便我们可以使用与单元测试相同的工具来运行我们的场景。我们来看看Cucumber如何与每个框架集成。
从JUnit运行黄瓜                           
黄瓜与JUnit赛跑者cucumber.api.junit.Cucumber一起运送。为了让JUnit运行我们的场景,我们将创建一个像这样的简单的JUnit测试类(当然这个类的名字是不相关的):
这个类不应该包含任何代码。它所做的就是告诉JUnit调用Cucumber JUnit runner。它将搜索特征文件并运行它们,以它能理解的格式将输出提供给JUnit。像往常一样,我们可以通过使用我们讨论过的选项注释测试类来控制Cucumber的运行方式。例如:
请记住,@CucumberOptions注释中提供的选项可能会以本章前面所述的所有方式被覆盖。
从TestNG运行黄瓜                              
TestNG支持于2013年添加到Cucumber项目中,与JUnit集成非常相似:
TestNG runner使用与JUnit runner 相同的@CucumberOptions注解来控制Cucumber。
使用@CucumberOptions注解          
通常,您将使用JUnit或TestNG运行Cucumber,因此您需要使用@CucumberOptions注释将选项提供给runner类。虽然你可以设置的选项是完全一样的,但结构是不同的,可以做一些解释。                   我们迄今为止使用的一个简单示例很容易放入@CucumberOptions注释中:
为一个属性提供多个值            
如果要为属性指定多个值,则可以使用列表。这里我们指定一个我们想要使用的两个插件的列表:
您可以使用字符串列表功能,胶水,插件和标签。
片段            
该片段选项类型,所以你需要使用提供的常量之一SnippetType.CAMELCASE或SnippetType.UNDERSCORE:
记住:您必须添加导入cucumber.api.SnippetType; 到你们班上
标记表达式                        
要运行使用特定标签标记的所有场景,请使用以下命令:
如前所述,标记项仍然可以组合起来形成逻辑表达式。因此,为了运行我们所有使用@TagA或@TagB标记的场景,我们会写:
要运行所有使用@TagA和@TagB标记的场景,我们会写:
我们也可以使用否定(NOT)运算符(〜)。
共享报告                   
在本章的前面,我们看到了如何使用--plugin选项来改变Cucumber的输出。如果我们传递--plugin junit:JUNIT_DIR给Cucumber,我们可以配置我们的CI服务器从JUNIT_DIR中获取这些报告并分析它们。一些CI服务器可以生成一个趋势图,显示我们的构建在一段时间内的健康状况 这是获得项目是在改善还是在衰减的指标的好方法。                            
我们也可以传递-p html:HTML_FILE来获得完整的HTML报告。如果我们使用的浏览器自动化工具,因为我们可以嵌入浏览器的截图权到HTML报告,正如我们在这样做是非常方便的构建用户界面。
打赏
赞(0) 打赏
未经允许不得转载:同乐学堂 » Cucumber-java版真正的入门到精通(Day7)

特别的技术,给特别的你!

联系QQ:1071235258QQ群:710045715

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏

error: Sorry,暂时内容不可复制!