From a8222b1d4fe9103327928b5cad7fe0e0a4fcf7fd Mon Sep 17 00:00:00 2001 From: jbranchaud Date: Thu, 23 Mar 2017 21:33:35 -0500 Subject: [PATCH] Add Chaining Multiple RSpec Change Matchers as a ruby til --- README.md | 3 +- ...chaining-multiple-rspec-change-matchers.md | 41 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 ruby/chaining-multiple-rspec-change-matchers.md diff --git a/README.md b/README.md index ef8c000..b01b19e 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ variety of languages and technologies. These are things that don't really warrant a full blog post. These are mostly things I learn by pairing with smart people at [Hashrocket](http://hashrocket.com/). -_516 TILs and counting..._ +_517 TILs and counting..._ --- @@ -362,6 +362,7 @@ _516 TILs and counting..._ - [Are They All True?](ruby/are-they-all-true.md) - [Assoc For Hashes](ruby/assoc-for-hashes.md) - [Block Comments](ruby/block-comments.md) +- [Chaining Multiple RSpec Change Matchers](ruby/chaining-multiple-rspec-change-matchers.md) - [Colorful Output With MiniTest](ruby/colorful-output-with-minitest.md) - [Comparing Class Hierarchy Relationships](ruby/comparing-class-hierarchy-relationships.md) - [Comparing Arrays In RSpec](ruby/comparing-arrays-in-rspec.md) diff --git a/ruby/chaining-multiple-rspec-change-matchers.md b/ruby/chaining-multiple-rspec-change-matchers.md new file mode 100644 index 0000000..263532e --- /dev/null +++ b/ruby/chaining-multiple-rspec-change-matchers.md @@ -0,0 +1,41 @@ +# Chaining Multiple RSpec Change Matchers + +It can be handy to use RSpec's `change` matchers to determine if some method +or process creates a new record. + +```ruby +expect{ Registration.create(attrs) }.to change{ User.count }.by(1) +``` + +But what if we are testing a method that creates a couple different records +in the system? + +RSpec allows us to chain together `change` matchers with `and`. Consider +this additional contrived example. + +```ruby +expect { + Project.generate(attrs) +}.to change{ Project.count }.by(1).and \ + change{ User.count }.by(1) +``` + +In addition to keeping our tests tight and concise, this approach gives +some pretty nice output on failure. + +If we were just beginning our implementation with a failing test, we'd see a +multi-part failure like the following. + +```ruby +Failure/Error: + expect { + Project.generate(attrs) + }.to change{ Project.count }.by(1).and \ + change{ User.count }.by(1) + + expected result to have changed by 1, but was changed by 0 + + ...and: + + expected result to have changed by 1, but was changed by 0 +```