Code Reading: Shared Examples in RSpec
In the first post
of this series, we examined shared examples in RSpec, what problems they
attempt to solve, and how to use them. This post is the second in a series on
shared examples in RSpec and Kiwi. All of the implementation details discussed
are accompanied by a link to the corresponding source code in
This post takes approximately 6 minutes to read, and it covers:
- How RSpec builds and runs example groups
- How RSpec registers and replays shared examples
Readers familiar with invoking RSpec to run a test suite will get the most out of this post.
RSpec uses two singletons to store examples and shared examples:
- Example and example groups like
describeblocks are stored in
- Shared examples are stored in
#it_behaves_like method is executed, the shared example in the
registry is retrieved and executed as a normal example group would be.
Building example groups
All sorts of setup
is executed when a user runs the
One step of this setup loads the spec files to be executed. In order to do so,
the aptly named
The method does exactly what it advertises: it calls the Ruby
#load on each spec
causing the code within these files to be executed.
Spec files contain RSpec DSL like
it. These return one of two
it "does something"are instances of
describe Thingare instances of a subclass of
As they are created, each
with the delightfully named singleton
which maintains an array of example
to execute. Each example group is associated with a set of examples and holds a
reference to any child example groups it may contain. For example, consider the
following spec file:
# burrito_spec.rb describe "burrito" do it "is delicious" do end describe "just how delicious" do it "is so very delicious" end describe "spiciness" do end end
ExampleGroup holds a reference to 1
Example and 2 child
ExampleGroup objects. In order to run these groups,
over its list of example groups and calls their
An aside on custom formatting
ExampleGroup#runtakes an instance of
RSpec::Core::Reporteras an argument. This class maintains an array of
#listenerswhich are expected to respond to methods such as
#example_failed. This is the key to RSpec's extensible output formatting system. Kiwi could borrow this technique to address issue #306, which specifically requests custom formatting.
Shared example groups
Shared example groups are stored in a registry separate from normal example
groups: the singleton object
maintains a hash of shared
using the shared example name as a
Shared examples are registered by using the
in your spec file. This method stores the block of code associated with the
shared example in the registry.
Later, when each example group is run by
methods encountered during execution cause a lookup to the corresponding
shared example group in the
the block of code mapped to that key is
In this sense,
#it_behaves_like acts like a placeholder for a shared example
This concludes our source code reading of the implementation of shared examples in RSpec. The next post in this series will detail a corresponding implementation in Kiwi.
If you're interested in learning more about RSpec internals, check out "Chapter 16: Extending RSpec" in The RSpec Book: Behaviour-Driven Development with RSpec, Cucumber, and Friends.
Note: If you found this post on RSpec useful, consider helping me write more of these posts, by supporting me on Patreon.