Rails 6 Integration test exception is too long - ruby-on-rails

I have just set up a brand new rails 6.1 application on Ruby 3.0.
Everything is working as expected, except for the IntegrationTest.
Whenever there's a error in the test, the stack trace is gigantic and unreadable. I'm not sure if it's a wrong config or a bug. It's so long it doesn't fit VSCode terminal. I had to pop up a system terminal to be able to go to the first line of the stack trace and understand what's going on
Here's an snippet of the stack trace:
rails test test/controllers/api/v1/sessions_controller_test.rb:23
E
Error:
API::V1::SessionsControllerTest#test_it_generates_token_on_successfull_auth:
NameError: undefined local variable or method `password' for #<API::V1::SessionsControllerTest:0x000000012d5d6ca8 #_routes=nil, #NAME="test_it_generates_token_on_successfull_auth", #failures=[#<Minitest::UnexpectedError: Unexpected exception>], #assertions=0, #integration_session=#<#<Class:0x0000000107222768>:0x00000001072221a0 #_routes=nil, #app=#<OcaServer::Application:0x000000011db277d0 #_all_autoload_paths=["/Users/joao/code/one_cent_auction/oca_server/app/channels", "/Users/joao/code/one_cent_auction/oca_server/app/controllers", "/Users/joao/code/one_cent_auction/oca_server/app/controllers/concerns", "/Users/joao/code/one_cent_auction/oca_server/app/helpers", "/Users/joao/code/one_cent_auction/oca_server/app/jobs", "/Users/joao/code/one_cent_auction/oca_server/app/mailers", "/Users/joao/code/one_cent_auction/oca_server/app/models", "/Users/joao/code/one_cent_auction/oca_server/app/models/concerns", "/Users/joao/code/one_cent_auction/oca_server/app/services"], #_all_load_paths=["/Users/joao/code/one_cent_auction/oca_server/lib", "/Users/joao/code/one_cent_auction/oca_server/vendor", "/Users/joao/code/one_cent_auction/oca_server/app/channels", "/Users/joao/code/one_cent_auction/oca_server/app/controllers", "/Users/joao/code/one_cent_auction/oca_server/app/controllers/concerns", "/Users/joao/code/one_cent_auction/oca_server/app/helpers", "/Users/joao/code/one_cent_auction/oca_server/app/jobs", "/Users/joao/code/one_cent_auction/oca_server/app/mailers", "/Users/joao/code/one_cent_auction/oca_server/app/models", "/Users/joao/code/one_cent_auction/oca_server/app/models/concerns", "/Users/joao/code/one_cent_auction/oca_server/app/services"], #app=#<ActionDispatch::HostAuthorization:0x000000010f88e5b8 #app=#<Rack::Sendfile:0x000000010f88e770 #app=#<ActionDispatch::Static:0x000000012d407350 #app=#<ActionDispatch::Executor:0x000000012d407490 #app=#<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x000000011dc782d8 #name="ActiveSupport::Cache::Strategy::LocalCache", #local_cache_key=:active_support_cache_null_store_local_cache_4540, #app=#<Rack::Runtime:0x000000012d4076c0 #app=#<Rack::MethodOverride:0x000000012d407800 #app=#<ActionDispatch::RequestId:0x000000012d407a30 #app=#<ActionDispatch::RemoteIp:0x000000012d407b98 #app=#<Rails::Rack::Logger:0x000000012d407cd8 #app=#<ActionDispatch::ShowExceptions:0x000000012d407dc8 #app=#<ActionDispatch::DebugExceptions:0x000000012d407ee0 #app=#<ActionDispatch::
It goes on for thousands of lines.
Here's my test_helper
ENV['RAILS_ENV'] ||= 'test'
require_relative "../config/environment"
require "rails/test_help"
require 'webmock/minitest'
class ActiveSupport::TestCase
include FactoryBot::Syntax::Methods
# Run tests in parallel with specified workers
parallelize(workers: :number_of_processors)
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
# Add more helper methods to be used by all tests here...
end
On another project that I am working on there was never an stacktrace that was that big.
-- Edit
Just to clarify what's triggering the error:
require 'test_helper'
class API::V1::SessionsControllerTest < ActionDispatch::IntegrationTest
setup do
#password = Faker::Internet.password
#user = create(:user)
#user.update! password: password, password_confirmation: password
end
#...
end
The error is happening because I called a variable that hasnt been declared. password instead of #password
The problem is that I was expecting the stack trace to be as simple as:
API::V1::SessionsControllerTest#test_it_generates_token_on_successfull_auth:
NameError: undefined local variable or method `password' for #<API::V1::SessionsControllerTest:0x000000012d5d6ca8>
And not show the entire content of the SessionsControllerTest class.
Is that a normal Rails 6.1 behavior on Ruby 3? I don't recall it happening on Ruby 2.
Here's what I was expecting, reproducing the same error on a Ruby 2, Rails 6.1 application:
rails test test/controllers/jobs_controller_test.rb:15
E
Error:
JobsControllerTest#test_should_get_index:
NameError: undefined local variable or method `it_will_fail' for #<JobsControllerTest:0x0000000115b7c620>
test/controllers/jobs_controller_test.rb:6:in `block in <class:JobsControllerTest>'
test/test_helper.rb:24:in `run'

Related

Factory_girl and RSpec: undefined method `new' for Test:Module

I generated the following scaffold (using Ruby 2.2.0, rails 4.1.8, postgres):
rails g scaffold Test user:references text:references data:hstore
In my test_spec.rb:
require 'rails_helper'
RSpec.describe Test, :type => :model do
describe 'User generates a test' do
before do
#text = create(:text, content: "Cats eat mice")
#user = create(:user)
#test = create(:test)
end
...
When I run rspec the test fails with the following message:
Failure/Error: #test = create(:test)
NoMethodError:
undefined method `new' for Test:Module
# ./spec/models/test_spec.rb:8:in `block (3 levels) in <top (required)>'
When I test other models (user, text) everything works well, only the Test model fails. Calling Test.create(...) in rspec file also fails. Creating new test in rails console works. Any ideas how to fix this?
With the default configuration, Rails defines the module constant Test, so Ruby doesn't autoload your test.rb file when FactoryGirl does a Test.new as part of your :test factory.
You can install Rails without the Test infrastructure by using the -T switch, in which case it won't define the Test module and you should be fine.
If Rails is already configured, you can put the following in your rails_helper.rb file to remove the Test constant and you should be ok as well:
Object.send(:remove_const, :Test)

Minitest - NoMethodError: undefined method `get'

I was stuck with error when i run very simple test with minitest-rails gem.
I have rails 4.1.5 and minitest 5.4.0
rake test:controllers
1) Error:
DashboardController::index action#test_0001_anonymous:
NoMethodError: undefined method get' for #<#<Class:0x00000008e28170>:0x00000008eeb9b8>
test/controllers/dashboard_controller_test.rb:6:inblock (3 levels) in '
Test:
require "test_helper"
describe DashboardController do
context "index action" do
before do
get :index
end
it { must_respond_with :success }
it "must render index view" do
must_render_template :index
end
end
end
My test_helper:
ENV["RAILS_ENV"] = "test"
require File.expand_path("../../config/environment", __FILE__)
require "rails/test_help"
require "minitest/rails"
require "minitest/rails/capybara"
class MiniTest::Spec
class << self
alias :context :describe
end
end
class RequestTest < MiniTest::Spec
include Rails.application.routes.url_helpers
register_spec_type(/request$/, self)
end
class ActionDispatch::IntegrationTest
# Register "request" tests to be handled by IntegrationTest
register_spec_type(/Request( ?Test)?\z/i, self)
end
class ActiveSupport::TestCase
ActiveRecord::Migration.check_pending!
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
#
# Note: You'll currently still have to declare fixtures explicitly in integration tests
# -- they do not yet inherit this setting
fixtures :all
# Add more helper methods to be used by all tests here...
extend MiniTest::Spec::DSL
end
There are many things wrong with what you are doing. As I understand it you want to use Minitest's spec DSL in your Rails tests, correct? It looks like you are doing things to accomplish this that you don't need to do. I don't understand why half that code in your test_helper.rb file is there. I also suspect that you have other code doing things that are not being shown.
Here is what I did to reproduce your setup:
$ echo "Creating a new Rails app"
☣ [rails41:rails41] $ rails new undefined_get
☣ [rails41:rails41] $ cd undefined_get/
$ echo "Generate a Dashboard controller"
$ rails g controller dashboard index
$ echo "Add minitest-rails dependencies"
$ echo 'gem "minitest-rails"' >> Gemfile
$ echo 'gem "minitest-rails-capybara"' >> Gemfile
$ bundle install
$ echo "The test runs fine now:"
$ rake test
Run options: --seed 47210
# Running:
.
Finished in 0.457972s, 2.1835 runs/s, 2.1835 assertions/s.
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
$ echo "Update to your test code and test_helper code"
$ echo "Use whatever editor you want. Not shown here."
$ echo "Now rerun the tests:"
$ rake test
rake aborted!
NoMethodError: undefined method `context' for #<Class:0x007f860258ae50>
The error I get is different than yours. You aliased the method context to describe in your test_helper.rb file, but unfortunately the object you aliased is not in the inheritance chain for the rails test objects. The rails test objects extend Minitest::Spec::DSL, but they do not inherit from Minitest::Spec. So, I am strongly suspicious that the code you provided is indeed producing the results you have presented. That said, here is the code in my test_helper.rb that will run your test:
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require "minitest/rails"
require "minitest/rails/capybara"
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
# Allow context to be used like describe
class << self
alias :context :describe
end
# Add more helper methods to be used by all tests here...
end
This is the standard test_helper.rb with two changes. First, it has the requires for minitest-rails and minitest-rails-capybara. That is all you need to do in order to enable the Minitest spec DSL in your rails tests. Second, it adds the alias for context to describe on ActiveSupport::TestCase, which is the basis for all the rails tests. If you want to add tests that do not inherit from ActiveSupport::TestCase then you can also alias it on Minitest::Spec, but that will not help you use context within your controller tests.
Still here? Okay. So why did your code give you a different error than mine? Likely the test object used for your controller tests isn't ActionController::TestCase. I say that because your error was undefined method get. The get method is something that ActionController::TestCase defines, and is not on Minitest::Spec. So, you somehow messed up your Minitest configuration. A simple way to make sure that your tests are using the correct test objects is to add an additional assertion to your test. Like this:
require "test_helper"
describe DashboardController do
context "index action" do
before do
# Make sure we are using the correct test class
self.class.ancestors.must_include ActionController::TestCase
# Continue with setup
get :index
end
it { must_respond_with :success }
it "must render index view" do
must_render_template :index
end
end
end
If that first assertion fails then you know you have done something wrong in your configuration.

Rails autoloading behaves strangely in RSpec with modules and subclasses with spork

In my Rails app I've added the following files:
app/models/baz.rb
lib/presenters/foo_presenter.rb
lib/presenters/foo_presenter/bar.rb
spec/models/baz_spec.rb
spec/lib/presenters/foo_presenter/bar_spec.rb
The contents of lib/presenters/foo_presenter.rb is something like:
module Presenters
module FooPresenter
def self.render
# do stuff
end
end
end
The contents of lib/presenters/foo_presenter/bar.rb is like:
module Presenters
class FooPresenter::Bar
def baz
# do stuff
end
end
end
The contents of spec/lib/presenters/foo_presenter/bar_spec.rb is like:
require 'spec_helper'
module Presenters::FooPresenter
describe Bar do
# some tests
end
end
Then I have a spec file in spec/models/baz_spec.rb:
require 'spec_helper'
describe Baz do
it 'works' do
Presenters::FooPresenter.render
end
end
(The contents of app/models/baz.rb is not relevant to this issue)
The problem is when I run rspec spec/models/baz_spec.rb it works fine without spork, but when spork is running, I get an error like:
NameError: undefined method `render' for Presenters::FooPresenter:Module
I traced through the code a bit and noticed that when rspec loads spec/lib/presenters/foo_presenter/bar_spec.rb it causes Rails to autoload lib/presenters/foo_presenter/bar.rb and so at that point Presenters::FooPresenter::Bar is loaded, but then when baz_spec.rb runs, lib/presenters/foo_presenter.rb has never been loaded and thus the exception. But this only happens if spork is running. The quick fix was to require 'foo_presenter' in a file in config/initializers, but is there a cleaner solution that doesn't need the explicit require? My guess is the issue here is that Rails doesn't autoload lib/presenters/foo_presenter.rb because Presenters::FooPresenter has already been defined by bar_spec.rb.
A co-worker and I were faced with this problem today and we eventually found we needed Spork to reload the classes on every run. We used the each_run() method to do this:
Spork.each_run do
Dir[Rails.root.join("app/classes/**/*.rb")].each {|f| require f}
end

RSpec: undefined local variable or method `activate_authlogic'

My _spec file includes the code below, but my test fails with:
NameError in 'MembershipsController should allow you to save updates to the notes'
undefined local variable or method `activate_authlogic' for #<Spec::Rails::Example::ControllerExampleGroup::Subclass_1:0x107cee930>
I don't understand why activate_authlogic is undefined in this case. I've used this line in TestUnit many times, and the RSpec examples I've read all seem to say that this should work. NOTE: I've also tried adding require 'authlogic' to the top of the _spec file, but it produces an identical error message.
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
require 'ruby-debug'
describe MembershipsController do
before(:each) do
activate_authlogic
#admin = Factory(:admin, :email => "admin#example.com")
UserSession.create(#admin)
end
...
end
Apparently a misunderstanding on my part. Instead of require 'authlogic'
I needed require 'authlogic/test_case'

performance testing with devise authentication

How can I run performance tests with devise. Using the Devise docs I have this in my test_helper.rb
class ActionController::TestCase
include Devise::TestHelpers
end
From Functional testing with Rails and Devise. What to put in my fixtures?, I have this in my performance test:
require 'test_helper'
require 'rails/performance_test_help'
class EditorTest < ActionDispatch::PerformanceTest
def test_create
#user = users(:one)
sign_in #user
get 'documents/new/1'
end
end
I get the following error
NoMethodError: undefined method `sign_in' for #<EditorTest:0xb6bc0654 ...>
/test/performance/editor_test.rb:9:in `test_create'
How do I properly include the Devise TestHelpers in a performance test?
Thank you!
[edit]
This works as a functional test.
[edit]
After including the devise helper in ActionDispatch::PerformanceTest and running the test with ruby -d, here is the bottom of the debug output:
/usr/lib/ruby/gems/1.8/gems/devise-1.1.rc2/lib/devise/test_helpers.rb:
53: warning: instance variable #request not initialized
Exception `NoMethodError' at /usr/lib/ruby/gems/1.8/gems/
activesupport-3.0.3/lib/active_support/whiny_nil.rb:48 - undefined
method `env' for nil:NilClass
EEditorTest#test_create (0 ms warmup)
/usr/lib/ruby/gems/1.8/gems/devise-1.1.rc2/lib/devise/test_helpers.rb:
53: warning: instance variable #request not initialized
Exception `NoMethodError' at /usr/lib/ruby/gems/1.8/gems/
activesupport-3.0.3/lib/active_support/whiny_nil.rb:48 - undefined
method `env' for nil:NilClass
E process_time: 0 ms
Exception `Errno::EEXIST' at /usr/lib/ruby/1.8/fileutils.rb:243 -
File
exists - tmp/performance
Exception Errno::EEXIST' at /usr/lib/ruby/1.8/fileutils.rb:243 -
File
exists - tmp/performance
ExceptionErrno::EEXIST' at /usr/lib/ruby/1.8/fileutils.rb:243 -
File
exists - tmp/performance
The short version of the above error:
NoMethodError: undefined method `env' for nil:NilClass
(Misread question original reply to the wrong question is below.)
Try adding
class ActionDispatch::PerformanceTest
include Devise::TestHelpers
end
to the bottom of your helper file.
(Original reply)
Make sure
class ActionController::TestCase
include Devise::TestHelpers
end
is all the way at the bottom of your helper file. It should NOT be inside the ActiveSupport::TestCase class.
It seems performance tests don't set a request variable, which Devise test helpers try to access. In other words, Devise test helpers won't help you here.
As suggested to you here http://groups.google.com/group/plataformatec-devise/browse_thread/thread/b50bfd8ecb24822c try filling in the sign in form like in integration tests.
This explains how integration tests work, with an example how to sign in: http://guides.rubyonrails.org/testing.html#integration-testing

Resources