Gauge中文文档(7)—语言特点

来源:互联网 发布:极黑的布伦希尔特 知乎 编辑:程序博客网 时间:2024/04/25 11:53

备注:语言执行器的一些行为是可以配置的,参阅配置语言执行器获取更多信息。


步骤实现

步骤具有执行spec时执行的具体语言实现。

简单步骤

步骤

* Say “hello” to “gauge”

实现

C#

// The Method can be written in **any C# class** as long as it is part of the project.public class StepImplementation {   [Step("Say <greeting> to <product name>")]   public void HelloWorld(string greeting, string name) {       // Step implementation   }}

Java

// This Method can be written in any java class as long as it is in classpath.public class StepImplementation {   @Step("Say <greeting> to <product name>")   public void helloWorld(String greeting, String name) {       // Step implementation   }}

Ruby

step 'Say <greeting> to <product name>' do |greeting, name| # Code for the stepend

使用表格的步骤

步骤

* Create following “hobbit” characters
|id |name |
|—|——-|
|123|frodo |
|456|bilbo |
|789|samwise|

实现

C#

// Here Table is a custom data structure defined by gauge.// This is available by adding a reference to the Gauge.CSharp.Lib.// Refer : http://nuget.org/packages/Gauge.CSharp.Lib/public class Users {   [Step("Create following <role> users <table>")]   public void HelloWorld(string role, Table table) {       // Step implementation   }}

Java

// Table is a custom data structure defined by gauge.public class Users {  @Step("Create following <race> characters <table>")  public void createCharacters(String type, Table table) {      // Step implementation  }}

Ruby

# Here table is a custom data structure defined by gauge-ruby.step 'Create following <race> characters <table>' do |role, table|  puts table.rows  puts table.columnsend

执行hooks

在测试套件执行期间,可以使用测试执行钩子作为不同的级别运行任意测试代码。

实现

C#

public class ExecutionHooks{  [BeforeSuite]  public void BeforeSuite() {    // Code for before suite  }  [AfterSuite]  public void AfterSuite() {    // Code for after suite  }  [BeforeSpec]  public void BeforeSpec() {    // Code for before spec  }  [AfterSpec]  public void AfterSpec() {    // Code for after spec  }  [BeforeScenario]  public void BeforeScenario() {    // Code for before scenario  }  [AfterScenario]  public void AfterScenario() {    // Code for after scenario  }  [BeforeStep]  public void BeforeStep() {    // Code for before step  }  [AfterStep]  public void AfterStep() {    // Code for after step  }}

Java

public class ExecutionHooks {  @BeforeSuite public void BeforeSuite() {     // Code for before suite  }  @AfterSuite  public void AfterSuite() {     // Code for after suite  }  @BeforeSpec  public void BeforeSpec() {     // Code for before spec  }  @AfterSpec  public void AfterSpec() {     // Code for after spec  }  @BeforeScenario  public void BeforeScenario() {     // Code for before scenario  }  @AfterScenario  public void AfterScenario() {     // Code for after scenario  }  @BeforeStep  public void BeforeStep() {     // Code for before step  }  @AfterStep  public void AfterStep() {     // Code for after step  }}

Ruby

before_suite do  # Code for before suiteendafter_suite do  # Code for after suiteendbefore_spec do  # Code for before specendafter_spec do  # Code for after specendbefore_scenario do  # Code for before scenarioendafter_scenario do  # Code for after scenarioendbefore_step do  # Code for before stependafter_step do  # Code for after stepend

默认情况下,gauge清除每个场景后的状态,以便为下一个场景执行创建新对象。您可以配置更改gauge清除缓存的级别。

数据存储

数据(对象)可以在运行时通过Gauge公开的DataStores在不同类中定义的步骤共享。

根据清除时的生命周期,有三种不同类型的DataStores。

ScenarioStore

该数据存储在场景执行的生命周期中保留添加的值,在每个场景执行后,值被清除。

C#

using Gauge.CSharp.Lib;// Adding valuevar scenarioStore = DataStoreFactory.ScenarioDataStore;scenarioStore.Add("element-id", "455678");// Fetching Valuevar elementId = (string) scenarioStore.Get("element-id");// avoid type cast by using generic Getvar anotherElementId = scenarioStore.Get("element-id");

Java

import com.thoughtworks.gauge.datastore.*;// Adding valueDataStore scenarioStore = DataStoreFactory.getScenarioDataStore();scenarioStore.put("element-id", "455678");// Fetching ValueString elementId = (String) scenarioStore.get("element-id");

Ruby

 // Adding value scenario_store = DataStoreFactory.scenario_datastore; scenario_store.put("element-id", "455678"); // Fetching Value element_id = scenario_store.get("element-id");

SpecStore

该数据存储在spec执行的生命周期中保留添加的值,在每个spec执行后,值被清除。

C#

using Gauge.CSharp.Lib;// Adding valuevar specStore = DataStoreFactory.SpecDataStore;specStore.Add("element-id", "455678");// Fetching Valuevar elementId = (string) specStore.Get("element-id");// avoid type cast by using generic Getvar anotherElementId = specStore.Get("element-id");

Java

// Import Package import com.thoughtworks.gauge.datastore.*;// Adding value DataStore specStore = DataStoreFactory.getSpecDataStore();specStore.put("key", "455678");// Fetching value DataStore specStore = DataStoreFactory.getSpecDataStore();String elementId = (String) specStore.get("key");

Ruby

// Adding valuespec_store = DataStoreFactory.spec_datastore;spec_store.put("element-id", "455678");// Fetching Valueelement_id = spec_store.get("element-id");

SuiteStore

该数据存储在整个测试套件执行的生命周期中保留添加的值,在整个测试套件执行后,值被清除。

警告:并行执行spec时不建议使用SuiteStore,在并行执行流之间不保留这些值。

Java

 // Import Package import com.thoughtworks.gauge.datastore.*;// Adding valueDataStore suiteStore = DataStoreFactory.getSuiteDataStore();suiteStore.put("element-id", "455678");// Fetching valueDataStore suiteStore = DataStoreFactory.getSuiteDataStore();String elementId = (String) suiteStore.get("element-id");

Ruby

// Adding valuesuite_store = DataStoreFactory.suite_datastore;suite_store.put("element-id", "455678");// Fetching Valuesuite_store = DataStoreFactory.suite_datastore;element_id = suite_store.get("element-id");

采用自定义截图

  • 如果此功能被打开,默认情况下会在失败的时候截图;
  • 因为您需要截取屏幕一部分,而需要捕获自定义截图(例如使用webdriver),这可以通过实现ICustomScreenshotGrabber(C#里是IScreenGrabber)接口来完成。

备注:如果在classpath中多个自定义截图功能被实现,gauge会随机选择其一来截图。因为gauge会选择它找到的第一个实现的截图功能,这又取决于库的扫描顺序。


Java

// Using Webdriver public classCustomScreenGrabber implements ICustomScreenshotGrabber {    // Return a screenshot byte array    public byte[] takeScreenshot() {        WebDriver driver = DriverFactory.getDriver();        return ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);    }}

C#

//Using Webdriver publicclass CustomScreenGrabber : IScreenGrabber {  // Return a screenshot byte array  public byte[] TakeScreenshot() {      var driver = DriverFactory.getDriver();      return ((ITakesScreenshot) driver).GetScreenshot().AsByteArray;  }}

Ruby

# Using WebdriverGauge.configure do |config|  # Return a screenshot byte array  config.screengrabber = -> {    driver.save_screenshot('/tmp/screenshot.png')    return File.binread("/tmp/screenshot.png")  }end

报告中的自定义信息

自定义消息/数据可以通过使用下面步骤实现中的API或者Hooks被添加到执行报告中。

这些信息会展示在执行报告中步骤底下。

C#

GaugeMessages.WriteMessage("Custom message for report");var id = "4567";GaugeMessages.WriteMessage("User id is {0}", id);

Java

Gauge.writeMessage("Custom message for report");String id = "4567";Gauge.writeMessage("User id is %s", id);

Ruby

Gauge.write_message("Custom message for report")id = "4567"Gauge.write_message("User id is" + id)

枚举作为步骤参数

枚举数据类型的常量值可以用作步骤的参数,但是在步骤实现中,参数的类型应与枚举名称本身匹配。

步骤:

* Navigate towards "SOUTH"

实现:

Java

public enum Direction { NORTH, SOUTH, EAST, WEST; }@Step("Navigate towards ")public void navigate(Direction direction) {   //  code here}

失败后继续执行

Gauge默认在步骤中的第一个失败时中断执行。所以如果场景中的第一个步骤失败了,随后的所有步骤都将跳过执行。
虽然这适用于大多数用例,但是有时您需要执行场景中的所有步骤,而不管前面的步骤是否失败。

为了解决这个要求,Gauge为语言执行器提供了一种方法,可以将步骤标记为可恢复,具体取决于步骤实现是否明确要求它。每个语言执行器使用不同的语法,具体取决于语言习语,允许标记步骤实现为失败继续执行。

Java

// The ``@ContinueOnFailure`` annotation tells Gauge to continue executing other// steps even if the current step fails.public class StepImplementation {    @ContinueOnFailure    @Step("Say <greeting> to <product name>")    public void helloWorld(String greeting, String name) {        // If there is an error here, Gauge will still execute next steps    }}

C#

// The ``[ContinueOnFailure]`` attribute tells Gauge to continue executing others// steps even if the current step fails.public class StepImplementation {    [ContinueOnFailure]    [Step("Say <greeting> to <product name>")]    public void HelloWorld(string greeting, string name) {        // If there is an error here, Gauge will still execute next steps    }}

Ruby

# The ``:continue_on_failure => true`` keyword argument# tells Gauge to continue executing other steps even# if the current step fails.step 'Say <greeting> to <name>', :continue_on_failure => true do |greeting, name|  # If there is an error here, Gauge will still execute next stepsend

失败继续执行可以使用可选参数来指定错误类的列表,在错误类列表中,它将在失败时继续执行进一步的步骤。目前仅支持Java。

Java

@ContinueOnFailure({AssertionError.class, CustomError.class})@Step("hello")public void sayHello() {  // code here}@ContinueOnFailure(AssertionError.class)@Step("hello")public void sayHello() {  // code here}@ContinueOnFailure@Step("hello")public void sayHello() {  // code here}

如果没有参数传递给@ContinueOnFailure,默认情况下,任何类型的错误都将会继续执行下一个步骤。

这可以用于控制执行应该继续的错误类型,而不是继续每种类型的错误。例如,在RuntimeException上,最好不要继续。而如果它是断言错误,继续执行可能会很好。


备注:

  • 在执行后,即在执行步骤方法之后,失败继续进行。如果执行步骤失败,例如参数计数/类型不匹配,gauge将不符合ContinueOnFailure标志。
  • Hooks不适用与失败继续执行,Hooks总在第一个错误时失败。
  • 默认情况下,步骤执行仍不可恢复,Gauge在执行失败时不执行后续步骤。要使失败的步骤继续执行,需要在测试代码中明确标注。
  • 没有办法全局标记测试运行,已处理所有步骤失败继续执行。每个步骤的实现必须明确标记。
  • 如果一个实现使用步骤别名,标记该实现失败继续执行也将使所有别名失败继续执行。因此,如果一个别名应该在失败时中断,另一个步骤别名应该失败继续执行,则需要将其提取到两个不同的步骤。