I'm working my way through the RailsTutorial book and have stalled in Chapter 3.
I'm beginning to feel like I'm going insane!
The autogenerated tests for the 'home' and 'contact' pages work fine, but try as I might I cannot get my test for the 'about' page to pass.
I have (and I tell no lie) created and the deleted the addional lines in the routes.rb file and the pages_controller.rb file and created the view file no fewer than 4 times just in case I had some strange non-printing characters. I must have checked my versions against the sample code from the book at least twice that many times!
I temporarily changed the 'about' test case into a second 'contact' test just to prove that the syntax of the test case is fine. It works OK.
To make matters worse, the 'about' page actually renders fine in the browser...
I've just created another new page called 'landing' and I get the same failure.
It's like the autogenerated tests were sprinkled with fairy dust!
Has anybody experienced similar?
I guessing that it's something glaringly obvious, but after 5 hours with no visible progress frustration has got the better of me...
I'm using Ubuntu 10.04, Ruby 1.9.2, Rails 3.0.3
RESOLVED An Issue with spork not reloading files
Sounds like you've been thorough. So this isn't working?
# pages_controller_spec.rb
describe "GET 'landing'" do
it "should be successful" do
get 'landing'
response.should be_success
end
end
# pages_controller.rb
def landing
end
# routes.rb
get "pages/landing"
# views/pages/landing.html.erb
blah
Related
I did a total rearrangement of my routes so I'm having to go back and change some path names. I ran a cucumber test for my navigation and it came back a success. Knowing that I have some old routes to change I thought that was an odd result so I did some manual checking to confirm my suspicions.
As an example I clicked on a page that was supposed to have a old and obsolete path <li><%= link_to p.title, forum_post_path(p) %></li> that's breaks the page when I am manually clicking around I get a no method error as I should.
But, when I run the cucumber test and use launchy to save and open page. I don't get that error. It loads like there isn't a problem at all. The launchy page that I'm given loads the link_to helper with the bad _path like there isn't a problem at all...
The only thing I can think of is that the words that it is expecting would be there and perhaps the page is loading correctly for a brief moment before Rails spits out the method error and Cucumber is picking up on the positive result first before it returns an error.
Any possible things I can look at? I would hate to get false positives.
Edit: I just added a 1 second sleep timer (should be more than enough) and cucumber still gives me a pass.
Here are the tests so you can view it:
# navigation.feature
Scenario: As a user I want to be able to view a specific forum and it's posts within.
Given There is a User
Given There is a Forum
Given I am on the index
When I click the "Test forum name" link
Then I should see "Name: Test forum name"
Then I should see "Description: test description with a minimum of 20 characters.."
And...
#navigation_steps.rb
Given(/^There is a User$/) do
User.create!(email: "user#test.com", password: "password#1")
expect(User.first.email).to eq("user#test.com")
end
Given(/^I am on the index$/) do
visit root_path
end
Given(/^There is a Forum$/) do
Forum.create!(name: "Test forum name", description: "test description with a minimum of 20 characters..", user_id: User.first.id)
expect(Forum.last.name).to eq("Test forum name")
end
When(/^I click the "([^"]*)" link$/) do |link|
click_link link
end
Then(/^I should see "([^"]*)"$/) do |message|
expect(page).to have_content(message)
end
Screenshots:
You don't say what exactly your tests are checking for, but a couple of possible reasons for this are:
You're using something like spring to keep your test environment loaded - If you are it may not be seeing changing to routes.rb and may require restarting before it knows the routes have changed. Solution: Restart spring or whatever your are using to keep the test env loaded
You incorrectly have the web-console gem in the test environment (it should only be in the development environment) which catches any errors and produces the nice error page. If that error page has the text on it your test checks for (possible since it includes the surrounding code) then your test can pass - Solution: remove web-console from the test environment in your Gemfile.
For the Rails Tutorial, I know what the solution is. (It's also here.) I do not understand why escaping the HTML is necessary though. I guess I'm confused on what it does. Specifically, in the user_profile_test.rb file given by this tutorial, we have the following test:
test "profile display" do
get user_path(#user)
...
assert_select 'div.pagination'
#user.microposts.paginate(page: 1).each do |micropost|
assert_match micropost.content, response.body
end
end
Why is escaping the HTML not necessary in this test and is necessary in the chapter 12 exercise one?
You need to escape HTML, to sanitize your data before it hits your database.
From the Ruby Docs:
CGI::escapeHTML('Usage: foo "bar" <baz>')
# => "Usage: foo "bar" <baz>"
If you didn't use escapeHTML someone could put a <script> tag in there and potentially write some harmful code. Maybe it's a social network site and people are embedding some malware in their comment and then everyone that visits for page has a bad time as well as you.
As far as the test goes, I think that's the reason, because you can control the test. But at the same time I really don't see why wouldn't add escapeHTML to the test as well, but maybe it's just not required where you are studying.
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'm using Test/Unit with a standard rails 2.1 project. I would like to be able to test Partial Views in isolation from any particular controller / action.
It seemed as though ZenTest's Test::Rails::ViewTestCase would help, but I couldn't get it working, similarly with view_test http://www.continuousthinking.com/tags/view_test
Most of the stuff Google turns up seems quite out of date, so I'm guessing doesn't really work with Rails 2.1
Any help with this much appreciated.
Thanks,
Roland
We're using RSpec in our Rails 2.1 project, and we can do this sort of thing:
describe "/posts/_form" do
before do
render :partial => "posts/form"
end
it "says hello" do
response.should match(/hello/i)
end
it "renders a form" do
response.should have_tag("form")
end
end
However I don't know how much of that you can do with the vanilla Rails testing apparatus.
Found this which may be relevant:
http://broadcast.oreilly.com/2008/10/testing-rails-partials.html
Testing a view without the controller code is a dangerous thing. Your tests might pass but your application might throw an error. Always test against real life situations not artificial ones.