testing with specs, capybara from railstutorial ch

2019-04-05 15:18发布

问题:

im working on ruby.railstutorial.org/ruby-on-rails-tutorial-book. Im using rails 3.2.7, spork, rspec, capybara, launchy and some guards :)

i have a really weird problem in Chapter 3 with testing:

It seems like the tests arent working for what is inside the <head>-Tag. If i put the <title>-tag inside the <body>-tag instead of the head-tag it works fine. Also it works when i put <h1>-tags above the <title> inside <head>-Tags. It is weird, isnt it?

Please help me figur out.

The example is from : ruby.railstutorial.org/chapters/static-pages#code:title_test :

it "should have the right title" do
  visit '/static_pages/home'
  page.should have_selector('title',
                    :text => "Ruby on Rails Tutorial Sample App | Home")
end

The Error-Message is:

Failures:

1) Static pages Home page should have the title 'Home' Failure/Error: page.should have_selector('title', :text => ' | Home') Capybara::ExpectationNotMet: expected to find css "title" with text " | Home" but there were no matches. Also found "", which matched the selector but not all filters. # ./spec/requests/static_pages_spec.rb:15:in `block (3 levels) in '

That one is working:

it "should have the h1 'Sample App'" do
  visit '/static_pages/home'
  page.should have_selector('h1', :text => 'Sample App')
end

the rendered HTML-file:

<!DOCTYPE html>
<html>
<head>
  <title>Ruby on Rails Tutorial Sample App | Home</title>
  <!-- some css,js stuff -->
</head>
<body>

<h1>Sample App</h1>
<p>
  This is the home page for the
  <a href="http://railstutorial.org/">Ruby on Rails Tutorial</a>
  sample application
</p>

</body>
</html>

Thanks

Edit: you can find the files im working with on github: https://github.com/farukg/sample_app/

the link to the spec file: https://github.com/farukg/sample_app/blob/master/spec/requests/static_pages_spec.rb

Explanation of what i did: The code for Home page is like it should be. The code for about page has its own layout with a h1-tag above title-tag inside to show that it works for some kind of reason. And finally the help page has its title tag inside the body tags which works too.

Im am absolutly confused, why do i have such a strange behaviour?

the complete output of guard:

> Run all
Bundle already up-to-date
Running all specs
Running tests with args ["--drb", "--colour", "-f", "progress", "-r", "/home/faruk/.rvm/gems/ruby-1.9.3-p125/gems/guard-rspec-1.2.0/lib/guard/rspec/formatters/notification_rspec.rb", "-f", "Guard::RSpec::Formatter::NotificationRSpec", "--out", "/dev/null", "--failure-exit-code", "2", "spec"]...
..FFF.....Neues Fenster in aktueller Browsersitzung erstellt.
.FF..

Failures:

  1) Static pages Home page having application layout should have_selector head title 'Home'
     Failure/Error: page.should have_selector('head title',
     Capybara::ExpectationNotMet:
       expected to find css "head title" with text "Ruby on Rails Tutorial Sample App | Home" but there were no matches. Also found "", which matched the selector but not all filters.
     # ./spec/requests/static_pages_spec.rb:23:in `block (3 levels) in <top (required)>'

  2) Static pages Home page having application layout should have content 'Home'
     Failure/Error: page.should have_content("Ruby on Rails Tutorial Sample App | Home")
       expected there to be text "Ruby on Rails Tutorial Sample App | Home" in "Sample App This is the home page for the Ruby on Rails Tutorial sample application"
     # ./spec/requests/static_pages_spec.rb:30:in `block (3 levels) in <top (required)>'

  3) Static pages Home page having application layout should have css title 'Home'
     Failure/Error: page.should have_css("title", :text => "Ruby on Rails Tutorial Sample App | Home")
     Capybara::ExpectationNotMet:
       expected to find css "title" with text "Ruby on Rails Tutorial Sample App | Home" but there were no matches. Also found "", which matched the selector but not all filters.
     # ./spec/requests/static_pages_spec.rb:36:in `block (3 levels) in <top (required)>'

  4) Static pages about page with own layout should JUST have_selector head title 
     Failure/Error: page.should have_selector('head title')
     Capybara::ExpectationNotMet:
       expected to find css "head title" but there were no matches
     # ./spec/requests/static_pages_spec.rb:86:in `block (3 levels) in <top (required)>'

  5) Static pages about page with own layout should have_selector head title 'About Us'
     Failure/Error: page.should have_selector('head title',
     Capybara::ExpectationNotMet:
       expected to find css "head title" with text "Ruby on Rails Tutorial Sample App | About Us" but there were no matches
     # ./spec/requests/static_pages_spec.rb:93:in `block (3 levels) in <top (required)>'

Finished in 0.66215 seconds
15 examples, 5 failures

Failed examples:

rspec ./spec/requests/static_pages_spec.rb:20 # Static pages Home page having application layout should have_selector head title 'Home'
rspec ./spec/requests/static_pages_spec.rb:27 # Static pages Home page having application layout should have content 'Home'
rspec ./spec/requests/static_pages_spec.rb:33 # Static pages Home page having application layout should have css title 'Home'
rspec ./spec/requests/static_pages_spec.rb:83 # Static pages about page with own layout should JUST have_selector head title 
rspec ./spec/requests/static_pages_spec.rb:90 # Static pages about page with own layout should have_selector head title 'About Us'
Done.

> Neues Fenster in aktueller Browsersitzung erstellt.
Neues Fenster in aktueller Browsersitzung erstellt.

回答1:

I just checked your project on Github, and it seems that you are using the edge version of capybara:

Gemfile

gem 'capybara', :git => 'git://github.com/jnicklas/capybara.git'

Gemfile.lock

GIT
  remote: git://github.com/jnicklas/capybara.git
  revision: e561d249555195cdd0e9251246fc75aae876f833
  specs:
      capybara (2.0.0.beta2)
      mime-types (>= 1.16)
      nokogiri (>= 1.3.3)
      rack (>= 1.0.0)
      rack-test (>= 0.5.4)
      selenium-webdriver (~> 2.0)
      xpath (~> 1.0.0.beta1)

If nothing else, I would dare say this is the cause of your problem. (And sure enough, my reference project is broken all over after updating capybara to use the edge version)

So, unless you are keen to help with the beta testing of Capybara 2, you would do well to stick to the 1.1.2 version as listed here.



回答2:

It's just because <title> is in the <head> so it doesn't appear.

Using this, solved my problem:

page.should have_selector 'title', :visible => false

Tip: You can apply the same to check other <head> elements, like <meta>, for example, to be sure you're (and you'll stay) Google-friendly.



回答3:

If you're using Capybara 2, you can use the have_title method like this:

page.should have_title("Ruby on Rails Tutorial Sample App | Home")



回答4:

Can you test with this :

page.should have_selector('head title',
                          :text => "Ruby on Rails Tutorial Sample App | Home")


回答5:

For the moment the easiest way to do this is to access the Title element from the page html, this will return the title:

page.html.match(/<title>(.*)<\/title>/)[1].to_s

Not ideal as it's a using a regex on html(!!) but will work. Probably best to write a helper function

# put in spec/support/utilities.rb
def page_title(page)
  page.html.match(/<title>(.*)<\/title>/)[1].to_s
end

then your tests can be written as

page_title(page).should eq( "Ruby on Rails Tutorial Sample App | Home" }


回答6:

This is new to me too after putting it off for so long. Thanks to stackoverflow I was able to fix some tests with render_views in the top of the spec file right after the description. I get passing tests from

 describe "GET 'home'" do
   it "returns http success" do
     get 'home'
     response.should be_success
 end

But without using layout yet I get this error for :text Capybara::ExpectationNotMet: expected to find css "title" with text "Home | Ruby on Rails Tutorial Sample App" but there were no matches. But aside from that after using gem 'capybara', '1.1.2' in the gem file my tests pass. But I also use get 'home' as this in the routes as an action match. I hope this helps.