My MacBook Pro died recently and I got a new one, restored all my files on it and came back to my rails app that I've been developing for quite some time.
In there somewhere, I'd moved the directory where I kept the app (and the Aptana Studio 3 project, though I'm guessing that's not relevant). The app now runs, but all of my functional tests crash, because it thinks the variable "session" is undefined. Here's a boiled down version of my test case code:
require 'test_helper'
class SkillsControllerTest < ActionController::TestCase
...
test "should not copy when current user does not have write permission" do
session[:user] = users(:existingbob)
assert_no_difference("Skill.count") do
post :create, :campaign_id => 1, :skill_uri => {:campaign_id => 1, :skill_id => 1}
end
assert_redirected_to permissions_path()
end
...
end
I do a lot of this, my application check to see if users have permission for a particular action, and I have a lot of tests to check that it's working right.
After my upheaval, the tests crash with the message:
/blah/blah/blah/skills_controller_test.rb:260:in`<class:SkillsControllerTest>':
undefined local variable or method `session' for SkillsControllerTest:Class (NameError)
This all used to work fine, and from what I can tell from the docs, it's still supposed to work just fine. I think I'm misconfigured somehow, but frankly, I don't even know where to start looking.
What's wrong? Where should I look to see?
Related
In my Rails app, I have a couple of controllers where I have an after_action hook that sends an email through an ActionMailer. Like so:
after_action :send_notifications, only: [:create, :update]
def send_notifications
case #record.status.downcase
when 'review', 'corrected'
RecordNotifier.received(#record).deliver_later
when 'rejected'
#rejection = Rejection.where(record_id: #record.id).last
RecordNotifier.rejected(#record, #rejection).deliver_later
when 'submitted'
#form = Form.find( #record.form_id )
RecordNotifier.submitted(#record).deliver_later
end
end
My problem is that my test suite fails randomly because sometimes a mailer will still need to finish executing after the spec has run, but since the Database gets cleaned after each test, the objects the mailer needs don't exist anymore. But I'm pretty sure thats the problem--I had one test that was failing in this way, but when I added sleep 1 before the last expect(page).to have_something statement, it passed. I could also see it in the logs--the database getting zapped before the app was ready.
Incidentally, I don't have any ActiveJob setup for the mailers, I just used deliver_later because the guides said it worked the same and if I add ActiveJob later, it will already be ready.
So how do I avoid this? How do I make sure the app is all done before the spec exits and DatabaseCleaner runs?
I have a weird issue when creating a controller spec for a namespaced controller when there also is a global controller with the same name.
The controller names are HomeController and Backend::HomeController.
Note that I have not yet created the file app/controllers/backend/home_controller.rb, only the global controller exists app/controllers/home_controller.rb
Therefore I expect the test to explode with errors, but it does not. It passes, all green and happy.
My spec looks like this
#spec/controllers/backend/home_controller_spec.rb
require 'rails_helper'
RSpec.describe Backend::HomeController, type: :controller do
before do
user = FactoryGirl.create(:user)
allow(controller).to receive(:authenticate_user!).and_return(true)
allow(controller).to receive(:current_user).and_return(user)
end
describe "GET #index" do
it "returns http success" do
get :index
expect(response).to have_http_status(:success)
end
end
end
However if I change the name in my global HomeController to something else, e.g NotMyHomeController the test fails with errors saying
Unable to autoload constant HomeController, expected app/controllers/home_controller.rb to define it
Which makes me suspect that Rspec doesn't bother with the "Backend" part in the Rspec.describe function.
Am I doing something wrong or am I missing some other vital part? IMHO, this spec shouldn't pass (to paraphrase Gandalf).
I'm using Rails 4.2.6, Rspec-Rails 3.4.2
Update
As Max pointed out, this is probably not at Rspec issue but instead something with Rails autoloading.
However i tried just typing
Backend::HomeController
In the Rails console, but there I get the expected error
NameError: uninitialized constant Backend::HomeController
And according to the Rails guide, both the console and the test suite autoloads. However I think I'm on the right track here.
I had this same problem before - you can read about the whole issue here:
Object.const_get and Rails - cutting off parent module names
but the meat of the answer comes from this answer from user Apneadiving:
Be aware that there are vicious cases in Rails development mode. In order to gain speed, the strict minimum is loaded. Then Rails looks for classes definitions when needed.
But this sometimes fails big time example, when you have say ::User already loaded, and then look for ::Admin::User. Rails would not look for it, it will think ::User does the trick.
This can be solved using require_dependency statements in your code.
I'm trying to add tests to an old app I started working on, but I'm failing miserably :(
It's a Rails 2.3.8 app with Rspec 1.3.2 and Rspec-rails 1.3.4.
This is all I have right now on a controller spec:
before(:each) do
#attributes = { ... }
end
it 'should create a notification' do
post 'create', :notification => #attributes
assigns[:notification].should_not be_new_record
end
I spent hours trying to figure out why the #notification variable wasn't being set, and I just found out the response has been 501 Not Implemented all this time...
Of course the controller works fine from a browser, so for the life of me I can't figure out why I'm getting that error.
Any ideas?
Bah, I forgot to clone the test database so some of the attributes I was assigning weren't on the test DB, and thus the error.
I only found out after I remembered log/test.log exists... I'm glad nobody answered first or I'd be even more embarrased :D
I have generated some scaffolding for my rails app.
I am running the generated tests and they are failing.
for example
test "should create area" do
assert_difference('Area.count') do
post :create, :area => { :name => 'area1' }
end
assert_redirected_to area_path(assigns(:area))
end
This test is failing saying that :
1) Failure:
test_should_create_area(AreasControllerTest)
[/test/functional/areas_controller_test.rb:16]:
"Area.count" didn't change by 1. <3>
expected but was <2>.
There is only one field in the model : name. I am populating this so it cant be because I am failing to populate the only field.
I can run the site and create an area with the name 'area1'. So reality is succeeding, but the test is failing.
I cant ask why its failing, because Im sure theres not enough information here for anyone here to know why. Im just stuck at knowing what avenues to go down to work out why the test is failing. Even putting puts into the code dont print out...
What steps can I take to track this down?
Per the request above, and matching what I was expecting that you'd find when you dug into your logs, you have an authorization that isn't being met in your test.
#request and #response are also useful objects to look at (i.e. puts #response inside your test). I don't know what authentication you are using, but check RAILS_ROOT/lib for authenticated_test_helper, or the /lib, or /test of your authentication gem. You'll find methods for performing a login.
OK, I am writing performance tests and am having trouble getting my session to persist like it does in integration tests. As I understand it, PerformanceTest is a child of IntegrationTest and any integration tests should work with performance test. However, when I take a integration test and copy it over to performance, change the ActionController::IntegrationTest to ActionController::PerformanceTest and then run the test, it fails.
I am using Authlogic and have not had a problem with the integration test sessions sticking around. With the performance tests though it looks like the session gets created properly but when I visit the "/reports" page (which is a protected page) it redirects me to the login page like there is no user session at all.
require 'performance_test_help'
class SimpleTest < ActionController::PerformanceTest
setup :activate_authlogic
test "login" do
assert user_session = UserSession.create!(User.find_by_login("admin"))
get "/reports"
assert_response :success
end
end
What's going on here? I've tried multiple ways to get a user session (create, post, etc.) and nothing seems to work. This is the first time I've written performance tests so I'm probably doing something stupid...
BTW: I am running Ruby 1.8.7, Rails 2.2.2 on Debian Squeeze.
You have to setup your performance tests like your integration tests.
Try to login using post:
post "user_session", :user_session => {:login => "user", :password => "password"}
not sure what is in your setup there, but you are missing require 'test_helper' as well. If this method is in there, or in an Authlogic test helper, you may have to make sure it's included.