I'm following along with RailsSpace: Building a Social Networking Website with Ruby on Rails by Michael Hartl. Running rails v2.3.2.
I've gotten to the 5th chapter in which testing is introduced. The following is supposed to match the title of the various pages to strings using the get method:
require File.dirname(__FILE__) + '/../test_helper'
require 'site_controller'
# Re-raise errors caught by the controller.
class SiteController; def rescue_action(e) raise e end; end
class SiteControllerTest < Test::Unit::TestCase
def setup
#controller = SiteController.new
#request = ActionController::TestRequest.new
#response = ActionController::TestResponse.new
end
def test_index
get :index
title = assigns(:title)
assert_equal "Welcome to RailsSpace!", title
assert_response :success
assert_template "index"
end
def test_about
get :title
title = assigns(:title)
assert_equal "About RailsSpace", title
assert_response :success
assert_template "about"
end
def test_help
get :help
title = assigns(:title)
assert_equal "RailsSpace Help", title
assert_response :success
assert_template "help"
end
end
On compiling I get:
Loaded suite site_controller_test
Started
EEE
Finished in 0.057 seconds.
1) Error:
test_about(SiteControllerTest):
NoMethodError: undefined method `get' for #<SiteControllerTest:0x4854b30>
site_controller_test.rb:23:in `test_about'
2) Error:
test_help(SiteControllerTest):
NoMethodError: undefined method `get' for #<SiteControllerTest:0x4854b1c>
site_controller_test.rb:31:in `test_help'
3) Error:
test_index(SiteControllerTest):
NoMethodError: undefined method `get' for #<SiteControllerTest:0x485470c>
site_controller_test.rb:15:in `test_index'
3 tests, 0 assertions, 0 failures, 3 errors
Other people have had this issue and the only proposed solution is just to reinstall. I'm not to enthused by this. Since this is an older book there this is probably just breakage between rails versions. What would be the equivalent of this for rails v2.3.2?
Replace all the following code
# Re-raise errors caught by the controller.
class SiteController; def rescue_action(e) raise e end; end
class SiteControllerTest < Test::Unit::TestCase
def setup
#controller = SiteController.new
#request = ActionController::TestRequest.new
#response = ActionController::TestResponse.new
end
with
class SiteControllerTest < ActionController::TestCase
The code you are using refers to Rails 2.0/2.1.
Try changing Test::Unit::TestCase to ActionController::TestCase.
One other thing you might like to know is that Railspace has evolved into Insoshi so the latest code is available there. Might be handy for you when you run into other issues.
Related
I am just started learning Ruby on Rails. Current chapter is about testing, while I do testing it is happening like this? What do i need to do? and What should I learn more to understand testing ruby on rails ?
Here's my Controller test code.
require 'test_helper'
class CategoriesControllerTest < ActionDispatch::IntegrationTest
def setup
#category = Category.create(name: "sports")
#user = User.create(username: "supyaeaung", email: "supyaeaung27714#gmail.com", password: "hlaing", admin: true)
end
test "should get new" do
sign_in_as(#user, "password")
get new_category_path
assert_response :success
end
Here's the error. What should I do ?
Error:
CategoriesControllerTest#test_should_get_new:
NoMethodError: undefined method `confirm' for #<User:0x00007fd0781e0370>
test/controllers/categories_controller_test.rb:15:in `block in <class:CategoriesControllerTest>'
Your controller, on line 15 tries to call method confirm on User object:
NoMethodError: undefined method `confirm' for #<User:0x00007fd0781e0370>
test/controllers/categories_controller_test.rb:15
You probably didn't implement it.
I'm using Rails 5 and minutest and trying to write a test for a controller. The test is
# issues_controller_test.rb
class IssuesControllerTest < ActionDispatch::IntegrationTest
include Devise::Test::IntegrationHelpers
test "logged in should get issues page" do
sign_in users(:one)
test_stop_id = 1
test_line_id = 1
get new_issue, :stop_id => test_stop_id, :line_id => test_line_id
assert_equal test_stop_id, #issue.stop_id
assert_equal test_line_id, #issue.line_id
assert_response :success
end
end
The method in question attempts to access this page, defined in my rails routes ...
new_issue GET /issues/new(.:format) issues#new
Yet when I run the test, I get this error
# Running:
.E
Error:
IssuesControllerTest#test_logged_in_should_get_issues_page:
NameError: undefined local variable or method `new_issue' for #<IssuesControllerTest:0x007f816759b330>
test/controllers/issues_controller_test.rb:10:in `block in <class:IssuesControllerTest>'
bin/rails test test/controllers/issues_controller_test.rb:6
Finished in 0.103956s, 19.2389 runs/s, 9.6195 assertions/s.
Why is the test framework unable to find a method defined in my routes file?
new_issue that way is just a local variable defined nowhere, try specifying it as a working url with new_issue_url:
test 'logged in should get issues page' do
sign_in users :one
test_stop_id = 1
test_line_id = 1
get new_issue_url, stop_id: test_stop_id, line_id: test_line_id
assert_equal test_stop_id, #issue.stop_id
assert_equal test_line_id, #issue.line_id
assert_response :success
end
The Show action for my Controller is not passing the unit test. I'm getting an error in my ControllerTest. Here is the error I get from 'rake test':
> ERROR["test_should_get_show", TransactionsControllerTest, 2015-07-18
> 00:30:18 -0400] test_should_get_show#TransactionsControllerTest
> (1437193818.29s) ActiveRecord::RecordNotFound:
> ActiveRecord::RecordNotFound: Couldn't find Transaction with 'id'=
> app/controllers/transactions_controller.rb:21:in `show'
> test/controllers/transactions_controller_test.rb:6:in `block in <class:TransactionsControllerTest>'
> app/controllers/transactions_controller.rb:21:in `show'
> test/controllers/transactions_controller_test.rb:6:in `block in <class:TransactionsControllerTest>'
>
> 5/5:
> [=======================================================================================================================] 100% Time: 00:00:00, Time: 00:00:00
>
> Finished in 0.24993s 5 tests, 4 assertions, 0 failures, 1 errors, 0
> skips
Despite this error, the view is successfully generates the page in the browser when I use this url:
http://localhost:3000/transactions/1
So, there is an error somewhere. It's not failing.
transactions_controller.rb
class TransactionsController < ApplicationController
def new
#transaction = Transaction.new
end
def create
#transaction = Transaction.new(transaction_params)
if #transaction.save
# Handle a successful save.
else
render 'new'
end
end
def index
#transactions = Transaction.all
end
def show
#transaction = Transaction.find(params[:id]) #this is row 21
end
private
def transaction_params
params.require(:transaction).permit(:company, :month, :account_code, :description, :transaction_amount)
end
end
transaction_controller_test.rb
require 'test_helper'
class TransactionsControllerTest < ActionController::TestCase
test "should get show" do
transaction = Transaction.create
get :show, id: transaction.id #this is row 6
assert_response :success
end
end
The following fixture was automatically generated by rails. I'm new at rails and have to admit that I don't really understand fixtures.
transactions.yml
one:
company: MyString
month: 2015-06-19
account_code: MyString
description: MyString
transaction_amount: 1.5
two:
company: MyString
month: 2015-06-19
account_code: MyString
description: MyString
transaction_amount: 1.5
In my routes file, I'm setting the root to the index action. I plan to access the show action via the url http://localhost:3000/transactions/1 and (as mentioned above) it actually works.
routes.rb
Rails.application.routes.draw do
root 'transactions#index'
resources :transactions
end
transaction.rb
class Transaction < ActiveRecord::Base
validates :month, presence: true
validates :account_code, presence: true
end
transaction_test.rb
require 'test_helper'
class TransactionTest < ActiveSupport::TestCase
def setup
##transaction = transactions(:one)
#transaction = Transaction.new(company: "Inc", month: Date.new(2015,6,15).to_s,
account_code: "80-32100-12-1201-60010",
description: "Salaries & Wages - Histo Gross 1", transaction_amount: 100000)
end
test "should be valid" do
assert #transaction.valid?
end
test "month should be present" do
#transaction.month = " "
assert_not #transaction.valid?
end
test "account_code should be present" do
#transaction.account_code = " "
assert_not #transaction.valid?
end
test "month cannot be a string" do #not sure if this is worth anything at all
#transaction.month = "xxxxxxxxxxxx"
assert_not #transaction.valid?
end
end
The test auto generated by Rails (before I modified it) was very simple:
require 'test_helper'
class TransactionsControllerTest < ActionController::TestCase
test "should get show" do
get :show
assert_response :success
end
end
I modified it to the current version above because (I believe) the test should first create a transaction and then reference id somehow. But I'm not sure I did this correctly.
I've seen questions similar to this on Stackoverflow. For instance, this question was helpful, but didn't quite get me there
Count; find User with id= Minitest
NOTE: Initially, I set up the Controller incorrectly. I set it up as a singular "TransactionController" and changed it to the plural "TransactionsController". So I had to change the name in the unit test also. Perhaps this has had an effect on the app.
So... questions:
why is the unit test failing while the show action is actually
working in the browser?
How might I change the code in the unit test so it recognizes that
I'm using transaction_params?
Do I have to modify the fixtures when I make changes to the
unit_test or the controller?
Ok, so coorasse's suggestion to use create! forced the app to uncover a validation error. The initial error (Couldn't find Transaction with 'id'= ) was replaced with a new error:
ActiveRecord::RecordInvalid: Validation failed: Month can't be blank,
Account code can't be blank
This was confusing because it leads me to think of a model validation error. Why am I getting a model validation error in a ControllerTest? Also, the transaction.rb model clearly shows that that I've added validations to satisfy the presence of Month and AccountCode.
So, I spent some time reading through "A Guide to Testing Rails Applications" on RailsGuides
http://guides.rubyonrails.org/testing.html
All the way down in Section 8, it shows how to include a block of code before each test. Here is the new transaction_controller_test
transaction_controller_test.rb (REVISED)
require 'test_helper'
class TransactionsControllerTest < ActionController::TestCase
# called before every single test
def setup
#transaction = transactions(:one)
end
test "should get show" do
get :show, id: #transaction.id
assert_response :success
end
end
After this the test passed! Unfortunately, the RailsGuides doesn't tell me why I would want to use setup in a controller test. If any smart Rails gurus has some guidance on this, your comments would be appreciated.
I'm working my way through Michael Hartl's Rails Tutorial. I hit a snag in Chapter 3 Section 3 on Testing. After generating two controllers - home and help, I ran the following in the terminal:
bundle exec rake test
The test should have passed but I received the following error for both the home and help controllers:
1) Error:
StaticPagesControllerTest#test_should_get_home:
SyntaxError: /home/ubuntu/workspace/sample_app/app/controllers /application_controller.rb:7: syntax error, unexpected tSTRING_BEG, expecting keyword_end
render :text "hello, world!"
^
app/controllers/static_pages_controller.rb:1:in `<top (required)>'
I have reviewed the code and haven't seen anywhere the end keyword should be required.
My static_pages_controller_test.rb file is setup as follows:
require 'test_helper'
class StaticPagesControllerTest < ActionController::TestCase
test "should get home" do
get :home
assert_response :success
end
test "should get help" do
get :help
assert_response :success
end
end
static_pages_controller.rb has the following code:
class StaticPagesController < ApplicationController
def home
end
def help
end
end
application_controller.rb has this code:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
def hello
render :text "hello, world!"
end
end
routes.rb has this code:
Rails.application.routes.draw do
get 'static_pages/home'
get 'static_pages/help'
root 'application#hello'
end
Any thoughts on what the problem might be? I have search this site with no luck. Thanks in advance for your help.
I am not sure but isn't it should be like this
respond_to do |format|
format.html
format.js { render :text => "hello, world!" }
end
I'm writing a plugin that adds a class method to ActionController::Base, so in my functional test I am creating a simple controller to test against. The example below is totally stripped down to basically do nothing. The test succeeds all the way up to assert_template, which fails.
require 'rubygems'
require 'test/unit'
require 'active_support'
require 'active_support/test_case'
require 'action_controller'
require 'action_controller/test_process'
class UnderTestController < ActionController::Base
def index; end
end
ActionController::Routing::Routes.draw {|map| map.resources :under_test }
class MyPluginTest < ActionController::TestCase
def setup
#controller = UnderTestController.new
#request = ActionController::TestRequest.new
#response = ActionController::TestResponse.new
end
test "should render the correct template" do
get :index
assert_template :index # everything works except this assert
end
end
Here are the results from running the above file:
Loaded suite /Users/jjulian/sandbox/vendor/plugins/my_plugin/test/my_plugin_test
Started
E
Finished in 0.014567 seconds.
1) Error:
test_should_render_the_correct_template(MyPluginTest):
NoMethodError: undefined method `[]' for nil:NilClass
method assert_template in response_assertions.rb at line 103
method clean_backtrace in test_case.rb at line 114
method assert_template in response_assertions.rb at line 100
method test_should_render_the_correct_template in so_test.rb at line 22
method __send__ in setup_and_teardown.rb at line 62
method run in setup_and_teardown.rb at line 62
1 tests, 0 assertions, 0 failures, 1 errors
My questions: what am I missing to allow assert_template to work? Am I requiring the correct libraries? Extending the correct TestCase class?
I figured it out. First, the missing template is because the view_path needs to be explicitly set in the controller under test:
before_filter {|c| c.prepend_view_path(File.join(File.dirname(__FILE__), 'fixtures')) }
I created a dummy erb file in test/fixtures/under_test/index.erb. That brings me back to the nil error in response_assertions.rb. Well, it looks like I need to include another test class:
require 'action_view/test_case'
Now it works.
One additional note: assert_template uses match to determine success, so in this case, assert_template 'ind' would succeed, as would assert_template 'x'.
Try replacing the setup method in the test with just tests UnderTestController. Rails takes care of setting up the test controller, request and response for you automatically.