Skip to content

Commit

Permalink
- Prepare for 1.0 release; last set of changes in current svn location
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.caldersphere.net/svn/main/ci_reporter@64 b03c2d0b-2f10-0410-a2f9-fc8001506dfa
  • Loading branch information
nicksieger committed Feb 15, 2007
1 parent 9c52870 commit bfdcd21
Show file tree
Hide file tree
Showing 14 changed files with 150 additions and 24 deletions.
3 changes: 3 additions & 0 deletions History.txt
@@ -0,0 +1,3 @@
== 1.0

Initial Release.
41 changes: 41 additions & 0 deletions README.txt
@@ -0,0 +1,41 @@
CI::Reporter is an add-on to Test::Unit and RSpec that allows you to generate
XML reports of your test and/or spec runs. The resulting files can be read by
a continuous integration system that understands Ant's JUnit report XML
format, thus allowing your CI system to track test/spec successes and
failures.

== Installation

CI::Reporter is available as a gem. To install the gem, use the usual gem command:

gem install ci_reporter

To use CI::Reporter as a Rails plugin, first install the gem, and then install the plugin as follows:

script/plugin install http://svn.caldersphere.net/svn/main/plugins/ci_reporter

== Usage

CI::Reporter works best with projects that use a +Rakefile+ along with the standard <code>Rake::TestTask</code> or <code>Spec::Rake::SpecTask</code> tasks for running tests or specs, respectively. In this fashion, it hooks into <code>Test::Unit</code> or +RSpec+ using environment variables recognized by these custom tasks to inject the CI::Reporter code into the test or spec runs. If you're using the Rails plugin, step 1 is unnecessary; skip to step 2.

1. To use CI::Reporter, simply add the following lines to your Rakefile:

require 'rubygems'
gem 'ci_reporter'
require 'ci/reporter/rake/rspec' # use this if you're using RSpec
require 'ci/reporter/rake/test_unit' # use this if you're using Test::Unit

2. Next, either modify your Rakefile to make the <code>ci:setup:rspec</code> or <code>ci:setup:testunit</code> task a dependency of your test tasks, or include them on the Rake command-line before the name of the task that runs the tests or specs.

rake ci:setup:testunit test

== Advanced Usage

If for some reason you can't use the above technique to inject CI::Reporter, you'll have to do one of these:

1. If you're using <code>Test::Unit</code>, ensure the <code>ci/reporter/rake/test_unit_loader.rb</code> file is loaded or required at some point before the tests are run.
2. If you're using +RSpec+, you'll need to pass the following arguments to the +spec+ command:
--require GEM_PATH/lib/ci/reporter/rake/rspec_loader
--format CI::Reporter::RSpec

There's a bit of a chicken and egg problem because rubygems needs to be loaded before you can require any CI::Reporter files. If you cringe hard-coding a full path to a specific version of the gem, you can also copy the +rspec_loader+ file into your project and require it directly -- the contents are version-agnostic and are not likely to change in future releases.
29 changes: 28 additions & 1 deletion Rakefile
@@ -1,7 +1,34 @@
require 'spec/rake/spectask'
require 'hoe'

MANIFEST = FileList["History.txt", "Manifest.txt", "README.txt", "Rakefile",
"lib/**/*.rb", "spec/**/*.rb", "tasks/**/*.rake"]

Hoe.new("ci_reporter", "1.0") do |p|
p.rubyforge_name = "caldersphere"
p.url = "http://rubyforge.org/projects/caldersphere"
p.author = "Nick Sieger"
p.email = "nick@nicksieger.com"
p.summary = "CI::Reporter allows you to generate reams of XML for use with continuous integration systems."
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
p.description = p.paragraphs_of('README.txt', 0..1).join("\n\n")
p.extra_deps.reject!{|d| d.first == "hoe"}
p.test_globs = ["spec/**/*_spec.rb"]
end.spec.files = MANIFEST

# Hoe insists on setting task :default => :test
# !@#$ no easy way to empty the default list of prerequisites
Rake::Task['default'].send :instance_variable_set, "@prerequisites", FileList[]

task :default => :spec

Spec::Rake::SpecTask.new do |t|
t.spec_opts = ["--diff", "unified"]
end
end

# Automated manifest
task :manifest do
File.open("Manifest.txt", "w") {|f| MANIFEST.each {|n| f << "#{n}\n"} }
end

task :package => :manifest
9 changes: 9 additions & 0 deletions lib/ci/reporter/rake/rspec.rb
@@ -0,0 +1,9 @@
namespace :ci do
namespace :setup do
task :rspec do
rm_rf ENV["CI_REPORTS"] || "spec/reports"
ENV["RSPECOPTS"] = ["--require", "#{File.dirname(__FILE__)}/rspec_loader.rb",
"--format", "CI::Reporter::RSpec"].join(" ")
end
end
end
7 changes: 7 additions & 0 deletions lib/ci/reporter/rake/rspec_loader.rb
@@ -0,0 +1,7 @@
require 'rubygems'
begin
gem 'ci_reporter'
rescue => e
$: << File.dirname(__FILE__) + "/../../../lib"
end
require 'ci/reporter/rspec'
8 changes: 8 additions & 0 deletions lib/ci/reporter/rake/test_unit.rb
@@ -0,0 +1,8 @@
namespace :ci do
namespace :setup do
task :testunit do
rm_rf ENV["CI_REPORTS"] || "test/reports"
ENV["TESTOPTS"] = "#{File.dirname(__FILE__)}/test_unit_loader.rb"
end
end
end
22 changes: 22 additions & 0 deletions lib/ci/reporter/rake/test_unit_loader.rb
@@ -0,0 +1,22 @@
require 'rubygems'
begin
gem 'ci_reporter'
rescue
$: << File.dirname(__FILE__) + "/../../../lib"
end
require 'ci/reporter/test_unit'

module Test #:nodoc:all
module Unit
module UI
module Console
class TestRunner
def create_mediator(suite)
# swap in our custom mediator
return CI::Reporter::TestUnit.new(suite)
end
end
end
end
end
end
4 changes: 2 additions & 2 deletions lib/ci/reporter/report_manager.rb
@@ -1,7 +1,7 @@
require 'fileutils'

module CI
module Reporter
module CI #:nodoc:
module Reporter #:nodoc:
class ReportManager
def initialize(prefix)
@basedir = ENV['CI_REPORTS'] || File.expand_path("#{Dir.getwd}/#{prefix.downcase}/reports")
Expand Down
2 changes: 2 additions & 0 deletions lib/ci/reporter/rspec.rb
Expand Up @@ -4,6 +4,7 @@

module CI
module Reporter
# Wrapper around a <code>RSpec</code> error or failure to be used by the test suite to interpret results.
class RSpecFailure
def initialize(failure)
@failure = failure
Expand All @@ -22,6 +23,7 @@ def message() @failure.exception.message end
def location() @failure.exception.backtrace.join("\n") end
end

# Custom +RSpec+ formatter used to hook into the spec runs and capture results.
class RSpec < Spec::Runner::Formatter::ProgressBarFormatter
def initialize(output, dry_run=false, colour=false, report_mgr=nil)
super(output, dry_run, colour)
Expand Down
14 changes: 13 additions & 1 deletion lib/ci/reporter/test_suite.rb
@@ -1,27 +1,32 @@
module CI
module Reporter
# Basic structure representing the running of a test suite. Used to time tests and store results.
class TestSuite < Struct.new(:name, :tests, :time, :failures, :errors)
attr_accessor :testcases
def initialize(name)
super
@testcases = []
end

# Starts timing the test suite.
def start
@start = Time.now
end

# Finishes timing the test suite.
def finish
self.tests = testcases.size
self.time = Time.now - @start
self.failures = testcases.select {|tc| tc.failure? }.size
self.errors = testcases.select {|tc| tc.error? }.size
end

# Creates the xml builder instance used to create the report xml document.
def create_builder
begin
gem 'builder'
require 'builder'
rescue LoadError
rescue
begin
gem 'activesupport'
require 'active_support'
Expand All @@ -33,6 +38,7 @@ def create_builder
Builder::XmlMarkup.new(:indent => 2, :escape_attrs => true)
end

# Creates an xml string containing the test suite results.
def to_xml
builder = create_builder
# more recent version of Builder doesn't need the escaping
Expand All @@ -56,25 +62,31 @@ def builder.trunc!(txt)
end
end

# Structure used to represent an individual test case. Used to time the test and store the result.
class TestCase < Struct.new(:name, :time)
attr_accessor :failure

# Starts timing the test.
def start
@start = Time.now
end

# Finishes timing the test.
def finish
self.time = Time.now - @start
end

# Returns non-nil if the test failed.
def failure?
failure && failure.failure?
end

# Returns non-nil if the test had an error.
def error?
failure && failure.error?
end

# Writes xml representing the test result to the provided builder.
def to_xml(builder)
attrs = {}
each_pair {|k,v| attrs[k] = builder.trunc!(v.to_s) }
Expand Down
5 changes: 5 additions & 0 deletions lib/ci/reporter/test_unit.rb
Expand Up @@ -4,12 +4,15 @@

module CI
module Reporter
# Factory for constructing either a CI::Reporter::TestUnitFailure or CI::Reporter::TestUnitError depending on the result
# of the test.
class Failure
def self.new(fault)
fault.kind_of?(Test::Unit::Failure) ? TestUnitFailure.new(fault) : TestUnitError.new(fault)
end
end

# Wrapper around a <code>Test::Unit</code> error to be used by the test suite to interpret results.
class TestUnitError
def initialize(fault)
@fault = fault
Expand All @@ -21,6 +24,7 @@ def message() @fault.exception.message end
def location() @fault.exception.backtrace.join("\n") end
end

# Wrapper around a <code>Test::Unit</code> failure to be used by the test suite to interpret results.
class TestUnitFailure
def initialize(fault)
@fault = fault
Expand All @@ -32,6 +36,7 @@ def message() @fault.message end
def location() @fault.location.join("\n") end
end

# Replacement Mediator that adds listeners to capture the results of the <code>Test::Unit</code> runs.
class TestUnit < Test::Unit::UI::TestRunnerMediator
def initialize(suite, report_mgr = nil)
super(suite)
Expand Down
20 changes: 10 additions & 10 deletions tasks/ci_reporter.rake
@@ -1,12 +1,12 @@
begin
gem 'ci_reporter'
rescue
$: << File.dirname(__FILE__) + "/../lib"
end
require 'ci/reporter/rake/rspec'
require 'ci/reporter/rake/test_unit'

namespace :ci do
task :setup_rspec do
rm_rf ENV["CI_REPORTS"] || "spec/reports"
ENV["RSPECOPTS"] = ["--require", "#{File.dirname(__FILE__)}/rspec_loader.rb",
"--format", "CI::Reporter::RSpec"].join(" ")
end

task :setup_testunit do
rm_rf ENV["CI_REPORTS"] || "test/reports"
ENV["TESTOPTS"] = "#{File.dirname(__FILE__)}/test_unit_loader.rb"
end
task :setup_rspec => "ci:setup:rspec"
task :setup_testunit => "ci:setup:testunit"
end
2 changes: 0 additions & 2 deletions tasks/rspec_loader.rb

This file was deleted.

8 changes: 0 additions & 8 deletions tasks/test_unit_loader.rb

This file was deleted.

0 comments on commit bfdcd21

Please sign in to comment.