What can prevent an integration test from loading instance variables?

27 views
Skip to first unread message

krfg

unread,
Feb 10, 2017, 4:19:33 AM2/10/17
to Ruby on Rails: Talk
Once I completed Michael Hartl's tutorial, I packed my homepage in a partial and called it _social_layer.html.erb
Then I inserted this partial in my new homepage and proceeded to develop my application.
Therefore, an extract of application's new homepage looks like as follows:

<!-- Tab panes -->
<div class="tab-content">

    <div role="tabpanel" class="tab-pane active" id="social-layer">
        <%= render 'static_pages/social_layer' %>
    </div>

    <div role="tabpanel" class="tab-pane" id="atp-team">
        <% if @atp_tournaments.any? %>
        <ul>
            <% @atp_tournaments.each do |tournament| %>
                <li> <%= tournament.name %>: <%= tournament.category %> </li>
            <% end %>
        </ul>
        <% end %>
    </div>
    ...

As you can see this page is divided in sections or tabs, each one containing the respective code.
I inserted Michael Hartl's tutorial in the first tab.

There are two versions for my homepage, one dedicated to freshly registered users and one for users who have completed a certain selection.
I called these two pages _non_gamers_home.html.erb and _gamers_home.html.erb
The code above belongs to the version of the homepage dedicated to gamers (_gamers_home.html.erb)
So my home.html.erb file is made up of if/else statements and contains these two partials.

The problem is that If I run the integration test dedicated to the microposts interface (the _social_layer.html.erb partial), the test fails because all instance variables in my homepage that do not belong to the social layer partial (the first one is @atp_tournaments as you can see in the above code) result nil.

I do not understand why this test fails.
All these instance variables belong to the controller that controls the home page (static_pages_controller.rb) and should be loaded by the test.
If I change these variables with their explicit value in the above code the test passes.

krfg

unread,
Feb 10, 2017, 4:23:03 AM2/10/17
to Ruby on Rails: Talk
NOTE: I did not inserted any link on 'tournament.name' but it keeps coming out of nowhere automatically.

Colin Law

unread,
Feb 10, 2017, 4:42:58 AM2/10/17
to Ruby on Rails: Talk
On 10 February 2017 at 09:16, 'krfg' via Ruby on Rails: Talk
Is it only the test that fails (as is suggested by your post) or does
it also fail when you run the app? If the latter is the case then the
problem is not to do with the test but is to do with the code itself.

Colin

krfg

unread,
Feb 10, 2017, 5:23:23 AM2/10/17
to Ruby on Rails: Talk
Only the test, the application works as expected.
I thought the problem might be that there are too many nested partials in the homepage, but apart from that I have no idea why the test fails

krfg

unread,
Feb 10, 2017, 5:34:05 AM2/10/17
to Ruby on Rails: Talk
You can have a look at the partial _social_layer.html.erb at this link: it is the code included in the if statement.
As I said, I changed my homepage as follows:

<% if logged_in? %>
    <% if current_user.gamer? %>
        <%= render 'static_pages/gamers_home' %>
    <% else %>
        <%= render 'static_pages/non_gamers_home' %>
    <% end %>
<% else %>
    <%= render 'static_pages/non_logged_in_home' %>
<% end %>

I reported an extract of static_pages/gamers_home in my first post.
In theory all instance variables inside static_pages_controller.rb should be loaded by the test but they are not.

Colin Law

unread,
Feb 10, 2017, 5:34:32 AM2/10/17
to Ruby on Rails: Talk
On 10 February 2017 at 10:23, 'krfg' via Ruby on Rails: Talk
Please remember to quote the previous message when replying, so that
it is more easy to follow the thread.

Exactly what do you mean when you say the test is failing? Is the test
itself failing or are you getting errors shown in the console when you
run the test? In either case copy/paste the error here so we can get a
better idea of what is going wrong. If you are not already doing so
then just run the one test.

Colin

Colin Law

unread,
Feb 10, 2017, 5:39:32 AM2/10/17
to Ruby on Rails: Talk
On 10 February 2017 at 10:34, 'krfg' via Ruby on Rails: Talk
The variables are not loaded by the test, they are loaded by the code
in your controller. If they are loaded when running the app but not
when running the test then you are not invoking the controller action
in the same way, or with equivalent database data.

Colin

krfg

unread,
Feb 10, 2017, 5:50:41 AM2/10/17
to Ruby on Rails: Talk
Below is what the console is reporting when I run the test.
As you can notice, the test raises one error: method any? on nil class (the instance variable @atp_tournaments of the code in my first post).
If I change this instance variable with its explicit value, the next error is of next method on next variable and so on.

me@SATELLITE-L50-A-161:~/workspace/fantasytennis_app (tabbed-navigation)*$ rails test test/integration/microposts_interface_test.rb
Running via Spring preloader in process 7112
Started with run options --seed 4407

ERROR["test_micropost_interface", MicropostsInterfaceTest, 6.374447322000378]
 test_micropost_interface#MicropostsInterfaceTest (6.37s)
ActionView::Template::Error:         ActionView::Template::Error: undefined method `any?' for nil:NilClass
            app/views/static_pages/_gamers_home.html.erb:44:in `_app_views_static_pages__gamers_home_html_erb___4018195177444297552_78940320'
            app/views/static_pages/home.html.erb:3:in `_app_views_static_pages_home_html_erb___222411343280921082_78889880'
            app/controllers/microposts_controller.rb:12:in `create'
            test/integration/microposts_interface_test.rb:16:in `block (2 levels) in <class:MicropostsInterfaceTest>'
            test/integration/microposts_interface_test.rb:15:in `block in <class:MicropostsInterfaceTest>'

  2/2: [==========================================================================] 100% Time: 00:00:06, Time: 00:00:06

Finished in 6.63174s
2 tests, 8 assertions, 0 failures, 1 errors, 0 skips

Message has been deleted

krfg

unread,
Feb 10, 2017, 6:03:39 AM2/10/17
to Ruby on Rails: Talk
In app/controllers/static_pages_
controller.rb the following variables (among others) are defined:

  def home
      if logged_in? && !current_user.gamer?
            ...
      elsif logged_in? && current_user.gamer?
            ...
          @week_num = Time.now.strftime("%W").to_i
          @atp_tournaments = AtpCalendar.where("week @> ?", "{#{@week_num}}")
          @wta_tournaments = WtaCalendar.where("week @> ?", "{#{@week_num}}")
      end
  end

The AtpCalendar and WtaCalendar fixtures are empty.
Therefore, any? should return an empty array

Colin Law

unread,
Feb 10, 2017, 6:31:17 AM2/10/17
to Ruby on Rails: Talk
On 10 February 2017 at 11:02, 'krfg' via Ruby on Rails: Talk
<rubyonra...@googlegroups.com> wrote:
> In app/controllers/static_pages_controller.rb the following variables (among
> others) are defined:
>
> def home
> if logged_in? && !current_user.gamer?
> ...
> elsif logged_in? && current_user.gamer?
> ...
> @week_num = Time.now.strftime("%W").to_i
> @atp_tournaments = AtpCalendar.where("week @> ?",
> "{#{@week_num}}")


Did you understand my previous post when I suggested that you should
quote the previous message when replying?

Put some debug code to check that it is getting to the line above. You
can use logger.info and the result will be printed in the log. So
something like
logger.info("atp tournaments count = #{@atp_tournaments.count}"

Colin

krfg

unread,
Feb 10, 2017, 6:50:19 AM2/10/17
to Ruby on Rails: Talk


Ok, I will quote.
I would need information about logger.info
When I try to open test.log Atom warns me that if it opens large files it might become unresponsive.
Shall I take for granted that you are interested it test.log?

krfg

unread,
Feb 10, 2017, 7:03:00 AM2/10/17
to Ruby on Rails: Talk

My application test.log file is 107 MB
 

Colin Law

unread,
Feb 10, 2017, 7:05:57 AM2/10/17
to Ruby on Rails: Talk
On 10 February 2017 at 11:50, 'krfg' via Ruby on Rails: Talk
Whichever log is relevant at the time, so when running tests then yes
it is test.log. You can use tail to watch the log while you run the
test
tail -f log/test.log
or you can use tail after the event just to show the last lines
tail -n 100 log/test.log

Also you can delete or empty the log file before running the test,
then it will only contain the latest information.

In fact I think logger.info outputs to the console too so you don't
need to look at the log. Not certain about that though.

Colin

>
> --
> You received this message because you are subscribed to the Google Groups
> "Ruby on Rails: Talk" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to rubyonrails-ta...@googlegroups.com.
> To post to this group, send email to rubyonra...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/rubyonrails-talk/31ab7391-bd2d-4342-9d95-3f711ae29cd9%40googlegroups.com.
>
> For more options, visit https://groups.google.com/d/optout.

krfg

unread,
Feb 10, 2017, 7:16:31 AM2/10/17
to Ruby on Rails: Talk
On Friday, February 10, 2017 at 1:05:57 PM UTC+1, Colin Law wrote:
On 10 February 2017 at 11:50, 'krfg' via Ruby on Rails: Talk
<rubyonra...@googlegroups.com> wrote:
>
> I would need information about logger.info
> When I try to open test.log Atom warns me that if it opens large files it
> might become unresponsive.
> Shall I take for granted that you are interested it test.log?

Whichever log is relevant at the time, so when running tests then yes
it is test.log.  You can use tail to watch the log while you run the
test
tail -f log/test.log
or you can use tail after the event just to show the last lines
tail -n 100 log/test.log

Also you can delete or empty the log file before running the test,
then it will only contain the latest information.

In fact I think logger.info outputs to the console too so you don't
need to look at the log. Not certain about that though.

Colin



Ok, thanks for the suggestion.
I will try to use tail if it works with such a heavy file, otherwise I would need instructions on how to empty the file.
The most important thing I have to understand is: where should I place logger.info?
In static_pages_controller.rb before the declaration of @atp_tournaments variable?

Colin Law

unread,
Feb 10, 2017, 7:25:37 AM2/10/17
to Ruby on Rails: Talk
On 10 February 2017 at 12:16, 'krfg' via Ruby on Rails: Talk
The purpose of inserting the line is firstly to check that the above
line is being reached, but secondly to check the value of the
variable. To check the value of the variable you must put it after the
line determining @atp_tournaments.

Colin

Colin Law

unread,
Feb 10, 2017, 7:29:38 AM2/10/17
to Ruby on Rails: Talk
On 10 February 2017 at 12:16, 'krfg' via Ruby on Rails: Talk
<rubyonra...@googlegroups.com> wrote:
>
> I will try to use tail if it works with such a heavy file, otherwise I would
> need instructions on how to empty the file.

echo "" > log/test.log
but probably you can just delete it
rm log/test.log

Colin
Message has been deleted

krfg

unread,
Feb 10, 2017, 7:44:48 AM2/10/17
to Ruby on Rails: Talk

As you suggested I inserted logger.info immediately after the declaration of @atp_tournaments in static_pages_controller.rb:


  def home
      if logged_in? && !current_user.gamer?
            ...
      elsif logged_in? && current_user.gamer?
            ...
          @week_num = Time.now.strftime("%W").to_i
          @atp_tournaments = AtpCalendar.where("week @> ?", "{#{@week_num}}")
          logger.info("atp tournaments count = #{@atp_tournaments.count}")
          @wta_tournaments = WtaCalendar.where("week @> ?", "{#{@week_num}}")
      end
  end


Using tail -n 100 log/test.log I got the following outut:

atp tournaments count = 0

Colin Law

unread,
Feb 10, 2017, 8:32:49 AM2/10/17
to Ruby on Rails: Talk
On 10 February 2017 at 12:44, 'krfg' via Ruby on Rails: Talk
<rubyonra...@googlegroups.com> wrote:
> ...
> As you suggested I inserted logger.info immediately after the declaration of
> @atp_tournaments in static_pages_controller.rb:
>
> def home
> if logged_in? && !current_user.gamer?
> ...
> elsif logged_in? && current_user.gamer?
> ...
> @week_num = Time.now.strftime("%W").to_i
> @atp_tournaments = AtpCalendar.where("week @> ?",
> "{#{@week_num}}")
> logger.info("atp tournaments count = #{@atp_tournaments.count}")
> @wta_tournaments = WtaCalendar.where("week @> ?",
> "{#{@week_num}}")
> end
> end
>
>
> Using tail -n 100 log/test.log I got the following outut:
>
> atp tournaments count = 0

Good, so now we can be confident that it is getting to that line. One
thing that confuses me is that in an earlier post you showed the
error:

ERROR["test_micropost_interface", MicropostsInterfaceTest, 6.374447322000378]
test_micropost_interface#MicropostsInterfaceTest (6.37s)
ActionView::Template::Error: ActionView::Template::Error:
undefined method `any?' for nil:NilClass
app/views/static_pages/_gamers_home.html.erb:44:in
`_app_views_static_pages__gamers_home_html_erb___4018195177444297552_78940320'
app/views/static_pages/home.html.erb:3:in
`_app_views_static_pages_home_html_erb___222411343280921082_78889880'
app/controllers/microposts_controller.rb:12:in `create'
test/integration/microposts_interface_test.rb:16:in `block
(2 levels) in <class:MicropostsInterfaceTest>'
test/integration/microposts_interface_test.rb:15:in `block
in <class:MicropostsInterfaceTest>'


which suggests that you are in the create method of the microposts
controller. What I don't understand is how it then getting to the
static pages controller. Can you post the start of
microposts_controller.rb (up to at least line 12) and also the start
of static_pages/home.html.erb.

Colin

krfg

unread,
Feb 10, 2017, 8:46:23 AM2/10/17
to Ruby on Rails: Talk
The home page is controlled by static_pages_controller.rb
However the part of the home page concerning microposts creation and deletion is controlled by the microposts controller.
Below is an extract of microposts_controller.rb

class MicropostsController < ApplicationController
  before_action :logged_in_user, only: [:create, :destroy]
  before_action :correct_user,   only: :destroy

  def create
    @micropost = current_user.microposts.build(micropost_params)
    if @micropost.save
      flash[:success] = "Micropost created!"
      redirect_to root_url
    else
      @feed_items = []
      render 'static_pages/home'
    end
  end

Line 12 is exactly render 'static_pages/home'
app/view/static_pages/home.html.erb is all below:

krfg

unread,
Feb 10, 2017, 8:49:36 AM2/10/17
to Ruby on Rails: Talk

The lines of the test that are mentioned by the test itself (lines 15 and 16) are:

    assert_no_difference 'Micropost.count' do
      post microposts_path, params: { micropost: { content: "" } }
    end

Colin Law

unread,
Feb 10, 2017, 8:58:48 AM2/10/17
to Ruby on Rails: Talk
On 10 February 2017 at 13:46, 'krfg' via Ruby on Rails: Talk
<rubyonra...@googlegroups.com> wrote:
> ...
> The home page is controlled by static_pages_controller.rb
> However the part of the home page concerning microposts creation and
> deletion is controlled by the microposts controller.
> Below is an extract of microposts_controller.rb
>
> class MicropostsController < ApplicationController
> before_action :logged_in_user, only: [:create, :destroy]
> before_action :correct_user, only: :destroy
>
> def create
> @micropost = current_user.microposts.build(micropost_params)
> if @micropost.save
> flash[:success] = "Micropost created!"
> redirect_to root_url
> else
> @feed_items = []
> render 'static_pages/home'

The render line does not invoke the static_pages controller, it just
invokes the view files for static_pages/home, so it will not call the
static_pages controller to setup your variables. I don't know how your
debug got to that code, I suspect it was from a different part of the
test. Perhaps you meant redirect_to which will invoke the controller
to perform the action. You may find this useful -
http://tosbourn.com/difference-between-redirect-render-rails/

Colin

Hassan Schroeder

unread,
Feb 10, 2017, 9:19:48 AM2/10/17
to rubyonrails-talk
On Fri, Feb 10, 2017 at 3:02 AM, 'krfg' via Ruby on Rails: Talk
<rubyonra...@googlegroups.com> wrote:

> The AtpCalendar and WtaCalendar fixtures are empty.
> Therefore, any? should return an empty array

1. If your test depends on some values being populated, then you
need to provide that through fixtures or factories.

2. Read the doc for Enum - "any?" returns a boolean, not an array.

--
Hassan Schroeder ------------------------ hassan.s...@gmail.com
twitter: @hassan
Consulting Availability : Silicon Valley or remote

krfg

unread,
Feb 10, 2017, 9:29:02 AM2/10/17
to Ruby on Rails: Talk


Then the problem was just rendering the home page after invalid submission instead of redirecting to the home page.
The original code was render 'static_pages/home', you can check it here.
This original code would show a flash error message that the test would catch with:

assert_select 'div#error_explanation'

If I remove or comment this line in the test, the test would pass as long as I use a redirect in the create action of the microposts controller.
No flash errors are showed after redirection, though

Colin Law

unread,
Feb 10, 2017, 9:29:06 AM2/10/17
to Ruby on Rails: Talk
On 10 February 2017 at 14:19, Hassan Schroeder
<hassan.s...@gmail.com> wrote:
> On Fri, Feb 10, 2017 at 3:02 AM, 'krfg' via Ruby on Rails: Talk
> <rubyonra...@googlegroups.com> wrote:
>
>> The AtpCalendar and WtaCalendar fixtures are empty.
>> Therefore, any? should return an empty array
>
> 1. If your test depends on some values being populated, then you
> need to provide that through fixtures or factories.
>
> 2. Read the doc for Enum - "any?" returns a boolean, not an array.

Whilst true I don't think that is the cause of the problem, the error is
Error: undefined method `any?' for nil:NilClass
from the code
if @atp_tournaments.any?
so @atp_tournaments is nil rather than the empty array he expects.

Colin

Colin Law

unread,
Feb 10, 2017, 9:43:00 AM2/10/17
to Ruby on Rails: Talk
On 10 February 2017 at 14:29, 'krfg' via Ruby on Rails: Talk
<rubyonra...@googlegroups.com> wrote:
> ...
> Then the problem was just rendering the home page after invalid submission
> instead of redirecting to the home page.
> The original code was render 'static_pages/home', you can check it here.
> This original code would show a flash error message that the test would
> catch with:
>
> assert_select 'div#error_explanation'
>
> If I remove or comment this line in the test, the test would pass as long as
> I use a redirect in the create action of the microposts controller.
> No flash errors are showed after redirection, though

That is because the static_pages controller knows nothing about the
error. If you want to get that into the static_pages controller you
will have to do something like (untested)

redirect_to 'static_pages/home', :flash => { :error =>
@micropost.errors.full_messages.join(', ')}

Colin

krfg

unread,
Feb 10, 2017, 10:07:08 AM2/10/17
to Ruby on Rails: Talk

It works, even though it needs some styling.
I am really grateful for your help Colin. and this is not the first time you helped me.
Many thanks indeed
Reply all
Reply to author
Forward
0 new messages