为什么需要用 Cucumber DataTable 初始化 Cucumber DataTable?

Why do I need to initialize a Cucumber DataTable with a Cucumber DataTable?

我们最近开始更新一个非常古老的 Rails 应用程序(或至少不再过时)。其中一项更改是将 Cucumber 从 1.3.x 更新到 2.99.

我们关于此应用程序的许多 rspec 规范都使用了一个帮助程序来加载利用 Cucumber::Ast::DataTable 的测试数据。 (助手声明了它自己的继承自 Cucumber::Ast::DataTable 的子类。)这已被弃用,因此按照建议,我将继承替换为 Cucumber::MultilineArgument::DataTable

子类如下所示:

class ParsedTable < ::Cucumber::MultilineArgument::DataTable
  def initialize(string)
    super(string.split("\n").map do |line|
      line = line.split('|').map(&:squish)
      line.slice(1, line.length)
    end)
  end
end

然后有一堆测试助手可以像这样创建测试数据(假设 "role" 是我们要测试的模型):

def create_roles(string)
  table = ParsedTable.new(string)
  table.hashes.each do |hash|
    create :role,
      name: hash['Name'],
      short_name: hash['Short Name'],
      contracted_work_day: hash['Contracted workday in minutes']
  end
end

这些助手是这样被调用的:

create_roles <<-eos
  | Name      | Contracted workday in minutes |
  | Therapist | 390                           |
eos

但是当那种电话打进来时,我得到 ArgumentError: data must be a Core::Ast::DataTable。堆栈表示此异常来自 lib/cucumber/multiline_argument/data_table.rb:93:in 'initialize',这是 ParsedTable 定义中的 super 调用。

我一直在尝试围绕 Cucumber 来源追查此问题,但我无法弄清楚我做错了什么。

Cucumber 的 API 文档指出 Cucumber::MultilineArgument::DataTable 的构造函数采用 Core::Ast::DataTable 对象。

来源:https://www.rubydoc.info/gems/cucumber/Cucumber/MultilineArgument/DataTable#constructor_details

您将需要一个 Core::Ast::DataTable 的实例,而不是从字符串中自定义解析它。

Creates a new instance. +raw+ should be an Array of Array of String or an Array of Hash You don't typically create your own DataTable objects - Cucumber will do it internally and pass them to your Step Definitions.

来源:https://www.rubydoc.info/gems/cucumber-core/1.3.1/Cucumber/Core/Ast/DataTable#constructor_details

看起来 Cucumber 应该已经在步骤绑定中将 table 解析为 Core::Ast::DataTable 对象,因此您需要做的就是将其传递给 [= 的构造函数13=] class.

如果这不可用,则您需要提供一个字符串数组。

Greg Burghardt 的回答有其正确的理由; Cucumber::MultilineArgument::DataTable class 需要一个 Core::Ast::DataTable 作为参数,而旧的 Cucumber::Ast::DataTable 则不是这样。 (这个 class 通常是 Cucumber 1.4.x 和当前版本之间的一个移动目标。)

最后我通过回避问题解决了这个问题。仔细查看使用自定义 ParsedTable class 的方法,我发现它们并不真正依赖于 class,而是指望在每个实例上调用 hashes。我需要的是对 hashes 做出适当回应的东西。

因此,我没有使用 subclassing Cucumber::MultilineArgument::DataTable 来获取自定义构造函数,而是用接受字符串的方法替换了 subclass 定义,将其拆分为行,并将 Array 行馈送到 Cucumber::MultilineArgument::DataTable#from。这返回了一个 Cucumber::MultilineArgument::DataTable 的实例,我可以在其上调用 hashes。那行得通。