Code Reading: RSpec Output Formatting
As I mentioned in my post on “shared examples”, each example group generated by RSpec is passed a reporter object when it’s run. Reporters notify listeners of events like
#example_failed. Listeners can then print output based on these events.
That’s the gist of how output formatting in RSpec works; this post examines it in slightly more detail.
Specifying a formatter on the command line
We can specify which formatter we’d like RSpec to use by providing the
--format option on the command line, like so:
$ rspec --format p # => Uses RSpec::Core::Formatters::ProgressFormatter
$ rspec # => Uses the default (RSpec::Core::Formatters::ProgressFormatter)
$ rspec --format j # => Uses RSpec::Core::Formatters::JsonFormatter
$ rspec --format MyCustomFormatter # => Uses MyCustomFormatter class. Attempts to require the file "my_custom_formatter.rb" if not loaded already.
When we execute
rspec, an instance of
RSpec::Core::CommandLine is initialized with the options passed via the command line. During the initialization, the formatter argument is added to a collection of formatters maintained by the
RSpec.configuration singleton. The singleton is also initialized with a reporter, an instance of
RSpec::Core::Reporter. Each formatter is registered as a listener of the reporter.
Notifying formatters of events
The spec files are then loaded and their example groups are run. Each example group is passed a reference to the reporter singleton when executed. Example groups and their examples notify the reporter whenever they begin, end, fail, etc.
The reporter passes these messages along to its listeners: the formatters specified in the previous section. The formatters then determine what to output; whether that be text, JSON, or some other representation.
Simple, right? RSpec makes it seem deceptively so because of how well it’s architected. In a future post, I’ll cover Kiwi’s implementation of reporting. Stay tuned!
Note: If you found this post on RSpec useful, consider helping me write more of these posts, by supporting me on Patreon.