Skip to content

Commit

Permalink
support multiple formatters
Browse files Browse the repository at this point in the history
- Closes rspec#213.
  • Loading branch information
dchelimsky committed Dec 31, 2010
1 parent 801e7bc commit a5f9ffd
Show file tree
Hide file tree
Showing 16 changed files with 256 additions and 111 deletions.
1 change: 1 addition & 0 deletions History.markdown
Expand Up @@ -9,6 +9,7 @@
(Clifford Heath)
* HTML Formatter _finally_ properly displays nested groups (Jarmo Pertman)
* apply hook filtering to examples as well as groups (Myron Marston)
* support multiple formatters, each with their own output

* Bug fixes
* send debugger warning message to $stdout if RSpec.configuration.error_stream
Expand Down
6 changes: 6 additions & 0 deletions features/command_line/README.md
@@ -0,0 +1,6 @@
The `rspec` command comes with several options you can use to customize RSpec's
behavior, including output formats, filtering examples, etc.

For a full list of options, run the `rspec` command with the `--help` flag:

$ rspec --help
2 changes: 1 addition & 1 deletion features/command_line/configure.feature
@@ -1,4 +1,4 @@
Feature: configure
Feature: --configure option

Use the --configure option on the command line to generate configuration
files.
Expand Down
6 changes: 3 additions & 3 deletions features/command_line/example_name_option.feature
@@ -1,13 +1,13 @@
Feature: example name option
Feature: --example option

Use the --example (or -e) option to filter the examples to be run by name.
Use the --example (or -e) option to filter examples by name.

The argument is compiled to a Ruby Regexp, and matched against the full
description of the example, which is the concatenation of descriptions of the
group (including any nested groups) and the example.

This allows you to run a single uniquely named example, all examples with
similar names, all the example in a uniquely named group, etc, etc.
similar names, all the examples in a uniquely named group, etc, etc.

Background:
Given a file named "first_spec.rb" with:
Expand Down
73 changes: 73 additions & 0 deletions features/command_line/format_option.feature
@@ -0,0 +1,73 @@
Feature: --formatt option

Use the --format option to tell RSpec how to format the output.

RSpec ships with a few formatters built in. By default, it uses the progress
formatter, which generates output like this:

....F.....*.....

A '.' represents a passing example, 'F' is failing, and '*' is pending.

To see the documentation strings passed to each describe(), context(), and it()
method, use the documentation formatter:

$ rspec spec --format documentation

You can also specify an output target (STDOUT by default) by appending a
filename to the argument:

$ rspec spec --format documentation:rspec.output.txt

Background:
Given a file named "example_spec.rb" with:
"""
describe "something" do
it "does something that passes" do
5.should eq(5)
end
it "does something that fails" do
5.should eq(4)
end
it "does something that is pending", :pending => true do
5.should be > 3
end
end
"""

Scenario: progress bar format (default)
When I run "rspec example_spec.rb"
Then the output should contain ".F*"

Scenario: documentation format
When I run "rspec example_spec.rb --format documentation"
Then the output should contain:
"""
something
does something that passes
does something that fails (FAILED - 1)
does something that is pending (PENDING: Not Yet Implemented)
"""

Scenario: documentation format saved to a file
When I run "rspec example_spec.rb --format documentation --out rspec.txt"
Then the file "rspec.txt" should contain:
"""
something
does something that passes
does something that fails (FAILED - 1)
does something that is pending (PENDING: Not Yet Implemented)
"""

Scenario: multiple formats
When I run "rspec example_spec.rb --format progress --format documentation --out rspec.txt"
Then the output should contain ".F*"
And the file "rspec.txt" should contain:
"""
something
does something that passes
does something that fails (FAILED - 1)
does something that is pending (PENDING: Not Yet Implemented)
"""
2 changes: 1 addition & 1 deletion features/command_line/line_number_appended_to_path.feature
Expand Up @@ -2,7 +2,7 @@ Feature: line number appended to file path

To run a single example or group, you can append the line number to the path, e.g.

rspec path/to/example_spec.rb:37
rspec path/to/example_spec.rb:37

Background:
Given a file named "example_spec.rb" with:
Expand Down
4 changes: 2 additions & 2 deletions features/command_line/line_number_option.feature
@@ -1,8 +1,8 @@
Feature: line number option
Feature: --line option

To run a single example or group, you can use the --line option:

rspec path/to/example_spec.rb --line 37
rspec path/to/example_spec.rb --line 37

Scenario: standard examples
Given a file named "example_spec.rb" with:
Expand Down
14 changes: 7 additions & 7 deletions features/command_line/tag.feature
@@ -1,18 +1,18 @@
Feature: tag option
Feature: --tag option

Use the --tag (or -t) option to filter the examples to be run by tag.
Use the --tag (or -t) option to filter the examples by tags.

The tag can be a simple name or a name:value pair. In the first case,
examples with :name => true will be filtered. In the second case, examples
with :name => value will be filtered, where value is always a string.
In both cases, name is converted to a symbol.
with :name => value will be filtered, where value is always a string. In
both cases, name is converted to a symbol.

Tags can also be used to exclude examples by adding a ~ before the tag.
For example ~tag will exclude all examples marked with :tag => true and
Tags can also be used to exclude examples by adding a ~ before the tag. For
example ~tag will exclude all examples marked with :tag => true and
~tag:value will exclude all examples marked with :tag => value.

To be compatible with the Cucumber syntax, tags can optionally start with
a @, that will be ignored.
an @ symbol, which will be ignored.

Background:
Given a file named "tagged_spec.rb" with:
Expand Down
28 changes: 2 additions & 26 deletions features/configuration/read_options_from_file.feature
Expand Up @@ -42,7 +42,7 @@ Feature: read command line configuration options from files
"""
describe "formatter set in custom options file" do
it "sets formatter" do
RSpec.configuration.formatter.
RSpec.configuration.formatters.first.
should be_a(RSpec::Core::Formatters::DocumentationFormatter)
end
end
Expand Down Expand Up @@ -70,30 +70,6 @@ Feature: read command line configuration options from files
When I run "rspec spec/example_spec.rb --options my.options"
Then the output should contain "1 example, 0 failures"

Scenario: formatter set in RSpec.configure overrides .rspec
Given a file named ".rspec" with:
"""
--format progress
"""
And a file named "spec/spec_helper.rb" with:
"""
RSpec.configure {|c| c.formatter = 'documentation'}
"""
And a file named "spec/example_spec.rb" with:
"""
require "spec_helper"
describe "formatter" do
context "when set with RSpec.configure and in spec.opts" do
it "takes the value set in spec.opts" do
RSpec.configuration.formatter.should be_an(RSpec::Core::Formatters::DocumentationFormatter)
end
end
end
"""
When I run "rspec ./spec/example_spec.rb"
Then the output should contain "1 example, 0 failures"

Scenario: using ERB in .rspec
Given a file named ".rspec" with:
"""
Expand All @@ -103,7 +79,7 @@ Feature: read command line configuration options from files
"""
describe "formatter" do
it "is set to documentation" do
RSpec.configuration.formatter.should be_an(RSpec::Core::Formatters::DocumentationFormatter)
RSpec.configuration.formatters.first.should be_an(RSpec::Core::Formatters::DocumentationFormatter)
end
end
"""
Expand Down
4 changes: 4 additions & 0 deletions features/step_definitions/additional_cli_steps.rb
Expand Up @@ -14,3 +14,7 @@
Then %q{the output should contain "0 failures"}
Then %q{the exit status should be 0}
end

Then /^the file "([^"]*)" should contain:$/ do |file, partial_content|
check_file_content(file, partial_content, true)
end
33 changes: 19 additions & 14 deletions lib/rspec/core/configuration.rb
Expand Up @@ -263,28 +263,33 @@ def full_description=(description)
filter_run({ :full_description => /#{description}/ }, true)
end

attr_writer :formatter_class

def formatter_class
@formatter_class ||= begin
require 'rspec/core/formatters/progress_formatter'
RSpec::Core::Formatters::ProgressFormatter
end
end

def formatter=(formatter_to_use)
self.formatter_class =
def add_formatter(formatter_to_use, output=nil)
formatter_class =
built_in_formatter(formatter_to_use) ||
custom_formatter(formatter_to_use) ||
(raise ArgumentError, "Formatter '#{formatter_to_use}' unknown - maybe you meant 'documentation' or 'progress'?.")

formatters << formatter_class.new(output || self.output)
end

def formatter
@formatter ||= formatter_class.new(output)
alias_method :formatter=, :add_formatter

def formatters
@formatters ||= []
end

def reporter
@reporter ||= Reporter.new(formatter)
@reporter ||= begin
add_formatter('progress') if formatters.empty?
Reporter.new(*formatters)
end
end

def default_formatter
@default_formatter ||= begin
require 'rspec/core/formatters/progress_formatter'
RSpec::Core::Formatters::ProgressFormatter.new(output)
end
end

def files_or_directories_to_run=(*files)
Expand Down
15 changes: 14 additions & 1 deletion lib/rspec/core/configuration_options.rb
Expand Up @@ -18,9 +18,15 @@ def configure(config)
keys = options.keys
keys.unshift(:requires) if keys.delete(:requires)
keys.unshift(:libs) if keys.delete(:libs)
formatters = options[:formatters] if keys.delete(:formatters)
keys.each do |key|
config.send("#{key}=", options[key]) if config.respond_to?("#{key}=")
end
if formatters
formatters.each do |pair|
config.add_formatter(*pair)
end
end
end

def drb_argv
Expand All @@ -30,10 +36,17 @@ def drb_argv
argv << "--backtrace" if options[:full_backtrace]
argv << "--tty" if options[:tty]
argv << "--fail-fast" if options[:fail_fast]
argv << "--format" << options[:formatter] if options[:formatter]
argv << "--line_number" << options[:line_number] if options[:line_number]
argv << "--options" << options[:custom_options_file] if options[:custom_options_file]
argv << "--example" << options[:full_description].source if options[:full_description]
if options[:formatters]
options[:formatters].each do |pair|
argv << "--format" << pair.shift
unless pair.empty?
argv << "--out" << pair.shift
end
end
end
(options[:libs] || []).each do |path|
argv << "-I" << path
end
Expand Down
18 changes: 12 additions & 6 deletions lib/rspec/core/option_parser.rb
Expand Up @@ -47,12 +47,18 @@ def parser(options)
' [d]ocumentation (group and example names)',
' [h]tml',
' [t]extmate',
' custom formatter class name') do |o|
options[:formatter] = o
end

parser.on('-o', '--out FILE', 'output to a file instead of STDOUT') do |o|
options[:output_stream] = File.open(o,'w')
' custom formatter class name') do |f|
options[:formatters] ||= []
options[:formatters] << [f]
end

parser.on('-o', '--out FILE',
'Write output to a file instead of STDOUT. This option applies',
'to the previously specified --format, or the default format if',
'no format is specified.'
) do |o|
options[:formatters] ||= [['progress']]
options[:formatters].last << File.open(o,'w')
end

parser.on_tail('-h', '--help', "You're looking at it.") do
Expand Down

0 comments on commit a5f9ffd

Please sign in to comment.