简体   繁体   中英

Ruby on Rails test fails or succeeds depending on how the test suite is called

I'm working my way through the Hartl Ruby on Rails Tutorial (4th Edition) and I've come across a problem with some tests I'm trying to run - specifically the exercise in section 11.2.3. All of my tests are green up to this point.

I test the new piece of code:

vagrant@ubuntu-18:/vagrant/sample_app/test$ rails test:mailers
Started with run options --seed 59483

  1/1: [======================================================================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.33304s
1 tests, 9 assertions, 0 failures, 0 errors, 0 skips

Everything is groovy.

I attempt to run the full test suite:

vagrant@ubuntu-18:/vagrant/sample_app/test$ rails test
Running via Spring preloader in process 11914
Started with run options --seed 56533

ERROR["test_account_activation", UserMailerTest, 1.2505091589991935]
 test_account_activation#UserMailerTest (1.25s)
ActionView::Template::Error:         ActionView::Template::Error: undefined method `merge' for nil:NilClass
            app/views/user_mailer/account_activation.html.erb:6:in `_app_views_user_mailer_account_activation_html_erb__2910351700178259135_47130470135880'
            app/mailers/user_mailer.rb:10:in `account_activation'
            test/mailers/user_mailer_test.rb:9:in `block in <class:UserMailerTest>'

  48/48: [========================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.71036s
48 tests, 206 assertions, 0 failures, 1 errors, 0 skips

Bugger. Testing which I won't bother reproducing here confirms that it's definitely the same piece of code that's failing in one place and working in the other.

However, if instead of calling rails test I call rails test:run , then this happens:

vagrant@ubuntu-18:/vagrant/sample_app/test$ rails test:run
Started with run options --seed 50303

  48/48: [========================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.72194s
48 tests, 215 assertions, 0 failures, 0 errors, 0 skips

And similarly, if I use rake test or rake test:run , then everything is fine.

vagrant@ubuntu-18:/vagrant/sample_app/test$ rake test
(in /vagrant/sample_app)
Started with run options --seed 9429

  48/48: [========================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.70475s
48 tests, 215 assertions, 0 failures, 0 errors, 0 skips
vagrant@ubuntu-18:/vagrant/sample_app/test$ rake test:run
(in /vagrant/sample_app)
Started with run options --seed 50280

  48/48: [========================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.73529s
48 tests, 215 assertions, 0 failures, 0 errors, 0 skips

Can anyone explain what's going on here? And ideally how to make just a rails test call work again?

EDIT

Started rails test with the same seed used by rails test:run to show that it's not anything to do with test ordering.

vagrant@ubuntu-18:/vagrant/sample_app/test$ rails test:run 
Started with run options --seed 326

  48/48: [=======================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.66690s
48 tests, 215 assertions, 0 failures, 0 errors, 0 skips
vagrant@ubuntu-18:/vagrant/sample_app/test$ rails test --seed 326
Running via Spring preloader in process 28117
Started with run options --seed 326

ERROR["test_account_activation", UserMailerTest, 1.605607868055813]
 test_account_activation#UserMailerTest (1.61s)
ActionView::Template::Error:         ActionView::Template::Error: undefined method `merge' for nil:NilClass
            app/views/user_mailer/account_activation.html.erb:6:in `_app_views_user_mailer_account_activation_html_erb__2910351700178259135_47130458820540'
            app/mailers/user_mailer.rb:10:in `account_activation'
            test/mailers/user_mailer_test.rb:9:in `block in <class:UserMailerTest>'

  48/48: [=======================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.64637s
48 tests, 206 assertions, 0 failures, 1 errors, 0 skips

rake TESTOPTS="--seed=326" also succeeds.

EDIT 2

Test:

require 'test_helper'

class UserMailerTest < ActionMailer::TestCase

  test "account_activation" do
    user = users(:michael)
    user.activation_token = User.new_token
    mail = UserMailer.account_activation(user)
    assert_equal "Account Activation", mail.subject
    assert_equal [user.email], mail.to
    assert_equal ['noreply@example.com'], mail.from
    assert_match user.name, mail.body.encoded
    assert_match user.activation_token, mail.body.encoded
    assert_match CGI.escape(user.email), mail.body.encoded
  end


end

Method Tested: (where the line beginning mail to: is user_mailer.rb:10)

class UserMailer < ApplicationMailer

  def account_activation(user)
    @user = user
    mail to: @user.email, subject: "Account Activation"
  end

end

Fixture:

michael:
    name: Michael Example
    email: michael@example.com
    password_digest: <%= User.digest('password') %>
    admin: true
    activated: true
    activated_at: <%= Time.zone.now %>

Template:

<h1>Sample App</h1>

<p>Hi <%= @user.name %>, </p>
<p>Welcome to the Sample App! Please click on the link belowe to activate your account.</p>

<%= link_to "Activate", edit_account_activation_url(@user.activation_token, email: @user.email) %>

Thanks to @AJFaraday for pointing out in the comments that the Spring preloader was running.

I called spring stop , and the problem resolved itself.

Spring seems to have turned itself back on again, but rails test is now giving the same test results as the other three methods.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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