Why use setup method for test suites in Ruby on Rails? - ruby-on-rails

I am working through railstutorial.org and in our first test suite we setup an instance variable in a setup method.
require 'test_helper'
class StaticPagesControllerTest < ActionDispatch::IntegrationTest
def setup
#base_title = "Ruby on Rails Tutorial Sample App"
end
test "should get home" do
get static_pages_home_url
assert_response :success
assert_select "title", "Home | #{#base_title}"
end
test "should get help" do
get static_pages_help_url
assert_response :success
assert_select "title", "Help | #{#base_title}"
end
test "should get about" do
get static_pages_about_url
assert_response :success
assert_select "title", "About | #{#base_title}"
end
end
Why do we do this instead of just defining it straight up as an instance variable?

You are defining it as an instance variable. When the test is run the class (StaticPagesControllerTest) is instantiated and the setup function called on that instance, not on the class. If you tried to do the following instead it would define a class level instance variable not accessible from instances:
class StaticPagesControllerTest < ActionDispatch::IntegrationTest
#base_title = "Ruby on Rails Tutorial Sample App"
test "should get home" do
get static_pages_home_url
assert_response :success
assert_select "title", "Home | #{#base_title}" # XXX not defined on instance
end
...
See this page for one explanation of the difference.
You could use a class variable (##base_title) but that might cause surprising consequences later, e.g. if you wanted to subclass the test.
Here's a quick demonstration:
class First
#a = 'hoge'
##b = 'hoge'
def initialize
#c = 'hoge'
end
def give_me_a
#a
end
def give_me_b
##b
end
def give_me_c
#c
end
end
f = First.new
# => #<First:0x007fb81607fcd0>
f.give_me_a
# => nil
f.give_me_b
# => "hoge"
f.give_me_c
# => "hoge"

Related

StatementInvalid: SQLite3::BusyException: database is locked

I have referred various answers on StackOverflow but I still haven't been able to resolve this issue. I am sharing the code for my controllers_test.rb and along with that the screenshot. Every time I run rails test, the following error is shown. I have made sure that console is close. In case there is any other source code needs to be share please do let me know.
require "test_helper"
class CategoriesControllerTest < ActionDispatch::IntegrationTest
setup do
#category = Category.create(name: "Sports")
end
test "should get index" do
get categories_url
assert_response :success
end
test "should get new" do
get new_category_url
assert_response :success
end
test "should create category" do
assert_difference('Category.count') do
post categories_url, params: { category: { name: "Travel" } }
end
assert_redirected_to category_url(Category.last)
end
test "should show category" do
get category_url(#category)
assert_response :success
end
end
test_helper.rb
class ActiveSupport::TestCase
# Run tests in parallel with specified workers
parallelize(workers: :number_of_processors, with: :threads)
# 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

Can someone identify the error in my code causing my test to fail?

I keep running this test and it continually fails, yet I cannot find an error. The failure message is:
[Failure:
StaticPagesControllerTest#test_should_get_contact [/Users/iThompkins/Documents/SiteDev/environment/sample_app/test/controlle
rs/static_pages_controller_test.rb:26]:
<Contact | Ruby on Rails Tutorial Sample App> expected but was
<Ruby on Rails Tutorial Sample App>..
Expected 0 to be >= 1.]
My test looks like:
require 'test_helper'
class StaticPagesControllerTest < ActionDispatch::IntegrationTest
test "should get home" do
get static_pages_home_url
assert_response :success
assert_select "title", "Ruby on Rails Tutorial Sample App"
end
test "should get help" do
get static_pages_help_url
assert_response :success
assert_select "title", "Help | Ruby on Rails Tutorial Sample App"
end
test "should get about" do
get static_pages_about_url
assert_response :success
assert_select "title", "About | Ruby on Rails Tutorial Sample App"
end
test "should get contact" do
get static_pages_contact_url
assert_response :success
assert_select "title", "Contact | Ruby on Rails Tutorial Sample App"
end
end
My controller
class StaticPagesController < ApplicationController
def home
end
def help
end
def about
end
def contact
end
end
And my View
<% provide(:title, 'Contact') %>
Contact
Contact the Ruby on Rails Tutorial about the sample app at the
contact page.
Have you got <%= yield(:title) %> in the title section of your view?
<title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
From the Hartl book, you need to yield the title value to get it to display.

Rails tutorial Testing failure

I am following a Rails tutorial..
Here is my testing file
require 'test_helper'
class StaticPagesControllerTest < ActionDispatch::IntegrationTest
def setup
#base_title = "Ruby on Rails Tutorial Sample App"
end
test "should get home" do
get static_pages_home_url
assert_response :success
assert_select "title", "Home | #{#base_title}"
end
test "should get help" do
get static_pages_help_url
assert_response :success
assert_select "title", "Help | #{#base_title}"
end
test "should get about" do
get static_pages_about_url
assert_response :success
assert_select "title", "About | #{#base_title}"
end
end
This is the error message i get:
Failure:
StaticPagesControllerTest#test_should_get_home
[c:/Sites/workspace/sample_app/te
st/controllers/static_pages_controller_test.rb:12]:
<Home | Ruby on Rails Tutorial Sample App> expected but was
<Home>..
Expected 0 to be >= 1.
Do take a not that the error sometimes shows About/Help in place of Home.
BTW when i comment out lines 5 to 7 and replace #{#base_title} in each of the tests the rails test result is success then.
Really conflicted with what is going on here.

How can I determine the subject of an rspec controller test?

So I don't have a great reason for needing to know this other than curiosity - the BEST reason - but I'm not sure what's going on here.
Background:
I'm working through the RSpec book and updating the examples.
On Chapter 24 - Rails Controllers there's a test for a messages controller.
## spec/controllers/messages_controller_spec.rb ##
require 'spec_helper'
describe MessagesController do
describe "POST create" do
let(:message) { mock_model(Message).as_null_object }
before do
Message.stub(:new).and_return(message)
end
# Then a bunch of Tests...
context "when the message fails to save" do
before do
message.stub(:save).and_return(false)
post :create
end
it "assigns #message" do
assigns[:message].should eq(message)
end
it "renders the new template" do
response.should render_template("new")
end
end
end
end
This goes along with the messages controller:
## app/controllers/messages_controller.rb ##
class MessagesController < ApplicationController
def create
#message = Message.new(params[:message])
if #message.save
flash[:notice] = "The message was saved successfully"
redirect_to action: "index"
else
render "new"
end
end
end
When I run the tests:
The test passes with response.
it "renders the new template" do
response.should render_template("new")
end
The test also passes with subject.
it "renders the new template" do
subject.should render_template("new")
end
The test Also passes with page
it "renders the new template" do
page.should render_template("new")
end
The test ALSO passes with NOTHING
it "renders the new template" do
should render_template("new")
end
In case it helps anyone make heads or tails of this, the config/routes.rb just has resources :messages
Why do all those tests pass? What am I actually testing? Are 'page', 'subject', and ' ' just synonyms for response?
Does it matter as long as my tests pass?
By default, the subject would be referencing the class, which is the MessagesController.
Not defining a subject in the last test example, will implicitly set the subject to be MessagesController.
From a binding.pry, it appears that subject is an instance of the controller class:
[2] pry(#<RSpec::ExampleGroups::MyController::DescribeString::ContextString>)> subject.is_a? Class
=> false
[3] pry(#<RSpec::ExampleGroups::MyController::DescribeString::ContextString>)> subject.is_a? Users::SessionsController
=> true

minitest: undefined method `get'

I'm need to test my controller with minitest.
I've tried:
describe 'CommentsController' do
it "should get index" do
get :index
assert_response :success
end
end
and
class CommentsControllerTest < MiniTest::Unit::TestCase
def test_should_get_index
get :index
assert_response :success
end
end
but I have "undefined method `get'" error
You should add the minitest-rails gem, following the steps outlined in the documentation. Then your tests should look like this:
require "minitest_helper"
describe CommentsController do
it "should get index" do
get :index
assert_response :success
end
end
Or, look like this:
require "minitest_helper"
class CommentsControllerTest < MiniTest::Rails::ActionController::TestCase
test "should get index" do
get :index
assert_response :success
end
end

Resources