Last active
August 29, 2015 14:04
-
-
Save afair/31619ddbd8492fd7be39 to your computer and use it in GitHub Desktop.
Notes from: Straight Up RSpec 3 - a neat Ruby BDD Tool
This file contains hidden or 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
################################################################################ | |
# Notes from: Straight Up RSpec 3 - a neat Ruby BDD Tool | |
#------------------------------------------------------------------------------- | |
# From: http://www.slideshare.net/gsterndale/straight-up-rspec-3 | |
# By: Greg Sterndale | |
################################################################################ | |
# .rspec | |
# lib/… | |
# spec/spec_helper.rb | |
# spec/support/matchers/drink.rb | |
# spec/martini_spec.rb | |
# spec_helper.rb | |
require 'barkeep' | |
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|file| require file } | |
################################################################################ | |
# .rspec | |
# | |
# --color | |
# --warnings | |
# --require spec_helper .rspec | |
# .rspec-local | |
# | |
# —-format documentation | |
# --backtrace .rspec-local | |
################################################################################ | |
# $ rspec spec/martini_spec.rb:15:22 | |
# | |
# $ rspec --format documentation | |
# | |
# $ rspec --fail-fast | |
# | |
# $ rspec --tag js:true | |
# | |
# $ rspec --profile | |
# Top 10 slowest examples (0.00226 seconds, 57.2% of total time): | |
# Martini with a mixer #ingredients should include "vermouth" 0.00058 seconds ./spec/martini_spec.rb:15 | |
# InitializeWithAttrsSpec with attributes #pages should eq 123 0.00052 seconds ./spec/initialize_with_attrs_spec.rb:16 … | |
# | |
# $ rspec --order random | |
# Randomized with seed 63958 | |
# | |
# $ rspec --order random:63958 | |
################################################################################ | |
describe "Martini" do | |
it "should have ingredients", :focus do | |
expect(martini).to respond_to(:ingredients) | |
end | |
end | |
describe "Martini" do | |
fit "should have ingredients" do | |
expect(martini).to respond_to(:ingredients) | |
end | |
end # fit | |
describe "Martini" do | |
it "should have ingredients", :skip do | |
expect(martini).to respond_to(:ingredients) | |
end | |
end | |
describe "Martini" do | |
xit "should have ingredients" do | |
expect(martini).to respond_to(:ingredients) | |
end | |
end | |
describe "Martini" do | |
pending "should have price" do | |
expect(@martini).to be_pricey | |
end | |
end | |
################################################################################ | |
RSpec.configure do |config| | |
config.include MyMartiniMatchers config.include ModelHelpers, :type => :model | |
end | |
describe Martini, :type => :model do | |
end | |
RSpec.configure do |c| | |
c.before(:suite) {} # once | |
c.before(:context) {} # once before each group | |
c.before(:example) {} # once before each example | |
c.after(:example) {} # once after each example | |
c.after(:context) {} # once after each group | |
c.after(:suite) {} # once run before each example of type :model | |
config.before(:example, :type => :model) {} | |
end # RSpec.configure | |
RSpec.configure do |c| | |
c.filter_run focus: true | |
c.run_all_when_everything_filtered = true | |
end | |
describe "thing" do | |
it "does something interesting", :focus do | |
# .... | |
end | |
end | |
# Check ruby version (useful in gems) | |
RSpec.configure do |c| | |
c.exclusion_filter = { :ruby => lambda { |version| (RUBY_VERSION.to_s =~ /^#{version.to_s}/) }} | |
end | |
describe "something" do | |
it "does something", :ruby => 1.8 do | |
# .... | |
end | |
it "does something", :ruby => 2.1 do | |
# .... | |
end | |
end | |
# Exclusion | |
describe "Barkeep::Martini" do | |
before do | |
@martini = Barkeep::Martini.new | |
end | |
it "should have an attribute named booze" do | |
@martini.should respond_to(:booze) | |
@martini.should respond_to(:booze=) | |
end | |
it "should have an attribute named garnish" do | |
@martini.should respond_to(:garnish) | |
@martini.should respond_to(:garnish=) | |
end | |
end | |
describe "Barkeep::Martini" do | |
before do | |
@martini = Barkeep::Martini.new | |
end | |
it "should have an attribute named booze" do | |
expect(@martini).to respond_to(:booze) | |
expect(@martini).to respond_to(:booze=) | |
end | |
it "should have an attribute named garnish" do | |
expect(@martini).to respond_to(:garnish) | |
expect(@martini).to respond_to(:garnish=) | |
end | |
end | |
################################################################################ | |
module AttributeMatchers | |
Spec::Matchers.define :have_attribute do |name| | |
match do |target| | |
getter = name.to_sym | |
setter = (name.to_s + "=").to_sym | |
target.respond_to?(getter) && target.respond_to?(setter) | |
end | |
end | |
end # Custom Matcher | |
describe "Barkeep::Martini" do | |
include AttributeMatchers | |
before do | |
@martini = Barkeep::Martini.new | |
end | |
it "should have an attribute named booze" do | |
expect(@martini).to have_attribute(:booze) | |
end | |
it "should have an attribute named garnish" do | |
expect(@martini).to have_attribute(:garnish) | |
end | |
end | |
describe "Barkeep::Martini" do | |
include AttributeMatchers | |
subject { Barkeep::Martini.new } | |
it "should have an attribute named booze" do | |
expect(subject).to have_attribute(:booze) | |
end | |
it "should have an attribute named garnish" do | |
expect(subject).to have_attribute(:garnish) | |
end | |
end # subject() | |
describe "Barkeep::Martini" do | |
include AttributeMatchers | |
subject(:martini) { Barkeep::Martini.new } | |
it "should have an attribute named booze" do | |
expect(martini).to have_attribute(:booze) | |
end | |
it "should have an attribute named garnish" do | |
expect(martini).to have_attribute(:garnish) | |
end | |
end # Named subject() | |
describe "Barkeep::Martini" do | |
include AttributeMatchers | |
subject { Barkeep::Martini.new } | |
it "should have an attribute named booze" do | |
is_expected.to have_attribute(:booze) | |
end | |
it "should have an attribute named garnish" do | |
is_expected.to have_attribute(:garnish) | |
end | |
end # Implicit subject() | |
describe "Barkeep::Martini" do | |
include AttributeMatchers | |
subject { Barkeep::Martini.new } | |
it { is_expected.to have_attribute(:booze) } | |
it { is_expected.to have_attribute(:garnish) } | |
end # DRY Messages | |
describe Barkeep::Martini do | |
include AttributeMatchers | |
it { is_expected.to have_attribute(:booze) } | |
it { is_expected.to have_attribute(:garnish) } | |
end # Derived subject() | |
module AttributeMatchers | |
end | |
################################################################################ | |
RSpec.configure do |config| | |
config.include AttributeMatchers | |
end #config.include() | |
describe Barkeep::Martini do | |
it { is_expected.to have_attribute(:booze) } | |
it { is_expected.to have_attribute(:garnish) } | |
end # config.include() | |
describe "Barkeep::Martini" do | |
before do | |
@martini = Barkeep::Martini.new | |
end | |
it "should have an attribute named booze" do | |
@martini.should respond_to(:booze) | |
@martini.should respond_to(:booze=) | |
end | |
it "should have an attribute named garnish" do | |
@martini.should respond_to(:garnish) | |
@martini.should respond_to(:garnish=) | |
end | |
end # Original Martini 2.X Spec | |
describe Barkeep::Martini do | |
it { is_expected.to have_attribute(:booze) } | |
it { is_expected.to have_attribute(:garnish) } | |
end # Refactored Martini 3.0 Spec | |
describe Barkeep::Whiskey do | |
it { is_expected.to have_attribute(:booze) } | |
it { is_expected.to have_attribute(:glass) } | |
end # New Whiskey Spec | |
describe Barkeep::Martini do | |
it { is_expected.to have_attribute(:booze) } | |
it { is_expected.to have_attribute(:glass) } | |
it { is_expected.to have_attribute(:garnish) } | |
end # Additions to Martini Spec | |
shared_examples_for "a drink" do | |
it { is_expected.to have_attribute(:booze) } | |
it { is_expected.to have_attribute(:glass) } | |
end # Shared Example Group | |
describe Barkeep::Whiskey do | |
it_behaves_like "a drink" | |
end # Whiskey Spec | |
describe Barkeep::Whiskey do | |
include_examples "a drink" | |
end # Whiskey Spec | |
describe Barkeep::Martini do | |
it_behaves_like "a drink" | |
it { is_expected.to have_attribute(:garnish) } | |
end # Martini Spec | |
shared_examples_for "a drink" do |ingredients| | |
it { is_expected.to have_attribute(:booze) } | |
it { is_expected.to have_attribute(:glass) } | |
describe "#ingredients" do | |
subject { super().ingredients } | |
it { is_expected.to be_a Array } | |
it { is_expected to include(*ingredients) } | |
end | |
end # Whiskey & Martini #ingredients | |
describe Barkeep::Martini do | |
it_behaves_like "a drink", "vodka" | |
it { is_expected.to have_attribute(:garnish) } | |
end # Martini Spec | |
describe Barkeep::Martini do | |
it_behaves_like "a drink" | |
it { is_expected.to have_attribute(:garnish) } | |
it { is_expected.to have_attribute(:mixer) } | |
context "with a mixer" do | |
before do | |
@mixer = 'vermouth' | |
subject.mixer = @mixer | |
end | |
it "should include mixer in ingredients" do | |
expect(subject.ingredients).to include @mixer | |
end | |
end | |
end #context() | |
describe Barkeep::Martini do | |
it_behaves_like "a drink" | |
it { is_expected.to have_attribute(:garnish) } | |
it { is_expected.to have_attribute(:mixer) } | |
context "with a mixer" do | |
let(:mixer) { 'vermouth' } | |
before { subject.mixer = mixer } | |
it "should include mixer in ingredients" do | |
expect(subject.ingredients).to include mixer | |
end | |
end | |
end # let() | |
describe Barkeep::Martini do | |
it_behaves_like "a drink" | |
it { is_expected.to have_attribute(:garnish) } | |
it { is_expected.to have_attribute(:mixer) } | |
context "with a mixer" do | |
let(:mixer) { 'vermouth' } | |
before { subject.mixer = mixer } | |
its(:ingredients) { is_expected.to include mixer } | |
end | |
end # its() | |
describe Barkeep::Martini do | |
it_behaves_like "a drink" | |
it { is_expected.to have_attribute(:garnish) } | |
it { is_expected.to have_attribute(:mixer) } | |
end | |
describe Barkeep::Martini, ".new with mixer" do | |
let(:mixer) { 'vermouth' } | |
subject { Barkeep::Martini.new(mixer: mixer) } | |
its(:ingredients) { is_expected.to include mixer } | |
end # its() | |
describe Barkeep::Martini, ".new with mixer" do | |
let(:mixer) { 'vermouth' } | |
subject { Barkeep::Martini.new(:mixer => mixer) } | |
its(:ingredients) { is_expected.to include mixer } | |
its(:ingredients) { is_expected.to have(1).items } | |
end # have() | |
describe Barkeep::Martini, ".new with mixer" do | |
let(:mixer) { 'vermouth' } | |
subject { Barkeep::Martini.new(:mixer => mixer) } | |
its(:ingredients) { is_expected.to include mixer } | |
it { is_expected.to have(1).ingredients } | |
end # have() | |
describe Barkeep::Martini, ".dirty" do | |
let(:martini) { Barkeep::Martini.dirty } | |
subject { martini.ingredients } | |
it { is_expected.to include 'juice', 'vodka', 'olives', 'vermouth' } | |
it { is_expected.to contain_exactly 'vodka', 'vermouth', 'juice', 'olives' } | |
end # Array Matchers | |
describe Barkeep::Martini, ".dirty" do | |
let(:martini) { Barkeep::Martini.dirty } | |
subject { martini.ingredients } | |
it { is_expected.to start_with 'vodka' } | |
it { is_expected.to end_with 'olives' } | |
end # Array Matchers | |
describe Barkeep::Martini, ".dirty" do | |
let(:martini) { Barkeep::Martini.dirty } | |
subject { martini.ingredients } | |
it { is_expected.to all be_a(String) } | |
it { is_expected.to all start_with(/^w/) } | |
end # Array Matchers | |
describe Barkeep::Martini, ".dirty" do | |
let(:martini) { Barkeep::Martini.dirty } | |
subject { martini.ingredients } | |
it { is_expected.to all be_a(String) & start_with(/^w/) } | |
end # Compound Matchers | |
describe Barkeep::Martini, ".dirty" do | |
let(:martini) { Barkeep::Martini.dirty } | |
subject { martini.ingredients } | |
it { is_expected.to match [ start_with(/^w/), match(/olives?/) ] } | |
end # Composable Matchers | |
describe Barkeep::Martini, ".dirty" do | |
let(:martini) { Barkeep::Martini.dirty } | |
subject { martini.ingredients } | |
it { is_expected.to match [ a_string_starting_with(/^w/), a_string_matching(/olives?/) ] } | |
end # Composable Matchers | |
describe Terminal, "#printer" do | |
let(:epson) { stub "Espon 5000" } | |
let(:terminal) { Terminal.new(:ip => "1.1.1.1") } | |
subject { terminal.printer } | |
before do | |
Printer.stub(:by_ip).and_return(epson) | |
end | |
it { should eq epson } | |
end | |
################################################################################ | |
# RSpec 2.X doubles | |
describe Terminal, "#printer" do | |
let(:epson) { double "Espon 5000" } | |
let(:terminal) { Terminal.new(:ip => "1.1.1.1") } | |
subject { terminal.printer } | |
before do | |
allow(Printer).to receive_messages(by_ip: epson) | |
end | |
it { is_expected.to eq epson } | |
end | |
#RSpec 3.0 doubles | |
describe Terminal, "#printer" do | |
let(:epson) { double "Espon 5000" } | |
let(:terminal) { Terminal.new(:ip => "1.1.1.1") } | |
subject { terminal.printer } | |
before do | |
allow(Printer).to receive_messages(by_ID: epson) | |
end | |
it { is_expected.to eq epson } | |
end | |
#Double checking™ | |
describe Terminal, "#printer" do | |
let(:epson) { stub "Espon 5000" } | |
let(:terminal) { Terminal.new(:ip => "1.1.1.1") } | |
subject { terminal.printer } | |
before do | |
Printer.should_receive(:by_ip).with("1.1.1.1").and_return(epson) | |
end | |
it { should eq epson } | |
end # RSpec 2.X message expectation | |
describe Terminal, "#printer" do | |
let(:epson) { double "Espon 5000" } | |
let(:terminal) { Terminal.new(:ip => "1.1.1.1") } | |
before do | |
allow(Printer).to receive_messages(by_ip: epson) | |
end | |
subject! { terminal.printer } | |
it { is_expected.to eq epson } | |
it "finds printer by IP" do | |
expect(Printer).to have_received(:by_ip).with("1.1.1.1") | |
end | |
end | |
describe User, ".admin_names" do | |
let(:admin) { User.create!(:admin => true, :first => "Clark", :last => "Kent")} | |
let(:avg_joe) { User.create!(:admin => false, :first => "Joe", :last => "Shmo")} | |
subject { admin_names } | |
it { should include "Clark Kent" } | |
it { should_not include "Joe Shmo" } | |
end # let() gotcha | |
describe User, ".admin_names" do | |
let(:admin) { User.create!(:admin => true, :first => "Clark", :last => "Kent")} | |
let(:avg_joe) { User.create!(:admin => false, :first => "Joe", :last => "Shmo")} | |
subject { User.admin_names } | |
before { admin && avg_joe } | |
it { should include "Clark Kent" } | |
it { should_not include "Joe Shmo" } | |
end # let() work-around | |
describe User, ".admin_names" do | |
let!(:admin) { User.create!(:admin => true, :first => "Clark", :last => "Kent")} | |
let!(:avg_joe) { User.create!(:admin => false, :first => "Joe", :last => "Shmo")} | |
subject { User.admin_names } | |
it { should include "Clark Kent" } | |
it { should_not include "Joe Shmo" } | |
end # let!() | |
# RSpec 3.0 message expectation | |
# Links | |
# Collection Matchers: github.com/rspec/rspec-collection_matchers | |
# RSpec Rails: | |
# github.com/rspec/rspec-rails | |
# ActiveModel mocks: | |
# github.com/rspec/rspec-activemodel-mocks Libraries | |
# Step-by-step upgrade instructions: | |
# relishapp.com/rspec/docs/upgrade | |
# RDoc: | |
# rubydoc.info/github/rspec/rspec-expectations | |
# Features as documentation: relishapp.com/rspec Documentation | |
# Transpec, the RSpec syntax conversion tool: | |
# yujinakayama.me/transpec/ | |
# Myron Marston’s blog: | |
# myronmars.to Resources | |
# CHEERS | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment