Slide 1

Slide 1 text

RSpec functions Kenta Murata 2012.09.21 12೥9݄21೔༵ۚ೔

Slide 2

Slide 2 text

Only about 2.11.x 12೥9݄21೔༵ۚ೔

Slide 3

Slide 3 text

Core 12೥9݄21೔༵ۚ೔

Slide 4

Slide 4 text

Terms require ‘spec_helper’ describe Account do context ‘when the subject is an admin’ do subject { described_class.make(:admin => true) } it { should be_admin } end context ‘when the subject is not an admin’ do subject { described_class.make(:admin => false) } it { should_not be_admin } end end 12೥9݄21೔༵ۚ೔

Slide 5

Slide 5 text

Terms require ‘spec_helper’ describe Account do context ‘when the subject is an admin’ do subject { described_class.make(:admin => true) } it { should be_admin } end context ‘when the subject is not an admin’ do subject { described_class.make(:admin => false) } it { should_not be_admin } end end Example group 12೥9݄21೔༵ۚ೔

Slide 6

Slide 6 text

Terms require ‘spec_helper’ describe Account do context ‘when the subject is an admin’ do subject { described_class.make(:admin => true) } it { should be_admin } end context ‘when the subject is not an admin’ do subject { described_class.make(:admin => false) } it { should_not be_admin } end end Example group Example group 12೥9݄21೔༵ۚ೔

Slide 7

Slide 7 text

Terms require ‘spec_helper’ describe Account do context ‘when the subject is an admin’ do subject { described_class.make(:admin => true) } it { should be_admin } end context ‘when the subject is not an admin’ do subject { described_class.make(:admin => false) } it { should_not be_admin } end end Code example Code example 12೥9݄21೔༵ۚ೔

Slide 8

Slide 8 text

Terms require ‘spec_helper’ describe Account do context ‘when the subject is an admin’ do subject { described_class.make(:admin => true) } it { should be_admin } end context ‘when the subject is not an admin’ do subject { described_class.make(:admin => false) } it { should_not be_admin } end end Expectation Expectation 12೥9݄21೔༵ۚ೔

Slide 9

Slide 9 text

Terms require ‘spec_helper’ describe Account do context ‘when the subject is an admin’ do subject { described_class.make(:admin => true) } it { should be_admin } end context ‘when the subject is not an admin’ do subject { described_class.make(:admin => false) } it { should_not be_admin } end end Spec file 12೥9݄21೔༵ۚ೔

Slide 10

Slide 10 text

Terms BDD TDD Expectations Assertions Code examples Tests Example groups Test cases 12೥9݄21೔༵ۚ೔

Slide 11

Slide 11 text

Shared example shared_examples “a collection” do # assumes the described class can be initialized with an Array let(:collection) { described_class.new([7, 2, 4]) } context “initialized with 3 items” do it “says it has three items” do collection.size.should eq(3) end end describe “#include?” do context “with an item that is in the collection” do it “returns true” do collection.should be_include(7) end end end end 12೥9݄21೔༵ۚ೔

Slide 12

Slide 12 text

Using shared example require ‘set’ describe Array do it_behaves_like “a collection” end describe Set do it_behaves_like “a collection” end 12೥9݄21೔༵ۚ೔

Slide 13

Slide 13 text

Shared example with parameters shared_examples “a measurable object” do |measurement, measurement_methods| measurement_methods.each do |measurement_method| describe “##{measurement_method}“ do it “should return #{measurement}” do subject.send(measurement_method).should eq(measurement) end end end end describe Array, “with 3 items” do subject { [1, 2, 3] } it_behaves_like “a measurable object”, 3, [:size, :length] end describe String, “of 6 ASCII-chars” do subject { “FooBar” } it_behaves_like “a measurable object”, 6, [:bytesize, :size, :length] end 12೥9݄21೔༵ۚ೔

Slide 14

Slide 14 text

Shared example with parameters shared_examples “a measurable object” do |measurement, measurement_methods| measurement_methods.each do |measurement_method| describe “##{measurement_method}“ do it “should return #{measurement}” do subject.send(measurement_method).should eq(measurement) end end end end describe Array, “with 3 items” do subject { [1, 2, 3] } it_behaves_like “a measurable object”, 3, [:size, :length] end describe String, “of 6 ASCII-chars” do subject { “FooBar” } it_behaves_like “a measurable object”, 6, [:bytesize, :size, :length] end 12೥9݄21೔༵ۚ೔

Slide 15

Slide 15 text

Shared example with parameters shared_examples “a measurable object” do |measurement, measurement_methods| measurement_methods.each do |measurement_method| describe “##{measurement_method}“ do it “should return #{measurement}” do subject.send(measurement_method).should eq(measurement) end end end end describe Array, “with 3 items” do subject { [1, 2, 3] } it_behaves_like “a measurable object”, 3, [:size, :length] end describe String, “of 6 ASCII-chars” do subject { “FooBar” } it_behaves_like “a measurable object”, 6, [:bytesize, :size, :length] end 12೥9݄21೔༵ۚ೔

Slide 16

Slide 16 text

shared context shared_context “shared stuff” do before { @some_var = :some_value } def shared_method “it works” end let(:shared_let) { { ‘arbitrary’ => ‘object’ } } subject { ‘this is the subject’ } end 12೥9݄21೔༵ۚ೔

Slide 17

Slide 17 text

include shared context describe ‘group that includes a shared context using ‘include_context’” do include_context ‘shared stuff’ specify ‘access things defined in the included shared context’ do shared_method.should eq(‘it works’) shared_let[‘arbitrary’].should eq(‘object’) @some_var.should be(:some_value) subject.should eq(‘this is the subject’) end end 12೥9݄21೔༵ۚ೔

Slide 18

Slide 18 text

shared context with metadata shared_context “shared stuff”, :foo => :bar do before { @some_var = :some_value } def shared_method “it works” end let(:shared_let) { { ‘arbitrary’ => ‘object’ } } subject { ‘this is the subject’ } end 12೥9݄21೔༵ۚ೔

Slide 19

Slide 19 text

shared context with metadata shared_context “shared stuff”, :foo => :bar do before { @some_var = :some_value } def shared_method “it works” end let(:shared_let) { { ‘arbitrary’ => ‘object’ } } subject { ‘this is the subject’ } end 12೥9݄21೔༵ۚ೔

Slide 20

Slide 20 text

include shared context by metadata describe ‘group that includes a shared context by metadata”, :foo => :bar do specify ‘access things defined in the included shared context’ do shared_method.should eq(‘it works’) shared_let[‘arbitrary’].should eq(‘object’) @some_var.should be(:some_value) subject.should eq(‘this is the subject’) end end 12೥9݄21೔༵ۚ೔

Slide 21

Slide 21 text

include shared context by metadata describe ‘group that includes a shared context by metadata”, :foo => :bar do specify ‘access things defined in the included shared context’ do shared_method.should eq(‘it works’) shared_let[‘arbitrary’].should eq(‘object’) @some_var.should be(:some_value) subject.should eq(‘this is the subject’) end end 12೥9݄21೔༵ۚ೔

Slide 22

Slide 22 text

pending with condition pending(“reason”, :if => true) { expectations } # this is pending pending(“reason”, :if => false) { expectations } # this is not pending pending(“reason”, :unless => true) { expectations } # this is not pending pending(“reason”, :unless => false) { expectations } # this is pending 12೥9݄21೔༵ۚ೔

Slide 23

Slide 23 text

around hook describe “...” do around(:each) do |ex| before preparation ex.run ensure finalization end end ... end 12೥9݄21೔༵ۚ೔

Slide 24

Slide 24 text

example usage of around hook # examples are run in temporary directries around(:each) do |ex| Dir.mktmpdir do |tmpdir| Dir.chdir tmpdir do ex.run end end end 12೥9݄21೔༵ۚ೔

Slide 25

Slide 25 text

example usage of around hook # with Timecop around(:each) do |ex| Timecop.travel(Time.local(2012, 7, 20, 12, 34, 56)) do ex.run end end 12೥9݄21೔༵ۚ೔

Slide 26

Slide 26 text

let and let! • helper method for memoization • let(:name) { ... } • is not called automatically • let!(:name) { ... } • is called automatically in a before hook 12೥9݄21೔༵ۚ೔

Slide 27

Slide 27 text

metadata describe “with metadata”, :foo, :bar, :baz => 42 do it ‘has `:fast => true` metadata’ do example.metadata[:fast].should eq(true) end it ‘has `:bar => true` metadata’ do example.metadata[:bar].should eq(true) end it ‘has `:baz => 42` metadata’ do example.metadata[:baz].should eq(42) end it ‘has `:hoge => true` metadata’, :hoge do example.metadata[:hoge].should eq(true) end end 12೥9݄21೔༵ۚ೔

Slide 28

Slide 28 text

metadata describe “with metadata”, :foo, :bar, :baz => 42 do it ‘has `:fast => true` metadata’ do example.metadata[:fast].should eq(true) end it ‘has `:bar => true` metadata’ do example.metadata[:bar].should eq(true) end it ‘has `:baz => 42` metadata’ do example.metadata[:baz].should eq(42) end it ‘has `:hoge => true` metadata’, :hoge do example.metadata[:hoge].should eq(true) end end 12೥9݄21೔༵ۚ೔

Slide 29

Slide 29 text

:focus • If examples with :focus metadata, rspec evaluates only these examples. 12೥9݄21೔༵ۚ೔

Slide 30

Slide 30 text

fail fast • Use fail_fast option to tell RSpec to abort the run on first failure. 12೥9݄21೔༵ۚ೔

Slide 31

Slide 31 text

fail fast # write the following configuration in spec_helper.rb RSpec.configure do |config| config.fail_fast = true end # or use --fail-fast command line option $ rspec --fail-fast 12೥9݄21೔༵ۚ೔

Slide 32

Slide 32 text

Expectations 12೥9݄21೔༵ۚ೔

Slide 33

Slide 33 text

The basic structure •actual.should matcher(expected) •actual.should_not matcher(expected) 12೥9݄21೔༵ۚ೔

Slide 34

Slide 34 text

Built-in matchers 12೥9݄21೔༵ۚ೔

Slide 35

Slide 35 text

identity actual.should be(expected) it is same as: (actual.equal? expected).should be_true 12೥9݄21೔༵ۚ೔

Slide 36

Slide 36 text

equivalence actual.should eq(expected) it is same as: (actual == expected).should be_true actual.should eql(expected) it is same as: (actual.eql? expected).should be_true actual.should equal(expected) it is same as: (actual.equal? expected).should be_true 12೥9݄21೔༵ۚ೔

Slide 37

Slide 37 text

Comparisons actual.should be > expected actual.should be >= expected actual.should be < expected actual.should be <= expected actual.should =~ /expression/ actual.should match(/expression/) actual.should be_within(delta).of(expected) it is same as: (actual - expected).abs.should be <= delta 12೥9݄21೔༵ۚ೔

Slide 38

Slide 38 text

errors and throws expect { ... }.to raise_error expect { ... }.to raise_error(ExceptionClass) expect { ... }.to raise_error(/pattern matches to message/) expect { ... }.to raise_error(ExcpetionClass, /pattern/) expect { ... }.to throw_symbol expect { ... }.to throw_symbol(:symbol) expect { ... }.to throw_symbol(:symbol, value) 12೥9݄21೔༵ۚ೔

Slide 39

Slide 39 text

predicates actual.should be_xxx # maps to actual.xxx? actual.should have_xxx(:arg) # maps to actual.has_xxx?(:arg) e.g.) [].should be_empty? {:foo => :bar}.should have_key(:foo) 12೥9݄21೔༵ۚ೔

Slide 40

Slide 40 text

collection membership [1, 2, 3].should include(1) [1, 2, 3].should include(1, 2) {:a => :b}.should include(:a => :b) “this string”.should include(“is str”) (1..10).should cover(3) # only >1.9 12೥9݄21೔༵ۚ೔

Slide 41

Slide 41 text

yield module Foo def self.foo(*args) yield *args end def self.bar(*args) end end expect {|blk| Foo.foo(1, &blk) }.to yield_control expect {|blk| Foo.bar(1, &blk) }.not_to yield_control 12೥9݄21೔༵ۚ೔

Slide 42

Slide 42 text

yield with args module Foo def self.foo(*args) yield *args end def self.bar(*args) end def self.baz(*args) yield end end expect {|blk| Foo.foo(1, &blk) }.to yield_with_args expect {|blk| Foo.bar(1, &blk) }.not_to yield_with_args expect {|blk| Foo.baz(1, &blk) }.not_to yield_with_args 12೥9݄21೔༵ۚ೔

Slide 43

Slide 43 text

yield with args module Foo def self.foo(*args) yield *args end def self.bar(*args) end def self.baz(*args) yield end end expect {|blk| Foo.foo(‘abc’, ‘xyz’, &blk) }.to yield_with_args(‘abc’, ‘xyz’) expect {|blk| Foo.foo(‘abc’, ‘xyz’, &blk) }.to yield_with_args(/bc/, /xy/) Use == or === to compare arguments 12೥9݄21೔༵ۚ೔

Slide 44

Slide 44 text

yield with no args module Foo def self.foo(*args) yield *args end def self.bar(*args) end def self.baz(*args) yield end end expect {|blk| Foo.foo(‘abc’, ‘xyz’, &blk) }.not_to yield_with_no_args expect {|blk| Foo.bar(‘abc’, ‘xyz’, &blk) }.not_to yield_with_no_args expect {|blk| Foo.baz(‘abc’, ‘xyz’, &blk) }.to yield_with_no_args 12೥9݄21೔༵ۚ೔

Slide 45

Slide 45 text

yield successive args expect {|blk| [1, 2, 3].each(&blk) }.to yield_successive_args(1, 2, 3) expect {|blk| [1, 2, 3].each(&blk) }.to yield_successive_args(Fixnum, Fixnum, Fixnum) expect {|blk| {:a => 1, :b => 2}.each(&blk) }.to yield_successive_args([:a, 1], [:b, 2]) expect {|blk| {:a => 1, :b => 2}.each(&blk) }.to yield_successive_args( lambda {|x| x.last == 1 }, lambda {|x| x.last == 2 } ) Use == or === to compare arguments 12೥9݄21೔༵ۚ೔

Slide 46

Slide 46 text

Custom matcher RSpec::Matchers.define :be_a_multiple_of do |expected| match do |actual| actual % expected == 0 end failure_message_for_should do |actual| “expected that #{actual} would be a multiple of #{expected}” end failure_message_for_should_not do |actual| “expected that #{actual} wouldn’t be a multiple of #{expected}” end description do “be multiple of #{expected}” # used for auto-generated description end end 12೥9݄21೔༵ۚ೔

Slide 47

Slide 47 text

Custom matcher describe 9 do it { should be_a_multiple_of(3) } # pass end describe 9 do it { should_not be_a_multiple_of(4) } # pass end describe 9 do it { should be_a_multiple_of(4) } #=> “expected that 9 would be a multiple of 4” end describe 9 do it { should_not be_a_multiple_of(3) } #=> “expected that 9 wouldn’t be a multiple of 3” end 12೥9݄21೔༵ۚ೔

Slide 48

Slide 48 text

References • https://www.relishapp.com/rspec/rspec-core/ v/2-11/docs • https://www.relishapp.com/rspec/rspec- expectations/v/2-11/docs • https://www.relishapp.com/rspec/rspec- mocks/v/2-11/docs • https://www.relishapp.com/rspec/rspec-rails/ v/2-11/docs 12೥9݄21೔༵ۚ೔