mercredi 5 août 2015

Automated test fails, but passes when I try it manually

I've already rubber duck tested this a couple of times, and I'm still coming up blank.

I refactored a view at the same time as I implemented a new feature, and for some reason, when I start the server and run the test manually, it works just fine, but when I run the automated tests, it fails. I can't figure out why, and Google (or SO) isn't bringing up anything helpful on the topic.

Here's what I'm getting when I run rake test:

ERROR["test_profile_display", UsersProfileTest, 2015-08-03 01:16:05 +0000]                                                                                                 
 test_profile_display#UsersProfileTest (1438564565.46s)                                                                                                                    
ActionView::Template::Error:         ActionView::Template::Error: undefined method `name' for nil:NilClass                                                                 
            app/views/shared/_user_info.html.erb:3:in `_app_views_shared__user_info_html_erb___3557273580152920663_70200153860160'                                         
            app/views/users/show.html.erb:3:in `_app_views_users_show_html_erb__3108584293830111389_70200153855820'                                                        
            test/integration/users_profile_test.rb:11:in `block in <class:UsersProfileTest>'                                                                               
        app/views/shared/_user_info.html.erb:3:in `_app_views_shared__user_info_html_erb___3557273580152920663_70200153860160'                                             
        app/views/users/show.html.erb:3:in `_app_views_users_show_html_erb__3108584293830111389_70200153855820'                                                            
        test/integration/users_profile_test.rb:11:in `block in <class:UsersProfileTest>'   

I've seen this one enough times now to know that it's trying to call the 'name' method on an object in a class that is nil, and it's often because Rails is trying to call something on an object that isn't defined yet. I thought it might have something to do with the new partial (shared/_user_info.html.erb) that I added to my user_path (users#show) view as part of my refactoring, which I had a little trouble getting to work at first. But a) the partial loads before the page does when I look at what the server spits out in the terminal, and b) I didn't even (seemingly) make updates to that piece of functionality, which is the header partial shared by the application. Also, the partial renders just fine on the other page that it's used on (the home page for the application) and all tests for that page pass, so I don't think it's the partial that's causing the issue.

Here's the integration test that keeps failing:

test 'layout links' do
    get root_path #pass
    assert_template 'static_pages/home' #pass
    assert_select "a[href=?]", root_path, count: 2 #pass
    assert_select "a[href=?]", help_path #pass
    assert_select "a[href=?]", about_path #pass
    assert_select "a[href=?]", contact_path #pass
    assert_select "a[href=?]", login_path #pass
    get signup_path #pass
    assert_select "title", full_title("Signup") #pass
    log_in_as @user #pass
    get root_path #fail
    assert_select "a[href=?]", users_path, text: "Users" #fail
    assert_select "a[href=?]", user_path(@user) #fail
    assert_select "a[href=?]", edit_user_path(@user) #fail
    assert_select "a[href=?]", logout_path #fail
end

The failure happens in the second half, the tests that run after log_in_as @user. I didn't make any changes to my header, so I'm not sure as to why this test is suddenly failing. The header view file has this:

    <li><%= link_to "Home", root_path %></li>
    <li><%= link_to "Help", help_path %></li>
    <% if logged_in? %>
         <li><%= link_to "Users", users_path %></li>
            <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">Account <b class="caret"></b></a>
                <ul class="dropdown-menu">
                    <li><%= link_to "Profile", current_user %></li>
                    <li><%= link_to "Settings", edit_user_path(current_user) %></li>
                    <li class="divider"></li>
                    <li><%= link_to "Log out", logout_path, method: "delete" %></li>
                </ul>
         </li>
    <% else %>
         <li><%= link_to "Log in", login_path %></li>
    <% end %>

It looks to me like what's happening is that Rails is trying to log in @user (the test user fixture) and look for the link to the profile, which is the user_path for current_user. current_user is defined in the SessionsHelper as:

# Returns the current logged-in user (if any)
def current_user
    if (user_id = session[:user_id])
        @current_user ||= User.find_by(id: user_id)
    elsif (user_id = cookies.signed[:user_id])
        user = User.find_by(id: user_id)
        if user && user.authenticated?(:remember, cookies[:remember_token])
            log_in user
            @current_user = user
        end
    end
end

Again, when starting the server and running the test manually, it's fine, and Rails can figure out that current_user = @user, so it correctly sets the "Profile" link to go to user_path for current_user. I have gone over this line-by-line multiple times to make sure I know exactly what it's doing. My understanding of sessions is still a little fuzzy, I think, but I do know that session[:user_id] = user.id based on a method defined in SessionsHelper before current_user:

# Logs in the given user
def log_in(user)
    session[:user_id] = user.id
end

Why is the automated test failing while it passes when I do it manually? Is this a common test scenario/error to get? And, obviously, what did I do wrong here and how do I fix it?

Thanks!

Aucun commentaire:

Enregistrer un commentaire