RSpec自定义diffable匹配器

23t*_*tux 9 ruby rspec

我在RSpec中有一个自定义匹配器,忽略空格/换行符,只匹配内容:

RSpec::Matchers.define :be_matching_content do |expected|
  match do |actual|
    actual.gsub(/\s/,'').should == expected.gsub(/\s/,'')
  end

  diffable
end
Run Code Online (Sandbox Code Playgroud)

我可以像这样使用它:

    body = "   some data   \n more data"
    body.should be_matching_content("some data\nmore wrong data")
Run Code Online (Sandbox Code Playgroud)

但是,当测试失败时(如上所述),diff输出看起来不太好:

   -some data
   -more wrong data
   +   some data   
   + more data
Run Code Online (Sandbox Code Playgroud)

是否可以配置diffable输出?第一行some data是对的,但第二行more wrong data是错的.仅将第二行作为失败的根本原因是非常有用的.

Ale*_*ein 11

我相信你应该diffable在RSpec中禁用默认行为并替换你自己的实现:

RSpec::Matchers.define :be_matching_content do |expected|
  match do |actual|
    @stripped_actual = actual.gsub(/\s/,'')
    @stripped_expected = expected.gsub(/\s/,'')
    expect(@stripped_actual).to eq @stripped_expected
  end

  failure_message do |actual|
    message = "expected that #{@stripped_actual} would match #{@stripped_expected}"
    message += "\nDiff:" + differ.diff_as_string(@stripped_actual, @stripped_expected)
    message
  end

  def differ
    RSpec::Support::Differ.new(
        :object_preparer => lambda { |object| RSpec::Matchers::Composable.surface_descriptions_in(object) },
        :color => RSpec::Matchers.configuration.color?
    )
  end
end

RSpec.describe 'something'do
  it 'should diff correctly' do
    body = "   some data   \n more data"
    expect(body).to be_matching_content("some data\nmore wrong data")
  end
end
Run Code Online (Sandbox Code Playgroud)

产生以下内容:

Failures:

  1) something should diff correctly
     Failure/Error: expect(body).to be_matching_content("some data\nmore wrong data")
       expected that somedatamoredata would match somedatamorewrongdata
       Diff:
       @@ -1,2 +1,2 @@
       -somedatamorewrongdata
       +somedatamoredata
Run Code Online (Sandbox Code Playgroud)

如果需要,您可以使用自定义不同,甚至可以将整个匹配器重新实现到系统调用diff命令,如下所示:

? diff -uw --label expected --label actual <(echo "   some data    \n more data") <(echo "some data\nmore wrong data")
--- expected
+++ actual
@@ -1,2 +1,2 @@
    some data    
- more data
+more wrong data
Run Code Online (Sandbox Code Playgroud)

干杯!


Rob*_*rty 6

您可以覆盖生成差异时将使用的expectedactual方法。在此示例中,我们将期望值和实际值存储为实例变量,并定义返回实例变量的方法:

RSpec::Matchers.define :be_matching_content do |expected_raw|
  match do |actual_raw|
    @actual = actual_raw.gsub(/\s/,'')
    @expected = expected_raw.gsub(/\s/,'') 
    expect(expected).to eq(@actual)
  end

  diffable
  attr_reader :actual, :expected
end
Run Code Online (Sandbox Code Playgroud)

另一个示例是匹配两种不同类型对象中的特定属性。(在这种情况下,预期的对象是Client模型。)

RSpec::Matchers.define :have_attributes_of_v1_client do |expected_client|
  match do |actual_object|
    @expected = client_attributes(expected_client)
    @actual = actual_object.attributes
    expect(actual_object).to have_attributes(@expected)
  end

  diffable
  attr_reader :actual, :expected

  def failure_message
    "expected attributes of a V1 Client view row, but they do not match"
  end

  def client_attributes(client)
    {
      "id" => client.id,
      "client_type" => client.client_type.name,
      "username" => client.username,
      "active" => client.active?,
    }
  end
end
Run Code Online (Sandbox Code Playgroud)

失败示例如下所示:

Failure/Error: is_expected.to have_attributes_of_v1_client(client_active_partner)
  expected attributes of a V1 Client view row, but they do not match
  Diff:
  @@ -1,6 +1,6 @@
   "active" => true,
  -"client_type" => #<ClientType id: 2, name: "ContentPartner">,
  +"client_type" => "ContentPartner",
   "id" => 11,
Run Code Online (Sandbox Code Playgroud)