Update: The issue below is now solved and it is possible to use multiple formatters with RSpec 2. Refer to it’s documentation how to do that.

I’ve started recently to upgrade WatirSplash to use RSpec 2. I thought that it will be as easy as walking in the park. I was wrong. As it turned out then i’m using RSpec unconventionally. This has caused me to create 6 brand new issues for rspec-core (part of them are already fixed and released with the new RSpec’s version thanks to the good work of David Chelimsky).

One of the features of WatirSplash is a custom HTML formatter which shows additional information for the failures like a screenshot of the browser and a html of the failing webpage. It has also links to all of the files created/downloaded during the test.

That custom formatter is used together with RSpec’s built in nested formatter (it is called as a documentation formatter in RSpec 2). That means if tests are executed then the progress is shown in the console and the html report is generated in the background. Test results in the console are meant for the faster feedback. Html report on the other hand is meant for the continuous integration machines and for the cases where additional information for the failure is needed.

In RSpec 1 it was possible to specify multiple formatters if the output stream was different - for example, you couldn’t use two formatters together which both wanted to use STDOUT for their outputting needs. To use multiple formatters together you’d just had to use –format switch to specify them:

spec --format nested --format html:output.html

The command above uses two built in formatters in RSpec 1 - nested and html. For all the formatters, having a different output from STDOUT, had to have specified output file with the syntax “:filename”. This approach allowed to use arbitrary count of different formatters at the same time.

With RSpec 2 things happen to be slightly different. Many parts of it have been rewritten. You can only use 1 (read: one) formatter at the same time by default (in version 2.1). At least from the outside. It is only possible to specify one formatter at a time with an output option:

rspec --format documentation --out output.txt

If you’d specify more than one –format switch to rspec command then the last one will be used.

Since i really wanted to use that feature then i had to look directly at the code itself.

One interesting class is a RSpec::Core::Configuration which deals with a.. err, configuration. At least two of the interesting methods there are reporter and formatter:

module RSpec module Core class Configuration def formatter @formatter ||= formatter_class.new(output) end def reporter @reporter ||= Reporter.new(formatter) end end end end

As it’s possible to see then an instance of a Reporter class is created with only one formatter which is determined by a formatter_class method, which returns a class for the ProgressFormatter by default.

On the other hand, when looking into the source code of the Reporter class then it’s possible to see that it’s responsible invoking methods in formatter classes. In plural:

module RSpec::Core class Reporter def initialize(*formatters) @formatters = formatters # ... end def notify(method, *args, &block) @formatters.each do |formatter| formatter.send method, *args, &block end end end end

In other words - Reporter class doesn’t care if it is initialized with only one or many formatter objects and it knows how to handle them all. This means that we might be able to use multiple formatters directly from the code!

I’ve created custom RSpec formatter before and it’s not much of a different with RSpec 2, but for the clarity’s sake let’s create one really simple and not much of an useful HtmlFormatter right now also:

require 'rspec/core/formatters/html_formatter' class MyCustomHtmlFormatter

We’re gonna use it with RSpec’s built in documentation formatter. To use multiple formatters with RSpec 2, let’s add this small code snippet to some file, which will be loaded before any specs. Let’s call it environment.rb for example:

require "my_custom_html_formatter" config = RSpec.configuration # we want to use colored output for the console, right? config.color_enabled = true documentation_formatter = config.send(:built_in_formatter, :documentation).new(config.output) custom_formatter = MyCustomHtmlFormatter.new(File.open("output.html", "w")) config.instance_variable_set(:@reporter, RSpec::Core::Reporter.new(documentation_formatter, custom_formatter))

Now make sure that the code will be loaded before any specs by adding a require statement into the RSpec’s option file called “.rspec”:

--require environment.rb

If executing `rspec spec` now from the command line then a colored documentation formatter will be seen on the console window and output.html file will be created with a HTML report also.

Unfortunately the solution above does not allow to change formatters from the command line nor with any “.rspec” files and needs to be done for every project separately. I’m not sure if there’s any good alternatives until possible native support of multiple formatters with RSpec 2. You may let me know in the comments if you have any better ideas for solving this problem.

There you have it - it is still possible to use multiple formatters in RSpec 2 if you really need it.