Back in the days when controller specs were a good idea and Rspec wasn’t all mighty, there was a little testing framework that could.
Rspec has added many great features over the years. Although I really enjoyed coding this, request specs are a superior solution.
-
Via the gem
gem install funktional
-
With braid
braid add git://github.com/brentgreeff/funktional.git -p
-
add a setup line to ‘test/test_helper.rb’
class ActiveSupport::TestCase setup :funktional end
Done!
* should_pricot (Hpricot matchers in Test::Unit) * hash_factory (Super simple factories for your tests) * matchy (RSpec matchers in Test::Unit)
Contexts, Don’t Repeat Yourself, share common setup steps between your tests.
context "On a hot summer day" do before { day :hot } context "in the middle of July" do before { Time.now = 'July 15' } should "be on the beach" do assert_equal 'beach', @me.location end should "be drinking lemonade" do assert_equal 'lemonade', @me.drinking end end end
-
Start off with a valid instance
context "A Company" do setup { @company = create_company } should "respond to fax no" do @company.should_respond_to :fax_no end should "require a name" do @company.should_require_a :name, 'please enter the name' end should "require an address" do @company.should_require_an :address, 'please enter the address' end should "not allow creative accounting" do @company.creative_accounting = true @company.should_have_invalid :books, 'no creative accounting please' end should "not require a telephone no if an address is present" do @company.address = an_address @company.should_not_require_a :telephone_no end should "not have a name longer than 80 characters" do @company.name = 81.random_characters @company.should_have_invalid :name, 'max is 80' # random_characters is a small useful helper method. end end
should "send email" do should :send_email => { :from => '[email protected]', :to => '[email protected]', :subject => 'Your order', :containing => "important info" } end should "not send email" do should_not :send_email do # do something here end end
should "create something" do should :create => Something do # Do something end end should "delete something" do should :delete => Something do # Do something end end should "not delete something" do should_not :delete => Something do # Do something end end should "not create something" do should_not :create => Something do # Do something end end
should :route => '/onions/new' do controller 'onions' action 'new' end
-
you need to pass the method if its not a :get request
should :route => '/onions', :method => :post do controller 'onions' action 'create' end
should "show the new order page" do get :new should :render => 'orders/new' end
The default ‘should :render’ checks for a http status code of 200
-
What about other codes?
should "return the not found page when the id does not exist" do get :show, :id => 'something does not exist' should :render_404 => 'public/404' end
should "go to the login page if not logged in" do logout get :new should :redirect_to => '/login' end
should "assign a new order" do get :new should :assign_new => Order end
should "load order by id" do get :edit, :id => @order.id assigned(Order).should_be @order end
-
This checks the object assigned is of the correct type.
should "associate the current user as the editor" do login_as @user = create_user put :update, :id => @article.id assigned(Article).editor.should_be @user end should "chain as long as you like" do assigned(Article).editor.first_name.should_be 'pete' end
-
If you pass a Symbol its just a value based assertion.
should "load a collection" do get :index assigned(:records).should_be [@record_1, @record_2] end
should "notify the user when order was created" do post :create, :order => attrib flashed(:notice).should_be 'Yay, Order created!' end
There are also some helpers for manipulating attributes.
I tend to define an attrib method in my funtional tests to represent valid attributes passed to create or update a resource.
-
eg:
def attrib { :first_name => 'Jim', :last_name => 'Bean' } end
Sometimes you want to tests different values, especially invalid ones, to get away from all the merge noise, I have defined these helpers:
missing_attrib blank_attrib replace_attrib add_attrib
-
Means you can write tests like the following:
should_not :create => Order do post :create, :order => blank_attrib(:cc_no) end should :render => 'orders/new'
context "When doing it all" do before { :hit_a_controller } should :render => 'somethings/new' should :render_404 => 'public/404' should :render_404 # (defaults to 'public/404') should :redirect_to => '/somethings' element('h1').should_be 'Something' # (you need should_pricot for this one). count('#friends ol.remaining').should_be 'Not Many' # (should_pricot here too) flashed(:notice).should_be 'Cool' should :assign_new => Something assigned(Something).name.should_be 'something' assigned(:something).should_be { @something } should :create => Something should :delete => Something should_not :create => Something should_not :delete => Something should :send_email => { :from => '[email protected]', :to => '[email protected]' } should_not :send_email end
Copyright © 2009 [Brent Greeff], released under the MIT license