Ruby的case等式运算符(`===`)是RSpec的'expect`

时间:2017-02-16 22:50:57

标签: ruby rspec

我正在运行一堆数据驱动的规范,并且预期的数据在不同的类中(因为我有时必须使用Regexps,因为输出字符串每次都会更改,但始终遵循特定的格式)。

一个完美地检查它们的表达式是Ruby的大小写相等运算符===。问题是,与大多数Ruby表达式相比,它可以向后运行,有时操作是不对称的:

/rgx a/ === b # equivalent to b =~ /rgx a/
ClassA  === b # equivalent to b.is_a? ClassA

在我的规范中,这意味着我必须将操作数放错:

[Class, /regex/, 'string'].each do |expected_data|
  it { expect(expected_data).to be === actual_data }
end

这会导致错误的错误消息:

expected: === "Actual data"
     got:     "Expected data"

有没有办法扭转 ===运算符 expect语法?

2 个答案:

答案 0 :(得分:1)

如果归结为它,你可以为此定义自己的匹配器:

describe 'reverse case eq' do
  it { expect('regex').to reverse_case_eq /regex/ }
  it { expect('bad match').to reverse_case_eq /regex/ } # fails
end

RSpec::Matchers.define :reverse_case_eq do |expected|
  match do |actual|
    expected === actual
  end
end

在这种情况下的错误消息如下所示:

 Failure/Error: it { expect('bad match').to reverse_case_eq /regex/ }
   expected "bad match" to reverse case eq /regex/

您也可以添加

  failure_message do |actual|
    "expected #{expected.inspect} to === #{actual.inspect}"
  end

到define块,然后失败消息将成为

Failure/Error: it { expect('bad match').to reverse_case_eq /regex/ }
   expected /regex/ to === "bad match"

如果您经常遇到此用例,可能会首选。

答案 1 :(得分:0)

事实证明,RSpec具有非常灵活的satisfy matcher。我可以按如下方式更改expect语法,它完全符合我的需要:

expect(actual_data).to satisfy { |v| expected_data === v }

(已编辑 - 感谢@Glyoko默认失败消息稍微过于迟钝(expected [actual data] to satisfy block),但您也可以将说明传递给#satisfy

expect(actual_data).to satisfy("match #{expected_data}") { |v| expected_data === v }

规范的默认说明(即如果您没有将说明传递给#it)则为[context/description] should match [expected data],失败邮件为expected [actual data] to match [expected data]