SlideShare a Scribd company logo
rspec matchers
Zaharie Marius - 06-03-2015
1 / 9
1. Composable matchers
Example:
#background_worker_spec.rb
describeBackgroundWorkerdo
it'putsenqueuedjobsontothequeueinorder'do
worker=BackgroundWorker.new
worker.enqueue(:klass=>"Class1",:id=>37)
worker.enqueue(:klass=>"Class2",:id=>42)
expect(worker.queue).tomatch[
a_hash_including(:klass=>"Class1",:id=>37),
a_hash_including(:klass=>"Class2",:id=>42)
]
end
end
a_hash_includingis an alias for the includematcher.
2 / 9
Aliases
RSpec 3 provides one or more aliases for all the built-in matchers.
consistent phrasing ("a_[type of object][verb]ing")
so they are easy to guess:
a_string_starting_withfor start_with
a_string_includinga_collection_includinga_hash_includingaliases
of include
see a list of them in this gist
easier to read when used in compound expresions or composed
matchers
and also more readable failure mssages.
RSpec 3 made it easy to define an alias for some built-in matcher or even your
custom matchers. Here is the bit of code to define the a_string_starting_with
alias of start_with:
RSpec::Matchers.alias_matcher:a_string_starting_with,:start_with
3 / 9
What are these composable matchers good for?
They will save you from this ...
describe"GET/api/areas/:area_id/pscs"do
context"whengivenvaliddata"do
it"returnsthePSCSforgivenareainJSON"do
get"/api/areas/#{area.id}/pscs",
{access_token:access_token_for(user),level_id:area.default_level.id},
{'Accept'=>Mime::JSON}
expect(response.status).tobe(200)
expect(response.content_type).tobe(Mime::JSON)
json_response=json(response.body)
expect(json_response[:latitude]).to eq(area.location.point.latitude.to_f)
expect(json_response[:longitude]).to eq(area.location.point.longitude.to_f)
#otherlongexpectshere
expect(level_node[:previous_level][:level_id]).toeq(area.parkings_levels.order_by_lev
expect(level_node[:image][:url]).to eq(area.level_image(area.default_leve
pscs_latitudes=json_response[:pscs].map{|e|e[:pscs][:latitude]}
expect(pscs_latitudes).toinclude(area.pscs_on_level(area.default_level.id).first.poin
end
end
end
4 / 9
The solution
is to use the matchmatcher, which became in rspec 3 a kind of black hole for any rspec
matcher.
describe"GET/api/areas/:area_id/pscs"do
context"whengivenvaliddata"do
it"returnsthePSCSforgivenareainJSON"do
get"/api/areas/#{area.id}/pscs",
{level_id:area.default_level.id},
{
'Authorization'=>"Bearer#{access_token_for(user)}",
'Accept'=>Mime::JSON
}
expect(response).tohave_status(200).and_content_type(Mime::JSON)
json_response=json(response.body)
expect(json_response).tomatch(pscs_list_composed_matcher(area:area))
expect(json_response[:pscs]).tocontain_latitude(area.pscs_on_level(area.default_level
end
end
end
5 / 9
The object passed to matchis more like a big hash containing any rspec
matchers as values for his keys:
modulePscsHelpers
defpscs_list_composed_matcher(area:,current_level:nil,is_favorite:false)
current_level=area.default_level
{
latitude:area.location.point.latitude.to_f,
longitude:area.location.point.longitude.to_f,
is_favorite:is_favorite,
zoomLevel:(a_value>0),
level:current_level_matcher(area,current_level),
pscs:an_instance_of(Array)
}
end
defcurrent_level_matcher(area,current_level)
{
level_id:current_level.id,
name:current_level.name,
default_level:level_matcher(area.default_level),
next_level: level_matcher(area.levels.first),
previous_level:level_matcher(area.levels.last),
image:level_image_matcher(area,current_level)
}
end
#reusable
deflevel_matcher(level)
#...
end
deflevel_image_matcher(area,current_level)
#... 6 / 9
2. Custom matchers
2.1 How to:
RSpec::Matchers.define:contain_latitudedo|expected|
latitudes=[]
matchdo|actual|
latitudes=actual.collect{|item|item[:pscs][:latitude]}
latitudes.find{|lat|lat.to_s==expected.to_s}
end
failure_messagedo|actual|
"expectedthatpscs_listwithlatitudesn #{latitudes}nwouldcontainthe'#{expec
end
end
#anduseitlikethis:
expect(json_response[:pscs]).tocontain_latitude(45.4545)
#orusingacompoundexpression
expect(json_response[:pscs])
.tocontain_latitude(45.4545)
.andcontain_longitude(25.90)
7 / 9
2.2 Chained matchers with fluent interface
When you want something more expressive then .andor .orfrom previous
example
modulePscsHelpers
#scopedmatcherswiththePscsHelpersmodule
extendRSpec::Matchers::DSL
matcher:contain_a_latitude_bigger_thando|first|
latitudes=[]
matchdo|actual|
latitudes=actual.collect{|item|item[:pscs][:latitude]}
bigger=latitudes.find{|lat|lat>expected}
smaller=latitudes.find{|lat|lat<second}
bigger&&smaller
end
chain:but_smaller_thando|second|
@second=second
end
end
end
#andthefancyexpectationusingit
expect(response).tocontain_a_latitude_bigger_than(43).but_smaller_than(47)
8 / 9
Resources
RSpec 3 - Composable Matchers
List of RSpec 3 Aliases gist
Define Matcher
9 / 9

More Related Content

PDF
Benchmarking Perl Lightning Talk (NPW 2007)
PPTX
利用Init connect做mysql clients stat 用户审计
PPTX
Python Spell Checker
PDF
PDF
[1062BPY12001] Data analysis with R / April 26
PDF
JavaScript Fundamentals with Angular and Lodash
PPTX
Conditional Statementfinal PHP 02
PDF
Java script introducation & basics
 
Benchmarking Perl Lightning Talk (NPW 2007)
利用Init connect做mysql clients stat 用户审计
Python Spell Checker
[1062BPY12001] Data analysis with R / April 26
JavaScript Fundamentals with Angular and Lodash
Conditional Statementfinal PHP 02
Java script introducation & basics
 

What's hot (20)

DOCX
What are arrays in java script
DOCX
It6312 dbms lab-ex2
RTF
cs8project
PPT
JavaScript Functions
PDF
The art of readable code (ch1~ch4)
PPT
JavaScript Arrays
PPTX
Lecture no 3
PDF
Understanding Javascript Engine to Code Better
PDF
Ruby Programming Language
PDF
Lodash js
PPTX
Database security
PPT
Javascript built in String Functions
ODT
Logic Equations Resolver J Script
PPTX
JavaScript Proven Practises
PDF
Clojure functions midje
PDF
Java Cheat Sheet
DOCX
Java and xml
PDF
Python 3.x Dictionaries and Sets Cheatsheet
PDF
Chaining and function composition with lodash / underscore
What are arrays in java script
It6312 dbms lab-ex2
cs8project
JavaScript Functions
The art of readable code (ch1~ch4)
JavaScript Arrays
Lecture no 3
Understanding Javascript Engine to Code Better
Ruby Programming Language
Lodash js
Database security
Javascript built in String Functions
Logic Equations Resolver J Script
JavaScript Proven Practises
Clojure functions midje
Java Cheat Sheet
Java and xml
Python 3.x Dictionaries and Sets Cheatsheet
Chaining and function composition with lodash / underscore
Ad

Viewers also liked (20)

DOCX
Media Analysis of film opening: Media Language
PPT
Restaurant floor manager kpi
PPT
Project associate
PPT
Custom-Soft review system pune India
PPT
Disastermanagementppt 130128141146-phpapp02
PDF
Ark PC brochure
PPTX
1С-Битрикс "Разумная разработка интернет-магазина: функционал и сценарии работы"
PPTX
Tik Bab 1 kelas 9
PPTX
Presentación1 some any
DOCX
How to make kids grow taller
PPTX
Consumer protection act 1986 akosha
PPTX
Swede powerpoint
PDF
Rupicon 2014 useful design patterns in rails
PPTX
活動紹介2014ホームページ用
PDF
Portafolio final fichas de producto y oportunidades
PDF
Www.hotroddingsingles.com
PPTX
Jobs and classroom objects
PPTX
Model arcs (J. Keller)
PPTX
PDF
Professional Persona Project: GANA
Media Analysis of film opening: Media Language
Restaurant floor manager kpi
Project associate
Custom-Soft review system pune India
Disastermanagementppt 130128141146-phpapp02
Ark PC brochure
1С-Битрикс "Разумная разработка интернет-магазина: функционал и сценарии работы"
Tik Bab 1 kelas 9
Presentación1 some any
How to make kids grow taller
Consumer protection act 1986 akosha
Swede powerpoint
Rupicon 2014 useful design patterns in rails
活動紹介2014ホームページ用
Portafolio final fichas de producto y oportunidades
Www.hotroddingsingles.com
Jobs and classroom objects
Model arcs (J. Keller)
Professional Persona Project: GANA
Ad

Similar to RSpec matchers (20)

PDF
Metaprogramovanie #1
PDF
Basics of R programming for analytics [Autosaved] (1).pdf
PDF
(Greach 2015) Dsl'ing your Groovy
PDF
RubyEnRails2007 - Dr Nic Williams - DIY Syntax
PDF
Better rspec 進擊的 RSpec
DOCX
OPM Recipe designer notes
PDF
Testing Ruby with Rspec (a beginner's guide)
PPTX
tree-sitter-objc-slides.pptx
PPTX
Object oriented programming with python
PDF
Tuples All the Way Down
PPTX
MiamiJS - The Future of JavaScript
PPTX
Indexing documents
KEY
Why ruby
PDF
Hadoop Integration in Cassandra
PDF
Hello- I hope you are doing well- I am doing my project- which is Rans (1).pdf
PDF
Metaprogramming
PDF
Reproducibility with R
PDF
Introduction to ad-3.4, an automatic differentiation library in Haskell
PDF
Introduction to ad-3.4, an automatic differentiation library in Haskell
PPTX
Mongo DB REG EXP and Logical Operator.pptx
Metaprogramovanie #1
Basics of R programming for analytics [Autosaved] (1).pdf
(Greach 2015) Dsl'ing your Groovy
RubyEnRails2007 - Dr Nic Williams - DIY Syntax
Better rspec 進擊的 RSpec
OPM Recipe designer notes
Testing Ruby with Rspec (a beginner's guide)
tree-sitter-objc-slides.pptx
Object oriented programming with python
Tuples All the Way Down
MiamiJS - The Future of JavaScript
Indexing documents
Why ruby
Hadoop Integration in Cassandra
Hello- I hope you are doing well- I am doing my project- which is Rans (1).pdf
Metaprogramming
Reproducibility with R
Introduction to ad-3.4, an automatic differentiation library in Haskell
Introduction to ad-3.4, an automatic differentiation library in Haskell
Mongo DB REG EXP and Logical Operator.pptx

More from rupicon (9)

PDF
DIY Cartography
PDF
Dr. PostGIS or: How I Learned to Stop Worrying and Love the Docs
PDF
Are you tougher than a boy/girl scout?
PDF
Johnny Cache
PDF
U wont bleev wut dis code doez
PDF
Rupicon 2014 Action pack
PDF
Rupicon 2014 Single table inheritance
PDF
Rupicon 2014 solid
PDF
Rupicon 2014 caching
DIY Cartography
Dr. PostGIS or: How I Learned to Stop Worrying and Love the Docs
Are you tougher than a boy/girl scout?
Johnny Cache
U wont bleev wut dis code doez
Rupicon 2014 Action pack
Rupicon 2014 Single table inheritance
Rupicon 2014 solid
Rupicon 2014 caching

Recently uploaded (20)

PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
System and Network Administraation Chapter 3
PDF
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
PPTX
L1 - Introduction to python Backend.pptx
PPTX
Introduction to Artificial Intelligence
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
PDF
Designing Intelligence for the Shop Floor.pdf
PPTX
Odoo POS Development Services by CandidRoot Solutions
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PPTX
Reimagine Home Health with the Power of Agentic AI​
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PDF
Design an Analysis of Algorithms I-SECS-1021-03
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
How to Choose the Right IT Partner for Your Business in Malaysia
Internet Downloader Manager (IDM) Crack 6.42 Build 41
wealthsignaloriginal-com-DS-text-... (1).pdf
Operating system designcfffgfgggggggvggggggggg
System and Network Administraation Chapter 3
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
L1 - Introduction to python Backend.pptx
Introduction to Artificial Intelligence
Internet Downloader Manager (IDM) Crack 6.42 Build 42 Updates Latest 2025
Designing Intelligence for the Shop Floor.pdf
Odoo POS Development Services by CandidRoot Solutions
Upgrade and Innovation Strategies for SAP ERP Customers
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Reimagine Home Health with the Power of Agentic AI​
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Odoo Companies in India – Driving Business Transformation.pdf
Design an Analysis of Algorithms I-SECS-1021-03

RSpec matchers

  • 1. rspec matchers Zaharie Marius - 06-03-2015 1 / 9
  • 3. Aliases RSpec 3 provides one or more aliases for all the built-in matchers. consistent phrasing ("a_[type of object][verb]ing") so they are easy to guess: a_string_starting_withfor start_with a_string_includinga_collection_includinga_hash_includingaliases of include see a list of them in this gist easier to read when used in compound expresions or composed matchers and also more readable failure mssages. RSpec 3 made it easy to define an alias for some built-in matcher or even your custom matchers. Here is the bit of code to define the a_string_starting_with alias of start_with: RSpec::Matchers.alias_matcher:a_string_starting_with,:start_with 3 / 9
  • 4. What are these composable matchers good for? They will save you from this ... describe"GET/api/areas/:area_id/pscs"do context"whengivenvaliddata"do it"returnsthePSCSforgivenareainJSON"do get"/api/areas/#{area.id}/pscs", {access_token:access_token_for(user),level_id:area.default_level.id}, {'Accept'=>Mime::JSON} expect(response.status).tobe(200) expect(response.content_type).tobe(Mime::JSON) json_response=json(response.body) expect(json_response[:latitude]).to eq(area.location.point.latitude.to_f) expect(json_response[:longitude]).to eq(area.location.point.longitude.to_f) #otherlongexpectshere expect(level_node[:previous_level][:level_id]).toeq(area.parkings_levels.order_by_lev expect(level_node[:image][:url]).to eq(area.level_image(area.default_leve pscs_latitudes=json_response[:pscs].map{|e|e[:pscs][:latitude]} expect(pscs_latitudes).toinclude(area.pscs_on_level(area.default_level.id).first.poin end end end 4 / 9
  • 5. The solution is to use the matchmatcher, which became in rspec 3 a kind of black hole for any rspec matcher. describe"GET/api/areas/:area_id/pscs"do context"whengivenvaliddata"do it"returnsthePSCSforgivenareainJSON"do get"/api/areas/#{area.id}/pscs", {level_id:area.default_level.id}, { 'Authorization'=>"Bearer#{access_token_for(user)}", 'Accept'=>Mime::JSON } expect(response).tohave_status(200).and_content_type(Mime::JSON) json_response=json(response.body) expect(json_response).tomatch(pscs_list_composed_matcher(area:area)) expect(json_response[:pscs]).tocontain_latitude(area.pscs_on_level(area.default_level end end end 5 / 9
  • 6. The object passed to matchis more like a big hash containing any rspec matchers as values for his keys: modulePscsHelpers defpscs_list_composed_matcher(area:,current_level:nil,is_favorite:false) current_level=area.default_level { latitude:area.location.point.latitude.to_f, longitude:area.location.point.longitude.to_f, is_favorite:is_favorite, zoomLevel:(a_value>0), level:current_level_matcher(area,current_level), pscs:an_instance_of(Array) } end defcurrent_level_matcher(area,current_level) { level_id:current_level.id, name:current_level.name, default_level:level_matcher(area.default_level), next_level: level_matcher(area.levels.first), previous_level:level_matcher(area.levels.last), image:level_image_matcher(area,current_level) } end #reusable deflevel_matcher(level) #... end deflevel_image_matcher(area,current_level) #... 6 / 9
  • 7. 2. Custom matchers 2.1 How to: RSpec::Matchers.define:contain_latitudedo|expected| latitudes=[] matchdo|actual| latitudes=actual.collect{|item|item[:pscs][:latitude]} latitudes.find{|lat|lat.to_s==expected.to_s} end failure_messagedo|actual| "expectedthatpscs_listwithlatitudesn #{latitudes}nwouldcontainthe'#{expec end end #anduseitlikethis: expect(json_response[:pscs]).tocontain_latitude(45.4545) #orusingacompoundexpression expect(json_response[:pscs]) .tocontain_latitude(45.4545) .andcontain_longitude(25.90) 7 / 9
  • 8. 2.2 Chained matchers with fluent interface When you want something more expressive then .andor .orfrom previous example modulePscsHelpers #scopedmatcherswiththePscsHelpersmodule extendRSpec::Matchers::DSL matcher:contain_a_latitude_bigger_thando|first| latitudes=[] matchdo|actual| latitudes=actual.collect{|item|item[:pscs][:latitude]} bigger=latitudes.find{|lat|lat>expected} smaller=latitudes.find{|lat|lat<second} bigger&&smaller end chain:but_smaller_thando|second| @second=second end end end #andthefancyexpectationusingit expect(response).tocontain_a_latitude_bigger_than(43).but_smaller_than(47) 8 / 9
  • 9. Resources RSpec 3 - Composable Matchers List of RSpec 3 Aliases gist Define Matcher 9 / 9