我在RSpec中有一个自定义匹配器,它忽略空白/换行符,只匹配内容:
RSpec::Matchers.define :be_matching_content do |expected|
match do |actual|
actual.gsub(/s/,'').should == expected.gsub(/s/,'')
end
diffable
end
我可以这样使用:
body = " some data n more data"
body.should be_matching_content("some datanmore wrong data")
但是,当测试失败时(如上面的测试),diff输出看起来不太好:
-some data
-more wrong data
+ some data
+ more data
是否可以配置可变输出?第一行some data
是对的,但第二行more wrong data
是错的。这将是非常有用的,只得到第二行作为失败的根本原因。
我认为你应该在RSpec中禁用默认的diffable
行为,并替换你自己的实现:
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 datanmore wrong data")
end
end
产生如下结果:
Failures:
1) something should diff correctly
Failure/Error: expect(body).to be_matching_content("some datanmore wrong data")
expected that somedatamoredata would match somedatamorewrongdata
Diff:
@@ -1,2 +1,2 @@
-somedatamorewrongdata
+somedatamoredata
你可以使用自定义的不同,如果你想,甚至重新实现这整个匹配器到diff
命令的系统调用,像这样:
♥ diff -uw --label expected --label actual <(echo " some data n more data") <(echo "some datanmore wrong data")
--- expected
+++ actual
@@ -1,2 +1,2 @@
some data
- more data
+more wrong data
干杯!
您可以覆盖expected
和actual
方法,这些方法将在生成diff时使用。在本例中,我们将期望值和实际值存储为实例变量,并定义返回实例变量的方法:
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
另一个例子是匹配两个不同类型对象中的特定属性。(本例中期望的对象是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
失败示例如下:
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,
有一种叫做diffy的宝石可以使用。
但是它会逐行遍历字符串并比较它们,因此您可以用换行符替换任意数量的空白并区分这些条目,而不是删除所有空白。
这是一个例子,你可以做一些事情来改善你的差异。我不是100%确定在哪里插入到你的代码。
def compare(str1, str2)
str1 = break_string(str1)
str2 = break_string(str2)
return true if str1 == str2
puts Diffy::Diff.new(str1, str2).to_s
return false
end
def break_string(str)
str.gsub(/s+/,"n")
end
可以设置diffy gem以产生适合终端的颜色输出。
使用此代码将像这样工作
str1 = 'extra some content'
str2 = 'extra more content'
puts compare(str1, str2)
这将打印
extra
-some # red in terminal
+more # green in terminal
content
No newline at end of file