I have some problems while testing my Rails aplication.
I have the simple following file to test a controller (relying on http://guides.rubyonrails.org/testing.html):
require "./test/test_helper"
class GraphControllerTest < ActionDispatch::IntegrationTest
setup do
#instance = Instance.where(client_id: 2).first
end
test "should_create" do
assert_difference('Graph.count') do
post v2_instance_graphs_url(instance_id: #instance.client_id), {'name': "test of test", 'instance_id': #instance.client_id}.to_json, {'Authorization': 'Token token=blabla', 'Content-Type': 'application/json'}
end
assert_equal JSON.parse(#response.body)["name"], "test of test"
end
end
With a test_helper.rb which is:
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml 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...
end
I run in console:
bin/rake test test/controllers/knowledge_graph_controller_test.rb
which should trigger only the two assertions above. However, and I get the two assertions above AND 8 errors.
the errors are the following:
1) Error:
ActiveSupport::TestCase#test_app=:
ArgumentError: wrong number of arguments (given 0, expected 1)
2) Error:
ActionController::TestCase#test_app=:
ArgumentError: wrong number of arguments (given 0, expected 1)
3) Error:
Minitest::Test#test_app=:
ArgumentError: wrong number of arguments (given 0, expected 1)
4) Error:
GraphControllerTest#test_app=:
ArgumentError: wrong number of arguments (given 0, expected 1)
5) Error:
ActionDispatch::IntegrationTest#test_app=:
ArgumentError: wrong number of arguments (given 0, expected 1)
6) Error:
Minitest::Unit::TestCase#test_app=:
ArgumentError: wrong number of arguments (given 0, expected 1)
7) Error:
Rails::Generators::TestCase#test_app:
RuntimeError: You need to configure your Rails::Generators::TestCase destination root.
8) Error:
Rails::Generators::TestCase#test_app=:
RuntimeError: You need to configure your Rails::Generators::TestCase destination root.
which I cannot explain. I don't even understand what file they come from.
I am using Rails 4.2.7.1
Thank you very much for your help!
The problem was an "include ActionDispatch" in another file.
Related
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'
I am trying to run a unit test.
The test needs to have require_relative 'francis'
require 'minitest/autorun'
require_relative 'francis'
class FrancisTest < MiniTest::Test
When I try running rake test TEST=test/francis_test.rb I get an error of
(in C:/Users/chris2/Documents/RailsProjects/francis)
rake aborted!
LoadError: cannot load such file -- C:/Users/chris2/Documents/RailsProjects/francis/test/francis
C:/Users/chris2/Documents/RailsProjects/francis/test/francis_test.rb:2:in `require_relative'
C:/Users/chris2/Documents/RailsProjects/francis/test/francis_test.rb:2:in `<top (required)>'
Tasks: TOP => test:single
(See full trace by running task with --trace)
How can I run this test?
Update
I moved francis_test.rb to the root of the project. I also remarked out the require_relative statement., I also had to change the setup line to #teen = ::Franci.new instead of Francis.new
So the beginning of francis_test looks like
require 'minitest/autorun'
# require_relative 'franci'
require 'test_helper'
class FrancisTest < MiniTest::Test
attr_reader :teen
def setup
#teen = ::Franci.new
end
def test_stating
assert_equal 'Whatevs.', teen.yo('Oh blah di, oh blah da.')
end
def test_yelling
assert_equal 'Chill!', teen.yo('GOOOAAAALLL!')
end
I seem to need require 'test_helper'.
BTW - my ruby and rails versions are
Rails 4.2.5.1
ruby 2.2.4p230 (2015-12-16 revision 53155) [i386-mingw32]
Now if I run rake test TEST=francis_test.rb -v
I see (partial)
# Running:
FrancisTest#test_stating_with_acronyms = 0.01 s = E
FrancisTest#test_inquiring = 0.00 s = E
FrancisTest#test_question_with_just_numbers = 0.00 s = E
. . .
Finished in 0.013518s, 1257.5400 runs/s, 0.0000 assertions/s.
1) Error:
FrancisTest#test_stating_with_acronyms:
ArgumentError: wrong number of arguments (1 for 0)
2) Error:
FrancisTest#test_inquiring:
ArgumentError: wrong number of arguments (1 for 0)
A couple of questions
is attr_reader valid in Ruby 2.2.4? I looked at the API but couldn't quite make sense of it.
Why am I getting 'wrong number of arguments'? I haven't used the attr_reader but it seems that when calling it the way I am, it should be passing the argument to teen.yo.
BTW - the francis table only has one column - 'yo'.
require_relative complements the builtin method require by allowing you to load a file that is relative to the file containing the require_relative statement.
For example, if you have unit test classes in the "test" directory, and data for them under the test "test/data" directory, then you might use a line like this in a test case:
require_relative "data/customer_data_1"
is attr_reader valid in Ruby 2.2.4? I looked at the API but couldn't
quite make sense of it.
Yes, it is. However you don't need it because columns are automatically made available as attributes by ActiveRecord.
Why am I getting 'wrong number of arguments'? I haven't used the
attr_reader but it seems that when calling it the way I am, it should
be passing the argument to teen.yo.
To answer this question, I need the content of your francis.rb file.
I'm trying to test an RSS feed by comparing a dynamically generated feed against a known output. To make this work, I need to load fixtures with the time frozen. The following works, but it seems overkill to reset the database by reloading the schema and the fixtures.
# test/integration/feed_test.rb
require 'test_helper'
load 'Rakefile'
class FeedTest < ActionDispatch::IntegrationTest
def setup
# Normalize time in order to match fixture file
travel_to Time.zone.parse('2015-03-01T12:00:00') do
silence_stream(STDOUT) do
# anything written to STDOUT here will be silenced
Rake::Task['db:schema:load'].reenable
Rake::Task['db:schema:load'].invoke
end
Rake::Task['db:fixtures:load'].reenable
Rake::Task['db:fixtures:load'].invoke
end
end
test 'feed matches fixture file' do
get feed_path
assert_equal contents('feed.atom'), response.body
end
end
# test/test_helper.rb
module ActiveSupport
class TestCase
fixtures :all
def contents(file_name)
IO.read "test/fixtures/files/#{file_name}"
end
end
end
I can't figure out how to reload just the projects filter inside a travel_to block. I also can't get travel_to to work in test_helper.rb.
But, the real problem with this approach is that reloading the Rakefile causes the following spurious warnings from the secure_headers gem:
$ rake test
/Users/dan/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/secure_headers-3.3.1/lib/tasks/tasks.rake:1: warning: already initialized constant INLINE_SCRIPT_REGEX
/Users/dan/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/secure_headers-3.3.1/lib/tasks/tasks.rake:1: warning: previous definition of INLINE_SCRIPT_REGEX was here
/Users/dan/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/secure_headers-3.3.1/lib/tasks/tasks.rake:2: warning: already initialized constant INLINE_STYLE_REGEX
/Users/dan/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/secure_headers-3.3.1/lib/tasks/tasks.rake:2: warning: previous definition of INLINE_STYLE_REGEX was here
/Users/dan/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/secure_headers-3.3.1/lib/tasks/tasks.rake:3: warning: already initialized constant INLINE_HASH_SCRIPT_HELPER_REGEX
/Users/dan/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/secure_headers-3.3.1/lib/tasks/tasks.rake:3: warning: previous definition of INLINE_HASH_SCRIPT_HELPER_REGEX was here
/Users/dan/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/secure_headers-3.3.1/lib/tasks/tasks.rake:4: warning: already initialized constant INLINE_HASH_STYLE_HELPER_REGEX
/Users/dan/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/secure_headers-3.3.1/lib/tasks/tasks.rake:4: warning: previous definition of INLINE_HASH_STYLE_HELPER_REGEX was here
Run options: --seed 17868
# Running:
........................................................................................................
Finished in 17.397614s, 5.9778 runs/s, 191.3481 assertions/s.
104 runs, 3329 assertions, 0 failures, 0 errors, 0 skips
Coverage report generated for MiniTest to /Users/dan/Dropbox/Documents/dev/cii-best-practices-badge/coverage. 754 / 781 LOC (96.54%) covered.
It seems like I should be able to reload some of the fixtures without using rake at all, but I can't figure out how to do so.
Here's the fix that resolved my issue:
# frozen_string_literal: true
require 'test_helper'
load 'Rakefile'
class FeedTest < ActionDispatch::IntegrationTest
# Turn off transactional fixtures for this test since we are loading
# the fixtures database anyway. This will prevent the timestamp change
# from spilling into other tests.
self.use_transactional_tests = false
setup do
# Ensure the test db has its environment metadata set to test,
# otherwise tasks farther down will fail. New for Rails 5
Rake::Task['db:environment:set'].invoke
# Normalize time in order to match fixture file
travel_to Time.zone.parse('2015-03-01T12:00:00') do
ActiveRecord::Schema.verbose = false
Rake::Task['db:schema:load'].reenable
Rake::Task['db:schema:load'].invoke
Rake::Task['db:fixtures:load'].reenable
Rake::Task['db:fixtures:load'].invoke
end
end
test 'feed matches fixture file' do
get feed_path
assert_equal contents('feed.atom'), response.body
end
end
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.
This is my code:
before(:each) do
request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials(api_key.access_token)
end
My test was supposed to pass but it is displaying this error:
Failure/Error: request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Token.encode_credentials("#{api_key.access_token}")
ArgumentError:
wrong number of arguments (0 for 1..2)
Gems:
rspec-rails version = 2.14.1.
rails verison = 4
mongoid from 'git://github.com/mongoid/mongoid.git'
The request method you are accessing in your test is documented at http://rubydoc.info/gems/rack-test/0.6.2/Rack/Test/Session:request and expects 1 or 2 arguments as the error indicates. You're getting an error on request.env because you're invoking request with no arguments.