Last active
August 29, 2015 13:57
-
-
Save ericbrooke/9655160 to your computer and use it in GitHub Desktop.
A place to remember the stuff that actually works
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#setup on the command line | |
gem install rspec | |
rspec --init | |
#add to gemfile: | |
group :test, :development do | |
gem 'rspec-rails' | |
end | |
# on the command line | |
bundle install | |
rails generate rspec:install | |
#create .rspec and save in the file the following: | |
-- color | |
-- format documentaion | |
# feature Specs: | |
feature Page_Name do | |
scenario '' do | |
it '' do | |
end | |
end | |
end | |
# model specs: | |
# unit Tests: | |
describe Model_Name do | |
describe 'Method_name' do | |
it '' do | |
end | |
end | |
end | |
# before the method_name | |
# '#' class methods | |
# '.' instance methods | |
# matchers: | |
# for text content - | |
expect(page).to have_content('Privacy Policy') | |
# for CSS - | |
expect(page).to have_css('.support-form') | |
# Note . = class, # = id | |
# for selector e.g. <footer> or <a> - | |
expect(page).to have_selector('footer') | |
# match a regular expression - | |
animal.type should_match(/hamster/) | |
# counting number - | |
human.hands.count should == 2 | |
human.should have(2).hands | |
human.should have_at_least(2).hands | |
human.should have_at_most(2).hands | |
human.should be_within(1).of(10) | |
# monitoring change - | |
expect { human.save }.to change { Human.count }.by(1) | |
expect { human.save }.to change { Human.count }.by(1).from(1) | |
expect { human.save }.to change { Human.count }.by(1).to(2) | |
# raise_exception - | |
expect { human.save }.to raise_error (ActiveRecord::RecordInvalid) | |
# for links - | |
expect(page).to have_link('Privacy Policy', href: "Privacy_Policy.pdf") | |
# for testing type - | |
expect(user).to be_a(Hash) | |
# testing collections - | |
Content.find_contents_for_user(user.id).should include content1, content2 #does not care about order | |
Content.find_contents_for_user(user.id).should eq content1 | |
Content.find_contents_for_user(user.id).should be content1 | |
expect(User.most_liked(1)).to start_with(user) | |
# method testing - | |
human.should respond_to(alive?) | |
# other matchers - | |
human.should exist | |
human.should satisfy { |human| human.hungry? } | |
creature.should be_kind_of(Human) | |
human.name.should be_an_instance_of(String) | |
# testing callbacks - | |
# Use 'RSpec-candy' Gem | |
describe Content, '#after_create' do | |
it_should_run_callbacks :set_short_url, :set_new_content, :send_notification | |
end | |
# testing with one subject allows you define the subject and then use it {} statements | |
subject { content } | |
it { should be_valid } or it { should_not be_valid } | |
# implicit subject/receiver | |
# if you use a class name in your describe block i.e. 'describe Human do' you have five further options: | |
subject.should respond_to(:name) | |
OR | |
should respond_to(:name) | |
describe Human do | |
it 'responds to name do | |
should respond_to(:name) | |
end | |
end | |
describe Human do | |
it 'responds to name' { should respond_to(:name) } | |
end | |
describe Human do | |
it { should respond_to(:name) } | |
end | |
describe Human do | |
its(:name) { should == 'Eric' } | |
end | |
# more then one subject use let and define subject in block | |
context 'poor human' do | |
let(:human) { Human.new(income: poor, clothes: [knackered]) } | |
let(:knackered) { Clothes.new(name: 'knackered') } | |
subject { human } | |
its (:clothes) { should include(knackered) } | |
it 'can wear its knackered clothes' do | |
human.wear(knackered).should == true | |
end | |
end | |
#newer RSpec allow you to combine the the subject and let line | |
subject(:human) { Human.new(income: poor, clothes: [knackered]) } | |
#Lazy evaluation and Let! - let does not create the object until the rest calls it, Let! creates it and puts it in the database | |
it "creates a human" { Human.count == 1 } # this would fail if the human was created with let but not Let! | |
#hooks to save duplication :each | |
before(:each) { method } | |
before(:all) { method } | |
after(:each) { method } | |
after(:all) {method } | |
#shared examples | |
spec/support/shared_examples_for_creatures.rb | |
shared_examples_for 'the living' do | |
it 'does have a pulse' do | |
subject.pulse.should == true | |
end | |
end | |
describe Human do | |
it_behaves_like 'the living' | |
end | |
describe Animal do | |
it_behaves_like 'the living' | |
end | |
#tags and filters | |
context 'test the things I am focus ed on', focus: true do | |
#command line, runs only tests with focus in them | |
rspec --tag focus spec/lib/human_spec.rb | |
#the opposite is also possible, ~filter out tests | |
context 'test the photo upload', slow: true do | |
# on the command line you can define which tags you want | |
rspec --tag ~slow spec/lib/human_spec.rb #skip slow examples | |
#mocking & stubbing | |
# stub - for replacing a method with code that returns a specifield result | |
# mock - a stub with an expectations that the methods gets called | |
context "#remove hunger" do | |
it "calls eat.food" do | |
human.should_receive(:eat) | |
human.not_hungry | |
end | |
it "sets status to full again" do | |
human.stub(:eat) | |
human.not_hungry | |
human.status.should == "full up" | |
end | |
end | |
class Human < ActiveRecord::Base | |
def locate | |
FindHuman.home_locator(self.home) | |
end | |
end | |
it "calls FindHuman.home_locator" do | |
FindHuman.should_receive(:home_locator).with(human.home) | |
human.locate | |
end | |
# above stubs the method + expection with correct param | |
# mock and return | |
class Human < ActiveRecord::Base | |
def locate | |
FindHuman.home_locator(self.home) | |
"{#loc[:latitude]}, #{loc[:longitude]}" | |
end | |
end | |
it "calls FindHuman.home_locator" do | |
FindHuman.should_receive(:home_locator).with(human.home) | |
.and_return{latitude: 2, longitude: 4} ) | |
human.locate | |
end | |
# above stubs the method + expectaion with correct param and return value | |
class Human < ActiveRecord::Base | |
def locate | |
FindHuman.home_locator(self.home) | |
"{#loc[:latitude]}, #{loc[:longitude]}" | |
end | |
end | |
it "calls FindHuman.home_locator" do | |
FindHuman.should_receive(:home_locator).with(human.home) | |
.and_return{latitude: 2, longitude: 4} ) | |
human.locate.should == "2, 4" | |
end | |
# stub - a double | |
it "calls FindHuman.home_locator" do | |
loc = stub(latitude: 2, longitude: 4) | |
FindHuman.stub(:home_locator).returns(loc) | |
human.locate_with_object.should == "2, 4" | |
end | |
# mailer | |
let(:human) { Human.create(email: '[email protected]') } | |
let(:human) { stub(email: [email protected]) } # does not call active record | |
target.should_receive(:function).once | |
.twice | |
.exactly(3).times | |
.at_least(2).times | |
.at_most(3).times | |
.any_number_of_times | |
# debugging tests: | |
# use 'byebug' Gem, add to Gemfile and bundle install | |
# insert the word byebug at the top of the it '' block | |
# use puts to output variables | |
# use sleep(30) to check the page | |
# use 'rails console' to understand the data that goes in and out | |
# good Resources: | |
e-book - http://everydayrails.com | |
webpage - http://betterspecs.org | |
Codeschool - $29 per month - has four courses - https://www.codeschool.com/courses/testing-with-rspec | |
Rails4 in Action - http://www.manning.com/bigg2/ | |
Railscast 158 - Factories - http://railscasts.com/episodes/158-factories-not-fixtures-revised | |
Railscast 275 - How I test - http://railscasts.com/episodes/275-how-i-test | |
Railscast 257 - Request Specs and Capybara - http://railscasts.com/episodes/275-how-i-test | |
webpage - http://railsadventures.wordpress.com/2013/09/25/11-steps-to-make-your-rspec-specs-awesome/ | |
webpage - http://gaslight.co/blog/6-ways-to-remove-pain-from-feature-testing-in-ruby-on-rails | |
# RSpec Maintainers: | |
http://www.andylindeman.com | |
http://myronmars.to/n/dev-blog | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment