diff options
| author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2007-03-17 02:48:41 +0000 |
|---|---|---|
| committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2007-03-17 02:48:41 +0000 |
| commit | ba23a5ac276e59fdda8186750c6d0fd2cfecdeac (patch) | |
| tree | 1e14b25ade74ea52d8da2788ede9b12b507867e8 /test/lib/spec/runner/formatter | |
| parent | 8ea6adaeb1e3d0aa6348c2a2c3a385d185372d06 (diff) | |
Adding spec libs, so we can use them some day
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@2283 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'test/lib/spec/runner/formatter')
| -rw-r--r-- | test/lib/spec/runner/formatter/base_text_formatter.rb | 118 | ||||
| -rw-r--r-- | test/lib/spec/runner/formatter/html_formatter.rb | 219 | ||||
| -rw-r--r-- | test/lib/spec/runner/formatter/progress_bar_formatter.rb | 27 | ||||
| -rw-r--r-- | test/lib/spec/runner/formatter/rdoc_formatter.rb | 22 | ||||
| -rw-r--r-- | test/lib/spec/runner/formatter/specdoc_formatter.rb | 23 |
5 files changed, 409 insertions, 0 deletions
diff --git a/test/lib/spec/runner/formatter/base_text_formatter.rb b/test/lib/spec/runner/formatter/base_text_formatter.rb new file mode 100644 index 000000000..31d1c3132 --- /dev/null +++ b/test/lib/spec/runner/formatter/base_text_formatter.rb @@ -0,0 +1,118 @@ +module Spec + module Runner + module Formatter + # Baseclass for text-based formatters. Can in fact be used for + # non-text based ones too - just ignore the +output+ constructor + # argument. + class BaseTextFormatter + def initialize(output, dry_run=false, colour=false) + @output = output + @dry_run = dry_run + @colour = colour + begin ; require 'Win32/Console/ANSI' if @colour && PLATFORM =~ /win32/ ; rescue LoadError ; raise "You must gem install win32console to use colour on Windows" ; end + end + + # This method is invoked before any specs are run, right after + # they have all been collected. This can be useful for special + # formatters that need to provide progress on feedback (graphical ones) + # + # This method will only be invoked once, and the next one to be invoked + # is #add_context + def start(spec_count) + end + + # This method is invoked at the beginning of the execution of each context. + # +name+ is the name of the context and +first+ is true if it is the + # first context - otherwise it's false. + # + # The next method to be invoked after this is #spec_started + def add_context(name, first) + end + + # This method is invoked right before a spec is executed. + # The next method to be invoked after this one is one of #spec_failed + # or #spec_passed. + def spec_started(name) + end + + # This method is invoked when a spec fails, i.e. an exception occurred + # inside it (such as a failed should or other exception). +name+ is the name + # of the specification. +counter+ is the sequence number of the failure + # (starting at 1) and +failure+ is the associated Failure object. + def spec_failed(name, counter, failure) + end + + # This method is invoked when a spec passes. +name+ is the name of the + # specification. + def spec_passed(name) + end + + # This method is invoked after all of the specs have executed. The next method + # to be invoked after this one is #dump_failure (once for each failed spec), + def start_dump + end + + # Dumps detailed information about a spec failure. + # This method is invoked for each failed spec after all specs have run. +counter+ is the sequence number + # of the associated spec. +failure+ is a Failure object, which contains detailed + # information about the failure. + def dump_failure(counter, failure) + @output.puts + @output.puts "#{counter.to_s})" + if(failure.expectation_not_met?) + @output.puts red(failure.header) + @output.puts red(failure.exception.message) + else + @output.puts magenta(failure.header) + @output.puts magenta(failure.exception.message) + end + @output.puts format_backtrace(failure.exception.backtrace) + STDOUT.flush + end + + # This method is invoked at the very end. + def dump_summary(duration, spec_count, failure_count) + return if @dry_run + @output.puts + @output.puts "Finished in #{duration} seconds" + @output.puts + summary = "#{spec_count} specification#{'s' unless spec_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}" + if failure_count == 0 + @output.puts green(summary) + else + @output.puts red(summary) + end + end + + def format_backtrace(backtrace) + return "" if backtrace.nil? + backtrace.map { |line| backtrace_line(line) }.join("\n") + end + + protected + + def backtrace_line(line) + line.sub(/\A([^:]+:\d+)$/, '\\1:') + end + + def colour(text, colour_code) + return text unless @colour && output_to_tty? + "#{colour_code}#{text}\e[0m" + end + + def output_to_tty? + begin + @output == Kernel || @output.tty? + rescue NoMethodError + false + end + end + + def red(text); colour(text, "\e[31m"); end + def green(text); colour(text, "\e[32m"); end + def magenta(text); colour(text, "\e[35m"); end + + end + end + end +end diff --git a/test/lib/spec/runner/formatter/html_formatter.rb b/test/lib/spec/runner/formatter/html_formatter.rb new file mode 100644 index 000000000..13b796581 --- /dev/null +++ b/test/lib/spec/runner/formatter/html_formatter.rb @@ -0,0 +1,219 @@ +module Spec + module Runner + module Formatter + class HtmlFormatter < BaseTextFormatter + attr_reader :current_spec_number, :current_context_number + + def initialize(output, dry_run=false, colour=false) + super + @current_spec_number = 0 + @current_context_number = 0 + end + + def start(spec_count) + @spec_count = spec_count + + @output.puts HEADER_1 + @output.puts extra_header_content unless extra_header_content.nil? + @output.puts HEADER_2 + STDOUT.flush + end + + def add_context(name, first) + @current_context_number += 1 + unless first + @output.puts " </dl>" + @output.puts "</div>" + end + @output.puts "<div class=\"context\">" + @output.puts " <dl>" + @output.puts " <dt id=\"context_#{@current_context_number}\">#{name}</dt>" + STDOUT.flush + end + + def start_dump + @output.puts " </dl>" + @output.puts "</div>" + STDOUT.flush + end + + def spec_started(name) + @current_spec_number += 1 + STDOUT.flush + end + + def spec_passed(name) + move_progress + @output.puts " <dd class=\"spec passed\"><span class=\"passed_spec_name\">#{escape(name)}</span></dd>" + STDOUT.flush + end + + def spec_failed(name, counter, failure) + @output.puts " <script type=\"text/javascript\">makeRed('header');</script>" + @output.puts " <script type=\"text/javascript\">makeRed('context_#{@current_context_number}');</script>" + move_progress + @output.puts " <dd class=\"spec failed\">" + @output.puts " <span class=\"failed_spec_name\">#{escape(name)}</span>" + @output.puts " <div class=\"failure\" id=\"failure_#{counter}\">" + @output.puts " <div class=\"message\"><pre>#{escape(failure.exception.message)}</pre></div>" unless failure.exception.nil? + @output.puts " <div class=\"backtrace\"><pre>#{format_backtrace(failure.exception.backtrace)}</pre></div>" unless failure.exception.nil? + @output.puts extra_failure_content unless extra_failure_content.nil? + @output.puts " </div>" + @output.puts " </dd>" + STDOUT.flush + end + + # Override this method if you wish to output extra HTML in the header + # + def extra_header_content + end + + # Override this method if you wish to output extra HTML for a failed spec. For example, you + # could output links to images or other files produced during the specs. + # + def extra_failure_content + end + + def move_progress + percent_done = @spec_count == 0 ? 100.0 : (@current_spec_number.to_f / @spec_count.to_f * 1000).to_i / 10.0 + @output.puts " <script type=\"text/javascript\">moveProgressBar('#{percent_done}');</script>" + end + + def escape(string) + string.gsub(/&/n, '&').gsub(/\"/n, '"').gsub(/>/n, '>').gsub(/</n, '<') + end + + def dump_failure(counter, failure) + end + + def dump_summary(duration, spec_count, failure_count) + if @dry_run + totals = "This was a dry-run" + else + totals = "#{spec_count} specification#{'s' unless spec_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}" + end + @output.puts "<script type=\"text/javascript\">document.getElementById('duration').innerHTML = \"Finished in <strong>#{duration} seconds</strong>\";</script>" + @output.puts "<script type=\"text/javascript\">document.getElementById('totals').innerHTML = \"#{totals}\";</script>" + @output.puts "</div>" + @output.puts "</body>" + @output.puts "</html>" + STDOUT.flush + end + + HEADER_1 = <<-EOF +<?xml version="1.0" encoding="iso-8859-1"?> +<!DOCTYPE html + PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head> + <title>RSpec results</title> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> + <meta http-equiv="Expires" content="-1" /> + <meta http-equiv="Pragma" content="no-cache" /> +EOF + + HEADER_2 = <<-EOF + <script type="text/javascript"> + function moveProgressBar(percentDone) { + document.getElementById("header").style.width = percentDone +"%"; + } + function makeRed(element_id) { + document.getElementById(element_id).style.background = '#C40D0D'; + } + </script> + <style type="text/css"> + body { + margin: 0; padding: 0; + background: #fff; + } + + #header { + background: #65C400; color: #fff; + } + + h1 { + margin: 0 0 10px; + padding: 10px; + font: bold 18px "Lucida Grande", Helvetica, sans-serif; + } + + #summary { + margin: 0; padding: 5px 10px; + font: bold 10px "Lucida Grande", Helvetica, sans-serif; + text-align: right; + position: absolute; + top: 0px; + right: 0px; + } + + #summary p { + margin: 0 0 2px; + } + + #summary #totals { + font-size: 14px; + } + + .context { + margin: 0 10px 5px; + background: #fff; + } + + dl { + margin: 0; padding: 0 0 5px; + font: normal 11px "Lucida Grande", Helvetica, sans-serif; + } + + dt { + padding: 3px; + background: #65C400; + color: #fff; + font-weight: bold; + } + + dd { + margin: 5px 0 5px 5px; + padding: 3px 3px 3px 18px; + } + + dd.spec.passed { + border-left: 5px solid #65C400; + border-bottom: 1px solid #65C400; + background: #DBFFB4; color: #3D7700; + } + + dd.spec.failed { + border-left: 5px solid #C20000; + border-bottom: 1px solid #C20000; + color: #C20000; background: #FFFBD3; + } + + div.backtrace { + color: #000; + font-size: 12px; + } + + a { + color: #BE5C00; + } + </style> +</head> +<body> + +<div id="header"> + <h1>RSpec Results</h1> + + <div id="summary"> + <p id="duration"> </p> + <p id="totals"> </p> + </div> +</div> + +<div id="results"> +EOF + end + end + end +end diff --git a/test/lib/spec/runner/formatter/progress_bar_formatter.rb b/test/lib/spec/runner/formatter/progress_bar_formatter.rb new file mode 100644 index 000000000..fe519d4d8 --- /dev/null +++ b/test/lib/spec/runner/formatter/progress_bar_formatter.rb @@ -0,0 +1,27 @@ +module Spec + module Runner + module Formatter + class ProgressBarFormatter < BaseTextFormatter + def add_context(name, first) + @output.puts if first + STDOUT.flush + end + + def spec_failed(name, counter, failure) + @output.print failure.expectation_not_met? ? red('F') : magenta('F') + STDOUT.flush + end + + def spec_passed(name) + @output.print green('.') + STDOUT.flush + end + + def start_dump + @output.puts + STDOUT.flush + end + end + end + end +end
\ No newline at end of file diff --git a/test/lib/spec/runner/formatter/rdoc_formatter.rb b/test/lib/spec/runner/formatter/rdoc_formatter.rb new file mode 100644 index 000000000..eae55c3ea --- /dev/null +++ b/test/lib/spec/runner/formatter/rdoc_formatter.rb @@ -0,0 +1,22 @@ +module Spec + module Runner + module Formatter + class RdocFormatter < BaseTextFormatter + def add_context(name, first) + @output.print "# #{name}\n" + STDOUT.flush + end + + def spec_passed(name) + @output.print "# * #{name}\n" + STDOUT.flush + end + + def spec_failed(name, counter, failure) + @output.print "# * #{name} [#{counter} - FAILED]\n" + STDOUT.flush + end + end + end + end +end
\ No newline at end of file diff --git a/test/lib/spec/runner/formatter/specdoc_formatter.rb b/test/lib/spec/runner/formatter/specdoc_formatter.rb new file mode 100644 index 000000000..67b4312bf --- /dev/null +++ b/test/lib/spec/runner/formatter/specdoc_formatter.rb @@ -0,0 +1,23 @@ +module Spec + module Runner + module Formatter + class SpecdocFormatter < BaseTextFormatter + def add_context(name, first) + @output.puts + @output.puts name + STDOUT.flush + end + + def spec_failed(name, counter, failure) + @output.puts failure.expectation_not_met? ? red("- #{name} (FAILED - #{counter})") : magenta("- #{name} (ERROR - #{counter})") + STDOUT.flush + end + + def spec_passed(name) + @output.print green("- #{name}\n") + STDOUT.flush + end + end + end + end +end
\ No newline at end of file |
