如何保持rspec测试DRY有很多“have_link”

我是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 # 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 ' 

要定义自定义匹配器,您可以阅读此function和一些灵感 。

并写下这样的东西:

 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,你的第一次尝试是写它的最佳方式:干净易读。

你可以编写一个自定义匹配器,但我认为这不是测试和DRY的想法。

在代码中,DRY口头禅鼓励将软件的每一条知识都保存在一个独特而明确的地方。 这不是规格的目标。 规范的目标是以明确且易于阅读的方式提供软件的正确性。

重复

 it { should have_link('Users', href: users_path) } 

如果比[text,url]的声明和数组更加可读和易读,甚至可以在某种自定义匹配器中进行迭代。

在测试中,您应该更喜欢可读性而不是简洁性。