我是Ruby on Rails的新手,我现在正在做http://ruby.railstutorial.org。
根据我的理解,该语言应严格遵循此DRY标准,但在本教程中涉及到测试驱动开发时,它是如此WET。
例如
it { should have_link('Users', href: users_path) }
it { should have_link('Profile', href: user_path(user)) }
it { should have_link('Settings', href: edit_user_path(user)) }
it { should have_link('Sign out', href: signout_path) }
这里我们有很多几乎看起来相同的行。
我试过这个
it "should have following links from this array" do
[
['Users', href: users_path],
['Profile', href: user_path(user)],
['Settings', href: edit_user_path(user)],
['Sign out', href: signout_path]
].each { |a| page.should have_link(a[0], a[1]) }
end
此代码有效,但看起来很丑陋而且行数更多。
所以我想知道是否有更好的方法将数组添加到have_link方法。
我现在有个好主意,但我不知道如何让它发挥作用。
这是我的帮手(当我创建这个问题时看起来不像它。它是在MichaëlWitrant回答之后编辑的)
RSpec::Matchers.define :have_these_links do |*links|
match do |actual|
links.each do |link|
have_link(link.first, link.extract_options!).matches?(actual)
end
end
end
这应该是我的测试
it { should have_these_links(['Users', href: users_path],
['Profile', href: user_path(user)],
['Settings', href: edit_user_path(user)],
['Sign out', href: signout_path]) }
所以这可行,但它不是用户友好的。当我运行测试并且页面上没有链接时,它告诉我我没有这些链接。但我可以让帮助者告诉我我错过了哪个链接。 这是我的错误代码
expected #<Capybara::Session> to have these links ["Users", {:href=>"/users"}], ["Test Link", {:href=>"/Does_not_exist"}], and ["Profile", {:href=>"/users/991"}]
# ./spec/requests/authentication_pages_spec.rb:42:in `block (4 levels) in <top (required)>'
答案 0 :(得分:7)
您可以编写自定义匹配器,但我认为这不是测试和DRY的想法。
在代码中,DRY口头禅鼓励将您软件的每一条知识都保存在一个独特而明确的地方。 这不是规格的目标。规范的目标是以明确且易于阅读的方式提供软件的正确性。
重复
it { should have_link('Users', href: users_path) }
如果比[text,url]的声明和数组更具可读性和易读性,并且迭代它们,甚至在某种自定义匹配器中。
在测试中,你应该更喜欢可读性而不是简洁。
答案 1 :(得分:4)
要定义自定义匹配器,您可以阅读this feature和一些inspiration。
写下这样的东西:
RSpec::Matchers.define :have_links do |expected|
match do |actual|
expected.all? do |name, options|
have_link(name, options).matches?(actual)
end
end
end
但IMO,你的第一次尝试是写它的最佳方式:干净易读。