【问题标题】:Converting a Cucumber scenario DataTable (HashMap) to method calls将 Cucumber 场景 DataTable (HashMap) 转换为方法调用
【发布时间】:2016-02-29 16:56:28
【问题描述】:

我正在使用 Cucumber(-JVM)、Junit、Java 8 为接受 XML 文件(最多数百个字段)的应用程序创建验收测试框架。我创建了一个库,可以将 POJO 序列化为 XML使用 Builder 接口的类(以避免有几十个构造函数并拥有各种声明性 API),即:

new Form.Builder
    .setThisField(withThis)
    .setThatField(withThat)
    .build();

我创建这个库是因为我想在我的测试中动态生成有效的 XML 文件。我希望我的黄瓜场景读起来像英语,所以我决定使用数据表而不是写类似的东西:

Given I have a form with x field
and with y field
and with z field
and ...

有 50 条不同的“和”行。所以它们看起来像这样:

Given that I have Form B101 with the following fields:
  | X Field        | X Value         |
  | Y Field        | Y Value         |
  | Z Field        | Z Value         |

问题:

我希望黄瓜数据表(已转换为 HashMap)中的键映射到我的构建器模式的方法名称。起初我认为使用 lambdas 和方法引用可以让我完成此任务,但我还没有找到方法。

所以我的下一个想法是反思。我决定在属性文件中存储从 Cucumber Data 表键到方法名称的映射:

//mapping.properties
X\ Field = setXField 
// the \ after X is to escape the space

但我遇到了一个问题:黄瓜数据表中的某些字段映射到我的 XML 数据绑定库中深度嵌套的字段(由于 XML 模式)。比如:

“X 字段”嵌套在 A 字段中。所以在我的测试方法中我需要做:

AField aField = new AField(new XField());

但是使用 java 中的反射,您需要在事前知道参数数据类型(或者我认为)。例如,如果我想找出与方法关联的参数类型:

Class[] paramString = new Class[1];
paramString[0] = AField.class;
// So I need to know before the fact that methodName (below) has a parameter
// of type AField in order to .... get the parameter types of methodName.


// this is legal because a method with methodName exists and it takes
// one parameter with type AField.
Class[] parameterTypes = 
  formB.getClass().getMethod(methodName, paramString).getParameterTypes();

// this is not legal. no method named methodName which doesn't 
// take parameters exists
Class[] parameterTypes = 
  formB.getClass().getMethod(methodName).getParameterTypes();

我确信我可以找到解决此问题的方法,但最终我似乎走上了一条“老套”的道路。有没有更好的方法来解决这个问题?还是我在“正确”的道路上?

【问题讨论】:

  • 您对您的实施谈了很多。你能分享更多关于你的问题吗?我感觉您正在以一种不擅长的方式使用 Cucumber。但是一个具体的例子可能会更好地了解您的目标。
  • @ThomasSundberg 问题是指我正在测试的应用程序吗?本质上,我正在测试一个将接受 XML 文件的 Web 服务。我构建了一个工具来动态生成 xml 文件。其中一些 XML 文件有 125 多个字段,以及我需要在 25 个不同字段上测试的业务规则。所以我需要在黄瓜的每个XML文件中表达我想要的数据。我认为数据表将是最明智的解决方案,而不是 a)黄瓜场景中的 100 行 b)用于表达 100 个字段的值的简写。
  • @ThomasSundberg 此外,我无法更改应用程序以将 XML 文件分解为更小的子 XML 文件。

标签: java reflection cucumber cucumber-jvm cucumber-junit


【解决方案1】:

冒着引起版主愤怒的风险(明确的答案比链接更受欢迎),我会给你指出这个link。要将 List 获取到 HashMap,请考虑 [this]

编辑

这里是引用链接中相关部分的摘录。

将两列表转换为 Map。

Feature: Cucumber can convert a Gherkin table to a map.
  This an example of a simple price list.

  Scenario: A price list can be represented as price per item
    Given the price list for a coffee shop
      | coffee | 1 |
      | donut  | 2 |
    When I order 1 coffee and 1 donut
    Then should I pay 3

还有代码:

package se.thinkcode.steps;

import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

import java.util.Map;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

public class SimplePriceList {
    private Map<String, Integer> priceList;
    private int totalSum;

    @Given("^the price list for a coffee shop$")
    public void the_price_list_for_a_coffee_shop(Map<String, Integer> priceList) throws Throwable {
        this.priceList = priceList;
    }

    @When("^I order (\\d+) (.*) and (\\d+) (.*)$")
    public void i_order_coffee_and_donut(int numberOfFirstItems, String firstItem,
           int numberOfSecondItems, String secondItem) throws Throwable {

        int firstPrice = priceList.get(firstItem);
        int secondPrice = priceList.get(secondItem);

        totalSum += firstPrice * numberOfFirstItems;
        totalSum += secondPrice * numberOfSecondItems;
    }

    @Then("^should I pay (\\d+)$")
    public void should_I_pay(int expectedCost) throws Throwable {
        assertThat(totalSum, is(expectedCost));
    }

}

【讨论】:

  • 我同意 MikeJRamsey56 的观点。 BeanUtils 是将 Map 转换为数据结构的“更好”方式。
  • 我同意你的看法 - 按照 SO 标准,这显然是一个糟糕的答案。这是“仅链接”的答案,您应该在答案中包含目标页面的要点 - 否则它可能会被关闭。
  • @AleksG 我哭了“叔叔!”。感谢您提示我改进答案。我当时太忙了,只想给 OP 一个线索。那时可能应该是评论。
  • 非常干净的答案..不像问题本身:)
猜你喜欢
  • 2019-08-30
  • 1970-01-01
  • 1970-01-01
  • 2020-06-07
  • 1970-01-01
  • 1970-01-01
  • 2020-03-17
  • 1970-01-01
  • 2021-09-29
相关资源
最近更新 更多