--- /dev/null
+module Spec
+ module Runner
+ class Reporter
+ attr_reader :options, :example_groups
+
+ def initialize(options)
+ @options = options
+ @options.reporter = self
+ clear
+ end
+
+ def add_example_group(example_group)
+ formatters.each do |f|
+ f.add_example_group(example_group)
+ end
+ example_groups << example_group
+ end
+
+ def example_started(example)
+ formatters.each{|f| f.example_started(example)}
+ end
+
+ def example_finished(example, error=nil)
+ @examples << example
+
+ if error.nil?
+ example_passed(example)
+ elsif Spec::Example::ExamplePendingError === error
+ example_pending(example_groups.last, example, error.message)
+ else
+ example_failed(example, error)
+ end
+ end
+
+ def failure(example, error)
+ backtrace_tweaker.tweak_backtrace(error)
+ example_name = "#{example_groups.last.description} #{example.description}"
+ failure = Failure.new(example_name, error)
+ @failures << failure
+ formatters.each do |f|
+ f.example_failed(example, @failures.length, failure)
+ end
+ end
+ alias_method :example_failed, :failure
+
+ def start(number_of_examples)
+ clear
+ @start_time = Time.new
+ formatters.each{|f| f.start(number_of_examples)}
+ end
+
+ def end
+ @end_time = Time.new
+ end
+
+ # Dumps the summary and returns the total number of failures
+ def dump
+ formatters.each{|f| f.start_dump}
+ dump_pending
+ dump_failures
+ formatters.each do |f|
+ f.dump_summary(duration, @examples.length, @failures.length, @pending_count)
+ f.close
+ end
+ @failures.length
+ end
+
+ private
+
+ def formatters
+ @options.formatters
+ end
+
+ def backtrace_tweaker
+ @options.backtrace_tweaker
+ end
+
+ def clear
+ @example_groups = []
+ @failures = []
+ @pending_count = 0
+ @examples = []
+ @start_time = nil
+ @end_time = nil
+ end
+
+ def dump_failures
+ return if @failures.empty?
+ @failures.inject(1) do |index, failure|
+ formatters.each{|f| f.dump_failure(index, failure)}
+ index + 1
+ end
+ end
+ def dump_pending
+ formatters.each{|f| f.dump_pending}
+ end
+
+ def duration
+ return @end_time - @start_time unless (@end_time.nil? or @start_time.nil?)
+ return "0.0"
+ end
+
+ def example_passed(example)
+ formatters.each{|f| f.example_passed(example)}
+ end
+
+ def example_pending(example_group, example, message="Not Yet Implemented")
+ @pending_count += 1
+ formatters.each do |f|
+ f.example_pending(example_group.description, example, message)
+ end
+ end
+
+ class Failure
+ attr_reader :exception
+
+ def initialize(example_name, exception)
+ @example_name = example_name
+ @exception = exception
+ end
+
+ def header
+ if expectation_not_met?
+ "'#{@example_name}' FAILED"
+ elsif pending_fixed?
+ "'#{@example_name}' FIXED"
+ else
+ "#{@exception.class.name} in '#{@example_name}'"
+ end
+ end
+
+ def pending_fixed?
+ @exception.is_a?(Spec::Example::PendingExampleFixedError)
+ end
+
+ def expectation_not_met?
+ @exception.is_a?(Spec::Expectations::ExpectationNotMetError)
+ end
+
+ end
+ end
+ end
+end