summaryrefslogtreecommitdiffstats
path: root/test/lib/spec/runner/formatter
diff options
context:
space:
mode:
authorluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2007-03-17 02:48:41 +0000
committerluke <luke@980ebf18-57e1-0310-9a29-db15c13687c0>2007-03-17 02:48:41 +0000
commitba23a5ac276e59fdda8186750c6d0fd2cfecdeac (patch)
tree1e14b25ade74ea52d8da2788ede9b12b507867e8 /test/lib/spec/runner/formatter
parent8ea6adaeb1e3d0aa6348c2a2c3a385d185372d06 (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.rb118
-rw-r--r--test/lib/spec/runner/formatter/html_formatter.rb219
-rw-r--r--test/lib/spec/runner/formatter/progress_bar_formatter.rb27
-rw-r--r--test/lib/spec/runner/formatter/rdoc_formatter.rb22
-rw-r--r--test/lib/spec/runner/formatter/specdoc_formatter.rb23
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, '&amp;').gsub(/\"/n, '&quot;').gsub(/>/n, '&gt;').gsub(/</n, '&lt;')
+ 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">&nbsp;</p>
+ <p id="totals">&nbsp;</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