Skip to content

Instantly share code, notes, and snippets.

@afair
Last active August 29, 2015 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save afair/31619ddbd8492fd7be39 to your computer and use it in GitHub Desktop.
Save afair/31619ddbd8492fd7be39 to your computer and use it in GitHub Desktop.
Notes from: Straight Up RSpec 3 - a neat Ruby BDD Tool
################################################################################
# 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