简体   繁体   English

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

[英]How to keep rspec tests DRY with lots of “have_link”

I'm new to Ruby on Rails and I'm doing http://ruby.railstutorial.org right now. 我是Ruby on Rails的新手,我现在正在做http://ruby.railstutorial.org

From what I understand the language is supposed to follow this DRY standard wery strictly but it's so WET when it comes to test driven development in this tutorial. 根据我的理解,该语言应该严格遵循这个DRY标准,但在本教程中涉及到测试驱动开发时,它是如此WET。

For example 例如

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) }

Here we have lots of rows that almost looks the same. 在这里,我们有很多行几乎看起来一样。

I'we tried this 我试过这个

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

This code works but it's looks ugly and it's more rows. 这段代码有效,但它看起来很丑陋而且行数更多。

So I want to know if it's an better way to add an array to have_link method. 所以我想知道是否有更好的方法将数组添加到have_link方法。


I now have a great idea but I don't know how to make it work. 我现在有一个好主意,但我不知道如何使它工作。

This is my helper (it does not look like it did when i created this question. It is edited after an answer from Michaël Witrant) 这是我的帮手(当我创建这个问题时看起来不像它。它是在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

and this should now be my test 这应该是我的考验

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]) }

So this works but it's not user friendly. 所以这可行,但它不是用户友好的。 When I run the test and I have an link does not exist on the page it tells me that I do not have these links. 当我运行测试并且页面上没有链接时,它告诉我我没有这些链接。 But I will be able to make the helper tell me which link I'm missing. 但我可以让帮助者告诉我我错过了哪个链接。 This is my error code 这是我的错误代码

   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)>'

You can write a custom matcher, but I think thats not the idea of tests and DRY. 你可以编写一个自定义匹配器,但我认为这不是测试和DRY的想法。

In the code, the DRY mantra encourages to keep every piece of knowledge of your software in a unique and unambiguous place. 在代码中,DRY口头禅鼓励将软件的每一条知识都保存在一个独特而明确的地方。 That is not the goal of the specs. 这不是规格的目标。 The goal of the specs is to poof the correctness of a software in a explicit and easy to read way. 规范的目标是以明确且易于阅读的方式提供软件的正确性。

Repeat 重复

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

if far more readable and easy to read than declaring and array of [text, url] and iterate over them, even inside some kind of custom matcher. 如果比[text,url]的声明和数组更加可读和易读,甚至在某种自定义匹配器中迭代它们。

In test you should prefer readability over conciseness. 在测试中,您应该更喜欢可读性而不是简洁性。

To define custom matchers you can read this feature and some inspiration . 要定义自定义匹配器,您可以阅读此功能和一些灵感

And write something like that: 并写下这样的东西:

RSpec::Matchers.define :have_links do |expected|
  match do |actual|
    expected.all? do |name, options|
      have_link(name, options).matches?(actual)
    end
  end
end

But IMO, your first try is the best way to write it: clean and easy to read. 但IMO,你的第一次尝试是写它的最佳方式:干净易读。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM