What is the quickest way to determine why an integration test failed? - ruby-on-rails

I have the following:
test "should update deal" do
patch user_deal_url(#user, #deal), params: { deal: { name: #deal.name+'xxx' } }
# p #response.body
# p #deal.errors.full_messages
assert_select ".alert", false # should not have alert
assert_redirected_to dashboard_url
follow_redirect!
assert_select ".alert", "Deal was successfully updated."
end
It only says:
Failure:
DealsControllerTest#test_should_update_deal [C:/Users/Chloe/workspace/test/controllers/deals_controller_test.rb:73]:
Expected response to be a <3XX: redirect>, but was a <200: OK>
I thought I could print #deal.errors.full_messages but it's not the same #deal in the controller. I'm able to print the entire response body and copy it into Notepad++ and search for the error messages, but it's so tedious. I thought I can assert that .alert doesn't exist and it would tell me what it actually was. I added
assert_select "#error_explanation", false # should not have error
But that only told me that it exists, not why it failed.
Expected exactly 0 elements matching "#error_explanation", found 1..
Expected: 0
Actual: 1
So how do you quickly determine why a model is failing to save or update in a controller during testing?
Rails 5.0.2
Reference: http://guides.rubyonrails.org/testing.html
My solution causes subsequent assert_select statements to fail! Just having puts css_select('#error_explanation') makes the last assert_select fail, but commenting it out makes it succeed. Why?
I entered a Rails bug for that in the mean time: https://github.com/rails/rails/issues/29367

I was able to put
puts css_select('#error_explanation')
right after the put/patch and it prints
# Running:
<div id="error_explanation">
<h2>
2 errors
prohibited this deal from being saved:
</h2>
<ul>
<li>Size can't be blank</li>
<li>Size is not a number</li>
</ul>
</div>
F
Failure:
I'm still looking for something better as leaving this line in causes subsequent assert_selects to fail!

Related

Getting assert_select to show me what an element actually was

I have the following test:
test "users title when logged out" do
get users_path
assert_select "title", 'Correct title"
end
If we assume that users_path returns a page with <title>Wrong title</title>, then I get the following output:
FAIL["test_users_title_when_logged_out", SiteLayoutTest, 1.0830602300120518]
test_users_title_when_logged_out#SiteLayoutTest (1.08s)
Expected at least 1 element matching "title", found 0..
Expected 0 to be >= 1.
test/integration/site_layout_test.rb:37:in `block in <class:SiteLayoutTest>'
I would like to replace the assert_select with something like assert_equal "Correct title", page.title so that the test failure message actually shows me what the page's title is, which would make tracing the problem much easier! (Naturally, the page shows the correct title in development mode…)
However, page.title does not seem to be available, and my efforts at searching are only turning up stuff like "you can do it with Capybara", which is a bit bulky for this purpose!
Is there a way to write this test so that it shows something like Expected page title to be "Correct title" but got "Wrong title" instead? [Edit for clarity: "Wrong title" is the title in the returned page, not a literal string — that is, I need the error to tell me what was actually returned.]
It looks like the answer is assert_equal 'Correct title', css_select('title').first.content.
This gives the more helpful failure message
FAIL["test_users_title_when_logged_out", SiteLayoutTest, 1.0830602300120518]
test_users_title_when_logged_out#SiteLayoutTest (1.08s)
Expected: "Correct title"
Actual: "Wrong title"
(though I suspect it may be better style to revert to the original assert_select once I've found the problem!)

Integration test: `assert_select 'a[href=?]'` fails for paginated pages

I have many integration tests that look something like:
first_page_of_users = User.page(1) # Using kaminari for pagination.
first_page_of_users.each do |user|
assert_select 'a[href=?]', user_path(user)
end
These tests fail with an error message such as:
Expected at least 1 element matching "a[href="/users/1"]", found 0..
I added puts #response.body to the tests to see the code that it responded with.
For all the users included in the response body it has correct hrefs, such as href="/users/75938613". However, the numbers behind /users/ are much higher, and "users1" is indeed not present (not just the url not present but the entire record isn't on that page). If I ensure that there are only a few fixtures so that no pagination applies, the tests pass. This makes me feel as if with pagination the order that first_page_of_users = User.page(1) applies differs from the order in records that first_page_of_users.each do |user| assert_select 'a[href=?]', user_path(user) expects...
What could be causing this error? It applies to different pages and models of my app.
Update: For another model even when I try
Organization.all.each do |org|
puts #response.body
assert_select 'a[href=?]', organization_path(org)
end
I get the error:
Expected at least 1 element matching "a[href="/organizations/fix0"]",
The organization with the name "fix0" is not present at all in the body that it reponds with. My (shortened) fixtures are below and they confirm there should not be any organization with that name. Any idea what's going on?
one:
name: abcd
activated: true
activated_at: 2015-04-16 11:38:53
two:
name: efgh
activated: true
activated_at: 2015-04-16 11:38:53
<% 35.times do |n| %>
organization_<%= n %>:
name: <%="fix#{n}" %>
activated: true
activated_at: <%= Time.zone.now %>
<% end %>
When integration testing, it's important to keep track of what should show up where and test just that. Because we have too many records for the first page in this case, anything that would land on later pages will cause the failing test. As you suspect, something like this should verify that the first page of results is present:
Organization.order('organizations.name','desc').page(1).each do |organization|
assert_select 'a[href=?]', organization_path(organization)
end
I recommend keeping a smaller data set for testing, because in this case you should also 'get' page two in your test and do the assertions above for 'page(2)' as well. This means this integration test has to issue two get requests (plus any setup you may need) and check the results, and making a habit of that can slow down your suite.

hashes, flash and assert_not - how do I assert_not a hash

I'm trying to finish the exercises in the Mhartl RoR tutorial.
The question asks you to complete the following integration test
assert_not 'flash.FILLIN'
assert_select 'div#FILLIN'
assert_select 'div.FILLIN'
And I have a flash that shows either
{:success => "success message here"}
or upon error,
<% flash.each do |message_type, message| %>
taking the standard #user.errors.fullmessages.
My questions are:
How would I go about finding the list of #users.errors.fullmessages, and how do assert_not error?
assert_not 'flash.errors'
yields no exit:success... :(
any help appreciated, the link to the exercise is here: https://draft.railstutorial.org/book/sign_up#sec-signup_exercises
Turns out that it is
assert_not flash.nil?
and some helpful places to look: Check for array not empty: any?
:)
assert_not flash.empty?
Michael Hartl says "I prefer only to test that the flash isn’t empty" at
http://3rd-edition.railstutorial.org/book/sign_up#sec-signup_exercises
And he writes the same test at
http://3rd-edition.railstutorial.org/book/updating_and_deleting_users#code-successful_edit_test
To assert that there is no flash message of a particular type set (:error in this example), you can do:
assert_predicate flash[:error], :nil?

Checking for multiple copies of a selector in RSpec

I'm having a problem with one of my tests in RSpec. The test in question is supposed to test whether there is more than one post on the index page, by checking for the existence of more than one <article class="post"> tag on the page. My current implementation looks like this:
it "should have more than one post" do
get :index
response.should have_selector("article", :class => "post", :count => 2)
end
For some reason this test fails, despite showing multiple instances of the <article class="post"> tag in the debug output. The specific error it give is
Failures:
1) PostsController GET 'index' should have more than one posts
Failure/Error: response.should have_selector("article", :class => "post", :count => 2)
expected following output to contain a <article class='post'/> tag:
Note that if I remove the :count => 2 option the test passes without incident.
Does anyone know why this test is failing?
I'm guessing you are using Capybara under RSpec here or Webrat? With the count option your test is asserting that the response contains exactly 2 posts, rather than at least 2. Does the minimum option do what you want?
See https://github.com/jnicklas/capybara/blob/master/lib/capybara/node/matchers.rb and http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Matchers#has_selector%3F-instance_method

Rails 2.3.x - How to stub a helper method (that gets called from a view) in a functional test (no RSpec)?

Please don't tell me "search more" or other stuff cause all solutions for similar question fail.
Simple:
I have a functional tests. I want to make a simple get and see if proper content gets rendered
test "displays headline if user should see it" do
get :index
assert_match /headline/, response.body
end
test "doesn't display headline if user shouldn't see it" do
get :index
assert_no_match /headline/, response.body
end
and a simple view
<% if show_headline?(arg) %>
headline
<% end %>
and a helper:
module TheHelper
def show_headline?(arg)
arg ? hard_code_logic : even_harder_logic
end
end
so what I need is to do in test something like:
test "displays headline if user should see it" do
Something.stubs(:show_headline?).returns(true)
get :index
assert_match /headline/, response.body
end
test "doesn't display headline if user shouldn't see it" do
Something.stubs(:show_headline?).returns(false)
get :index
assert_no_match /headline/, response.body
end
The question is what is Something? I want to stub it cause I have helpers tested in unit/helpers.
After the get helper module gets remixed into the controller class. Please don't give me links to other answers, I read them (but of course I could have read the wrong ones) and they don't work for me. I use Rails 2.3.10 with mocha 0.9.8.
Things that don't work:
TheController.any_instance.stubs(:show_headline?)
ActionView::Base.any_instance...
#controller.stubs...
UPDATE:
the only mock that worked was:
<% self.stubs(:show_headline?).returns(true) >%
<% if show_headline?(arg) %>
headline
<% end %>
but of course I will not use that... maybe it is a clue

Resources