rails integration tests pass with ruby -Itest, fail with rake test:integration - ruby-on-rails

I'm following the rails_admin README. I have setup devise and cancan, only users of group admin can access rails_admin.
Here is the test
test "try to access rails_admin as a non admin user" do
get_via_redirect '/users/auth/facebook'
assert_response :success
assert_match 'Successfully authenticated', flash[:notice]
puts User.all.count
puts User.first.name
puts Group.find(User.first.group_id).name
assert_equal Ability.new(User.first).can?(:access, :dashboard), false
puts session
get '/admin'
assert_response :found
assert_redirected_to '/'
assert_match 'You are not authorized', flash[:alert]
end
When I run 'ruby -Itest test/integration/test.rb' all passes. The output is
1
Facebook User
user
{"session_id"=>"5345e64582b2557d0d02cd2011461467", "warden.user.user.key"=>["User", [2], "$2a$04$B.nVokuCXSWOpZ2Ezf60Cu"], "flash"=>#<ActionDispatch::Flash::FlashHash:0xb49d9a4 #used=#<Set: {:notice}>, #closed=false, #flashes={:notice=>"Successfully authenticated from facebook account."}, #now=nil>}
When I run 'bundle exec rake test:integration' the test fails. The output is
1
Facebook User
user
{"session_id"=>"0005d96c17c75d0843166e5dbb4dcc05", "warden.user.user.key"=>["User", [3], "$2a$04$4f5/I9uSZbMWBdCgDA086O"], "flash"=>#<ActionDispatch::Flash::FlashHash:0xa4c0db0 #used=#<Set: {:notice}>, #closed=false, #flashes={:notice=>"Successfully authenticated from facebook account."}, #now=nil>}
F.
Finished tests in 1.054687s, 3.7926 tests/s, 24.6519 assertions/s.
1) Failure:
test_try_to_access_rails_admin_as_a_non_admin_user(RailsAdminTest):
Expected response to be a <:found>, but was <200>
I also tried "assert_select 'body', 'something'". When running rake test:integration it outputs some html like a standard rails_admin dashborad page. Looks like the user is authorized to access rails_admin.
I'm using rails 3.2.6, devise 2.1.2, cancan 1.6.8, rails_admin 0.0.5
Any ideas? Thanks.

I was having the same issues (single test running but not all at once). It seems this is due to rails_admin not being initalized by default when running test.
What helped was setting
SKIP_RAILS_ADMIN_INITIALIZER=false
before calling rake. So now it's
SKIP_RAILS_ADMIN_INITIALIZER=false rake test
for me.
Unfortunately i do not know how to reinitialize rails_admin from inside the tests (there is a rake task to disable but not to enable) and prefixing rake test every time is annoying. Also the tests do run quite a bit longer if rails_admin is initalized (that's propably why it's turned of by default).
We now use a small test helper for those tests which check rails_admin access. The helper returns immediately and logs a warning if SKIP_RAILS_ADMIN_INITIALIZER is true and thus does not run the tests on normal dev systems. On our continuous integration system SKIP_RAILS_ADMIN_INITIALIZER=false is set and the tests are run.

Related

Capybara feature tests does not commit database transactions

I am using Machinist to create my test users which I want to log in before each test which I am running with Capybara:
include Capybara::DSL
include ActionController::UrlWriter
before do
SslRequirement.disable_ssl_check = true
user = User.make
visit new_user_session_path
fill_in('username', with: user.email)
fill_in('password', with: '12345')
click_button('submit')
end
it "responds as expected" do
# ...
end
Now when the user is created with User.make I can access it through User.all when it fact it's not persisted in the database yet, this is because
ActiveRecord::Base.connection.open_transactions == 1
I can fix/hack this by doing a
ActiveRecord::Base.connection.commit_db_transaction
after User.make, but I'd rather fix this properly. Is this a Capybara configuration which I am missing? Disclaimer: Using Rails 2.3 and RSpec 1.3
You don't show which driver you're using with Capybara, but generally you shouldn't be using transactions for testing when using Capybara (yes there are potential workarounds to allow it but they all have side-effects). See transactions and database setup and then look into the database_cleaner gem with truncation - here's a blog post about it that should be good with the age of gems you're using - http://devblog.avdi.org/2012/08/31/configuring-database_cleaner-with-rails-rspec-capybara-and-selenium/

Rails Rspec Suite Has Failures But They Pass When Run Individually

Facts:
Running my entire suite of specs will result in 21 consistent errors out of 610 specs.
If I run any individual spec file (for instance: messages_controller_spec.rb), they will all pass.
If I run any of the failed specs individually, they will each pass.
These errors are mostly ActionMailer failures, but some are otherwise.
One confusing aspect is that some of the specs fail because there was an extra row in the database than expected, while others fail because there was one less row than expected. That is, if it were a cleaning or cache issue, it seems like it should be consistently one more or one less.
I’m currently running Rails 4.1.1, Ruby 2.0.0p451, Rspec 2.14.8, Sidekiq via inline!
Gemfile(for test)
group :development, :test do
gem 'better_errors'
gem 'binding_of_caller'
gem 'faker'
gem 'guard-rspec'
gem 'pry'
gem 'rspec-rails'
gem 'spork-rails'
gem 'sqlite3'
gem 'thin'
end
group :test do
gem 'capybara'
gem 'capybara-email'
gem 'capybara-webkit'
gem 'database_cleaner'
gem 'fabrication'
gem 'launchy'
gem 'selenium-webdriver'
gem 'shoulda-matchers'
gem 'webmock'
gem 'vcr'
end
Please note, I’ve checked out about a dozen similar questions that did not work to fix this. So, to clarify:
I’m not using ARGV
I’m not using before(:all) - I use before(:each).
I have attempted Rails.cache.clear before both the :suite & the :each spec.
I have database cleaner set to :truncation for all cleaning (slower, but better results than :transaction - have had issues with reloading updated values using :transaction)
For convenience sake, maybe some examples will help:
scheduler_spec.rb (showing test that fails when whole suite is run)
require 'spec_helper'
require 'rake'
require 'sidekiq/testing'
Sidekiq::Testing.inline!
describe "scheduler", :vcr do
describe ":wipe_abandoned_images" do
let!(:abandoned_old_image) { Fabricate(:image) }
let!(:abandoned_young_image) { Fabricate(:image) }
let!(:adopted_image) { Fabricate(:image) }
let(:run_cleaner) do
Rake::Task[:wipe_abandoned_images].reenable
Rake.application.invoke_task :wipe_abandoned_images
end
before do
abandoned_young_image.update_columns(listing_id: nil, updated_at: 6.days.ago)
abandoned_old_image.update_columns( listing_id: nil, updated_at: 9.days.ago)
Rake.application.rake_require 'tasks/scheduler'
Rake::Task.define_task(:environment) #Stub env. Rspec runs the App, so dont want Rake to run it again.
end
context "for claimed images" do
it "leaves the image" do
adopted_image_id = adopted_image.id
run_cleaner
expect(Image.all.count ).to eq(2)
expect(Image.find(adopted_image_id) ).to be_present
end
end
end
end
Note that I'm using Sidekiq's inline! testing configuration on prior apps with good success & without this issue.
forgot_passwords_controller_spec.rb (showing test that fails when whole suite is run)
require 'spec_helper'
require 'sidekiq/testing'
Sidekiq::Testing.inline!
describe ForgotPasswordsController do
let!(:jen) { Fabricate(:user, email: 'jen#example.com') }
describe "POST create" do
context "with valid email provided" do
before { post :create, email: 'jen#example.com' }
after do
ActionMailer::Base.deliveries.clear
Sidekiq::Worker.clear_all
end
it 'sends the reset email to the users provided email' do
expect(ActionMailer::Base.deliveries.count).to eq(1)
end
end
end
end
Here's what happens when I run the specs in various ways:
ForgotPasswordsController Specs pass via RubyTest plugin in SublimeText2
2014-08-28T03:42:43Z 32968 TID-ov5g65p44 INFO: Sidekiq client with
redis options {} ........... Finished in 0.95479 seconds 11 examples,
0 failures Randomized with seed 40226 [Finished in 5.8s]
Scheduler Tests pass via RubyTest in SublimeText2
.Rationing out invitations to users... done. .Rationing out
invitations to users... done. ..Sweeping the server for abandoned
images... 2014-08-28T01:49:02Z 32426 TID-owjt9ggh8 INFO: Sidekiq
client with redis options {} done. .Sweeping the server for abandoned
images... done. .Sweeping the server for abandoned images... done.
.
Finished in 1.52 seconds 7 examples, 0 failures Randomized with seed
37996 [Finished in 8.6s]
Tests pass via rspec in Console
$ rspec ./spec/lib/tasks/scheduler_spec.rb
.Rationing out invitations to users... done. .Rationing out
invitations to users... done. ..Sweeping the server for abandoned
images... 2014-08-28T02:14:43Z 32456 TID-ouiui9g8c INFO: Sidekiq
client with redis options {} done. .Sweeping the server for abandoned
images... done. .Sweeping the server for abandoned images... done.
.
Finished in 1.32 seconds 7 examples, 0 failures Randomized with seed
19172
Tests fail when run entire suite of Rspec
These failures will pass if run individually or as the spec file they are from.
$ rspec
Finished in 49.71 seconds 610 examples, 21 failures, 10 pending
Failed examples:
Sometimes it has an extra value
13) scheduler :wipe_abandoned_images for abandoned images under 1
week old leaves the image
Failure/Error: expect(Image.all.count ).to eq(2)
expected: 2
got: 3
(compared using ==)
# ./spec/lib/tasks/scheduler_spec.rb:78:in `block (4 levels) in <top (required)>'
Sometimes it loses or doesn’t load a value
18) ForgotPasswordsController POST create with valid email provided
sends the reset email to the users provided email
Failure/Error: expect(ActionMailer::Base.deliveries.count).to eq(1)
expected: 1
got: 0
(compared using ==)
# ./spec/controllers/forgot_passwords_controller_spec.rb:22:in `block (4 levels) in <top (required)>'
Here's a list of the failures
rspec ./spec/controllers/messages_controller_spec.rb:161 # MessagesController POST create message about listing to user from guest with valid information with EXISTING, UN-confirmed guest with EXPIRED token sends another confirmation email with link to the guest
rspec ./spec/controllers/messages_controller_spec.rb:114 # MessagesController POST create message about listing to user from guest with valid information with NEW, UN-confirmed, and valid guest email sends an invitation for the guest to be put on safe-email list
rspec ./spec/controllers/invitations_controller_spec.rb:30 # InvitationsController POST create with valid email & available invitations sends an email
rspec ./spec/controllers/invitations_controller_spec.rb:33 # InvitationsController POST create with valid email & available invitations sends an email to the recipient_email address
rspec ./spec/controllers/users_controller_spec.rb:161 # UsersController POST create with invitation token in params with valid token & input confirmation email sending sends the email to the registering user
rspec ./spec/controllers/users_controller_spec.rb:158 # UsersController POST create with invitation token in params with valid token & input confirmation email sending sends the email
rspec ./spec/controllers/users_controller_spec.rb:164 # UsersController POST create with invitation token in params with valid token & input confirmation email sending sends an email with a confirmation link in the body
rspec ./spec/controllers/users_controller_spec.rb:354 # UsersController GET confirm_with_token with valid token has a welcome message in the email
rspec ./spec/controllers/users_controller_spec.rb:348 # UsersController GET confirm_with_token with valid token sends a welcome email
rspec ./spec/controllers/users_controller_spec.rb:351 # UsersController GET confirm_with_token with valid token sends the welcome email to the user
rspec ./spec/controllers/searches_controller_spec.rb:19 # SearchesController GET search GET search with specific category selected returns the matching OR partial-matching table row objects
rspec ./spec/controllers/searches_controller_spec.rb:22 # SearchesController GET search GET search with specific category selected only returns values from the selected category
rspec ./spec/lib/tasks/scheduler_spec.rb:75 # scheduler :wipe_abandoned_images for abandoned images under 1 week old leaves the image
rspec ./spec/lib/tasks/scheduler_spec.rb:68 # scheduler :wipe_abandoned_images for abandoned images over 1 week old deletes the images
rspec ./spec/lib/tasks/scheduler_spec.rb:84 # scheduler :wipe_abandoned_images for claimed images leaves the image
rspec ./spec/controllers/forgot_passwords_controller_spec.rb:24 # ForgotPasswordsController POST create with valid email provided sets the email subject to notify the user of the reset link
rspec ./spec/controllers/forgot_passwords_controller_spec.rb:27 # ForgotPasswordsController POST create with valid email provided sends the link with token in the body of the email
rspec ./spec/controllers/forgot_passwords_controller_spec.rb:21 # ForgotPasswordsController POST create with valid email provided sends the reset email to the users provided email
rspec ./spec/controllers/reset_passwords_controller_spec.rb:70 # ResetPasswordsController POST create with a valid token sets the email subject to notify the user of the reset password
rspec ./spec/controllers/reset_passwords_controller_spec.rb:67 # ResetPasswordsController POST create with a valid token sends a confirmation email to the user that their password has been changed
rspec ./spec/controllers/reset_passwords_controller_spec.rb:73 # ResetPasswordsController POST create with a valid token sends the link with token in the body of the email
I can't explain what is really causing the error. But it must due to setting the Sidekiq test mode globally. Remove the Sidekiq setting from the head section of the specs and try the following:
before do
Sidekiq::Testing.inline! do
post :create, email: 'jen#example.com'
end
end
after do
ActionMailer::Base.deliveries.clear
Sidekiq::Worker.clear_all
end
it 'sends the reset email to the users provided email' do
expect(ActionMailer::Base.deliveries.count).to eq(1)
end

Rails 3 with Devise and rspec: Warden test helpers unreliable

I have an application using rails 3.2 and Devise. I have a request test suite using rspec and Capybara.
I have attempted to shift to using the Warden test helpers in my sign in helper rather than having Capybara fill in the sign in form and submit it. Due to the size and complexity of my test suite, this results in over a minute and a half of savings in my test runtimes.
In my configuration is:
RSpec.configure do |config|
config.include Warden::Test::Helpers, :type => :request
config.after :each do
Warden.test_reset!
end
end
And in a Context:
let!(:current_user) { FactoryGirl.create(:user) }
background do
login_as(current_user, :scope => :user)
end
However, when running the test suite using these configurations nearly every test run has a different randomly failing request spec due to the page presenting as though the user were not logged in. (Specifically, links controlled by a user_signed_in? conditional)
My question: Has anyone else encountered such unreliability and how can it be mitigated?
The absolute easiest thing to do is just use the sign_in form in your before :each block. You need the test helpers in Controller specs, because it's isolated from devise. You don't have that problem in an integration test.
Though an old post I also have this problem with Rails 4.1 and Warden 1.2.3. I noticed that there is a newer version of Warden with work on the test helpers. Anyone success with the newer version?
Btw the behavior that I observe is that Warden does not always successfully login via the login_as helper. This results in my app finding itself on the login page instead of the place it thought it ought to be.

How can I put RSpec Rails Controller tests in a different directory?

I'd like to put a few integration tests in a separate directory from my controller unit specs. However, when I move my spec file to spec/integration, it fails with:
ArgumentError:
bad argument(expected URI object or URI string)
The spec passes correctly when in the spec/controllers directory.
Here's a bit from my spec:
require 'spec_helper'
describe Users::LoginsController, type: :controller do
let!(:user) { User.create(email: 'test#test.com', password: 'test')
it 'logs in the user' do
post :create, email: 'test#test.com', password: 'test'
controller.current_user.should == user
end
end
I'm using Rails 3.1.3, RSpec 2.7.0.
Are there any tricks I have to use to achieve this?
Try specifying type:
describe ProductsController, type: :controller do
it 'can test #show' do
get :show
end
end
Works in Rails 3.2.11
You have to do the following:
describe Users::LoginsController do
controller_name 'users/logins'
... the rest of your spec here ...
end
I am not entirely certain about the nested syntax, but at least you need to specify the controller_name to get it to work.
Hope this helps.
The test framework does not like it if you specify the test action using a symbol.
it 'logs in the user' do
post :create, email: 'test#test.com', password: 'test'
controller.current_user.should == user
end
becomes
it 'logs in the user' do
post 'create', email: 'test#test.com', password: 'test'
controller.current_user.should == user
end
I had the same problem and ended up simply using the URL
get "/users"
It's not as clean but gets the job done. I couldn't get the other suggestions to work.
This approach works for me in Rails 4 and RSpec 2.14.7:
My findings:
Don't name your directory integration. I need to grep through the source of either RSpec or Rails, but it appears to have an adverse effect on running controller specs. Perhaps someone with this knowledge can chime in to confirm this.
Name it something other than integration; in my case I tried int, which resulted in problems until I added the "type: :controller" after the #describe method.
After that, I was able to move all of my slow Rails specs into my int directory, allowing me to create a unit directory for all of my decoupled, fast specs.
Please let me know if this works for you.
By the way, I am running:
Ruby 1.9.3
Rails 4.0.2
rspec-core 2.14.7
rspec-rails 2.14.1
all on Mac OS X.
Take the opportunity now to get rid of your controller and integration specs. They're needlessly painful to write and too coupled to implementation. Replace them with Cucumber stories. Your life will be much easier...

Rails 3 / RSpec: Controller tests -- access to a class function in my test returns an SQLite3::SQLException "no such table" error

I have a Page scaffold that I created through rails generate scaffold. I ran rake db:migrate, and viewing the database through SQLite Database Browser reveals that it in fact exists. I can go to the rails console and run:
Page.all.each {|page| puts page.url}
When I run this, it in fact returns the right results (e.g., the value of url for each record of Page.
What I am trying to do is set up an rspec test in my pages controller test to see that each of the routes I've set up in config/routes.rb actually works. So I have a test defined in spec/controllers/pages_controller_spec.rb as follows:
describe PagesController do
Page.all.each do |page|
describe "GET /#{page.url}" do
it "should be able to get at page at #{page.url}" do
get "/#{page.url}"
response.should be_successful
end
end
end
end
This test does not run. Instead, it generates the following message:
C:/Ruby192/lib/ruby/gems/1.9.1/gems/activerecord-3.0.1/lib/active_record/connection_adapters/abstract_adapter.rb:202:in `rescue in log': SQLite3::SQLException: no such table: pages: SELECT "pages".* FROM "pages" (ActiveRecord::StatementInvalid)
Does anyone know what is going on? Or, in the alternative, does anyone know why this will work in my Rails Console, but not in my rspec tests?
Thank you so much. I am relatively new to Rails, so still learning a lot!
Run rake db:test:prepare to make sure the database schema is setup in the test environment.

Resources