Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

ci_reporter for MiniTest::Unit #49

Merged
merged 6 commits into from

2 participants

@realmyst

Loader and reporter for minitest/unit

@nicksieger
Owner

This is great! An often requested feature. Any chance you could create a couple of minitest tests and add them to the acceptance suite? You'll need to add a test file to the acceptance directory, and modify Rakefile and acceptance/verification_spec.rb.

@realmyst

I added tests and fixed a small bug that these tests revealed. All ok?

@nicksieger nicksieger merged commit cb87ca0 into ci-reporter:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 27, 2012
  1. @realmyst

    added reporter for minitest

    realmyst authored
  2. @realmyst

    fix gemspec

    realmyst authored
  3. @realmyst

    added minitest to stub.rake

    realmyst authored
  4. @realmyst

    updated readme

    realmyst authored
  5. @realmyst
  6. @realmyst

    added acceptance spec

    realmyst authored
This page is out of date. Refresh to see the latest.
View
2  README.rdoc
@@ -16,6 +16,7 @@ CI::Reporter works best with projects that use a +Rakefile+ along with the stand
require 'ci/reporter/rake/rspec' # use this if you're using RSpec
require 'ci/reporter/rake/cucumber' # use this if you're using Cucumber
require 'ci/reporter/rake/test_unit' # use this if you're using Test::Unit
+ require 'ci/reporter/rake/minitest' # use this if you're using MiniTest::Unit
2. Next, either modify your Rakefile to make the <code>ci:setup:rspec</code>, <code>ci:setup:cucumber</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.
@@ -28,6 +29,7 @@ Report files are written, by default, to the <code>test/reports</code>, <code>fe
If you don't have control over the Rakefile or don't want to modify it, CI::Reporter has a substitute rake file that you can specify on the command-line. It assumes that the main project rake file is called +Rakefile+ and lives in the current directory. Run like so:
rake -f GEM_PATH/stub.rake ci:setup:testunit test
+ rake -f GEM_PATH/stub.rake ci:setup:minitest test
rake -f GEM_PATH/stub.rake ci:setup:rspec spec
rake -f GEM_PATH/stub.rake ci:setup:cucumber features
View
1  Rakefile
@@ -97,6 +97,7 @@ task :generate_output do
begin
result_proc = proc {|ok,*| puts "Failures above are expected." unless ok }
ruby "-Ilib #{opts} -rci/reporter/rake/test_unit_loader acceptance/test_unit_example_test.rb", &result_proc
+ ruby "-Ilib #{opts} -rci/reporter/rake/minitest_loader acceptance/minitest_example_test.rb", &result_proc
ruby "-Ilib #{opts} -S #{@spec_bin} --require ci/reporter/rake/rspec_loader --format CI::Reporter::RSpec acceptance/rspec_example_spec.rb", &result_proc
ruby "-Ilib #{opts} -rci/reporter/rake/cucumber_loader -S cucumber --format CI::Reporter::Cucumber acceptance/cucumber", &result_proc
ensure
View
17 acceptance/minitest_example_test.rb
@@ -0,0 +1,17 @@
+require 'minitest/autorun'
+
+class MiniTestExampleTestOne < MiniTest::Unit::TestCase
+ def test_one
+ puts "Some <![CDATA[on stdout]]>"
+ assert false
+ end
+ def teardown
+ raise "second failure"
+ end
+end
+
+class MiniTestExampleTestTwo < MiniTest::Unit::TestCase
+ def test_two
+ assert true
+ end
+end
View
35 acceptance/verification_spec.rb
@@ -37,6 +37,41 @@
end
end
+describe "MiniTest::Unit acceptance" do
+ it "should generate two XML files" do
+ File.exist?(File.join(REPORTS_DIR, 'TEST-MiniTestExampleTestOne.xml')).should == true
+ File.exist?(File.join(REPORTS_DIR, 'TEST-MiniTestExampleTestTwo.xml')).should == true
+ end
+
+ it "should have one error and one failure for MiniTestExampleTestOne" do
+ doc = File.open(File.join(REPORTS_DIR, 'TEST-MiniTestExampleTestOne.xml')) do |f|
+ REXML::Document.new(f)
+ end
+ doc.root.attributes["errors"].should == "1"
+ doc.root.attributes["failures"].should == "1"
+ doc.root.attributes["assertions"].should == "1"
+ doc.root.attributes["tests"].should == "1"
+ doc.root.elements.to_a("/testsuite/testcase").size.should == 1
+ doc.root.elements.to_a("/testsuite/testcase/error").size.should == 1
+ doc.root.elements.to_a("/testsuite/testcase/failure").size.should == 1
+ doc.root.elements.to_a("/testsuite/system-out").first.texts.inject("") do |c,e|
+ c << e.value; c
+ end.strip.should == "Some <![CDATA[on stdout]]>"
+ end
+
+ it "should have no errors or failures for MiniTestExampleTestTwo" do
+ doc = File.open(File.join(REPORTS_DIR, 'TEST-MiniTestExampleTestTwo.xml')) do |f|
+ REXML::Document.new(f)
+ end
+ doc.root.attributes["errors"].should == "0"
+ doc.root.attributes["failures"].should == "0"
+ doc.root.attributes["assertions"].should == "1"
+ doc.root.attributes["tests"].should == "1"
+ doc.root.elements.to_a("/testsuite/testcase").size.should == 1
+ doc.root.elements.to_a("/testsuite/testcase/failure").size.should == 0
+ end
+end
+
describe "RSpec acceptance" do
it "should generate two XML files" do
File.exist?(File.join(REPORTS_DIR, 'SPEC-RSpec-example.xml')).should == true
View
28 ci_reporter.gemspec
@@ -1,23 +1,23 @@
# -*- encoding: utf-8 -*-
Gem::Specification.new do |s|
- s.name = %q{ci_reporter}
+ s.name = "ci_reporter"
s.version = "1.6.9"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
- s.authors = [%q{Nick Sieger}]
- s.date = %q{2011-12-15}
- s.description = %q{CI::Reporter is an add-on to Test::Unit, RSpec and Cucumber that allows you to generate XML reports of your test, spec and/or feature 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.}
- s.email = %q{nick@nicksieger.com}
- s.extra_rdoc_files = [%q{History.txt}, %q{Manifest.txt}, %q{LICENSE.txt}, %q{README.rdoc}]
- s.files = [%q{History.txt}, %q{Manifest.txt}, %q{README.rdoc}, %q{LICENSE.txt}, %q{Rakefile}, %q{stub.rake}, %q{lib/ci/reporter/core.rb}, %q{lib/ci/reporter/cucumber.rb}, %q{lib/ci/reporter/report_manager.rb}, %q{lib/ci/reporter/rspec.rb}, %q{lib/ci/reporter/test_suite.rb}, %q{lib/ci/reporter/test_unit.rb}, %q{lib/ci/reporter/version.rb}, %q{lib/ci/reporter/rake/cucumber.rb}, %q{lib/ci/reporter/rake/cucumber_loader.rb}, %q{lib/ci/reporter/rake/rspec.rb}, %q{lib/ci/reporter/rake/rspec_loader.rb}, %q{lib/ci/reporter/rake/test_unit.rb}, %q{lib/ci/reporter/rake/test_unit_loader.rb}, %q{lib/ci/reporter/rake/utils.rb}, %q{spec/spec_helper.rb}, %q{spec/ci/reporter/cucumber_spec.rb}, %q{spec/ci/reporter/output_capture_spec.rb}, %q{spec/ci/reporter/report_manager_spec.rb}, %q{spec/ci/reporter/rspec_spec.rb}, %q{spec/ci/reporter/test_suite_spec.rb}, %q{spec/ci/reporter/test_unit_spec.rb}, %q{spec/ci/reporter/rake/rake_tasks_spec.rb}, %q{tasks/ci_reporter.rake}]
- s.homepage = %q{http://caldersphere.rubyforge.org/ci_reporter}
- s.rdoc_options = [%q{--main}, %q{README.rdoc}, %q{-SHN}, %q{-f}, %q{darkfish}]
- s.require_paths = [%q{lib}]
- s.rubyforge_project = %q{caldersphere}
- s.rubygems_version = %q{1.8.9}
- s.summary = %q{CI::Reporter allows you to generate reams of XML for use with continuous integration systems.}
- s.test_files = [%q{spec/ci/reporter/cucumber_spec.rb}, %q{spec/ci/reporter/output_capture_spec.rb}, %q{spec/ci/reporter/report_manager_spec.rb}, %q{spec/ci/reporter/rspec_spec.rb}, %q{spec/ci/reporter/test_suite_spec.rb}, %q{spec/ci/reporter/test_unit_spec.rb}, %q{spec/ci/reporter/rake/rake_tasks_spec.rb}]
+ s.authors = ["Nick Sieger"]
+ s.date = "2012-01-27"
+ s.description = "CI::Reporter is an add-on to Test::Unit, RSpec and Cucumber that allows you to generate XML reports of your test, spec and/or feature 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."
+ s.email = "nick@nicksieger.com"
+ s.extra_rdoc_files = ["History.txt", "LICENSE.txt", "README.rdoc"] + Dir.glob("Manifest.txt")
+ s.files = ["History.txt", "README.rdoc", "LICENSE.txt", "Rakefile", "stub.rake", "lib/ci/reporter/minitest.rb", "lib/ci/reporter/report_manager.rb", "lib/ci/reporter/test_suite.rb", "lib/ci/reporter/rspec.rb", "lib/ci/reporter/core.rb", "lib/ci/reporter/cucumber.rb", "lib/ci/reporter/rake/minitest.rb", "lib/ci/reporter/rake/minitest_loader.rb", "lib/ci/reporter/rake/cucumber_loader.rb", "lib/ci/reporter/rake/rspec.rb", "lib/ci/reporter/rake/rspec_loader.rb", "lib/ci/reporter/rake/utils.rb", "lib/ci/reporter/rake/test_unit_loader.rb", "lib/ci/reporter/rake/cucumber.rb", "lib/ci/reporter/rake/test_unit.rb", "lib/ci/reporter/test_unit.rb", "lib/ci/reporter/version.rb", "spec/spec_helper.rb", "spec/ci/reporter/rspec_spec.rb", "spec/ci/reporter/test_suite_spec.rb", "spec/ci/reporter/report_manager_spec.rb", "spec/ci/reporter/test_unit_spec.rb", "spec/ci/reporter/rake/rake_tasks_spec.rb", "spec/ci/reporter/cucumber_spec.rb", "spec/ci/reporter/output_capture_spec.rb", "tasks/ci_reporter.rake"]
+ s.homepage = "http://caldersphere.rubyforge.org/ci_reporter"
+ s.rdoc_options = ["--main", "README.rdoc", "-SHN", "-f", "darkfish"]
+ s.require_paths = ["lib"]
+ s.rubyforge_project = "caldersphere"
+ s.rubygems_version = "1.8.10"
+ s.summary = "CI::Reporter allows you to generate reams of XML for use with continuous integration systems."
+ s.test_files = ["spec/ci/reporter/rspec_spec.rb", "spec/ci/reporter/test_suite_spec.rb", "spec/ci/reporter/report_manager_spec.rb", "spec/ci/reporter/test_unit_spec.rb", "spec/ci/reporter/rake/rake_tasks_spec.rb", "spec/ci/reporter/cucumber_spec.rb", "spec/ci/reporter/output_capture_spec.rb"]
if s.respond_to? :specification_version then
s.specification_version = 3
View
220 lib/ci/reporter/minitest.rb
@@ -0,0 +1,220 @@
+# Copyright (c) 2012 Alexander Shcherbinin <alexander.shcherbinin@gmail.com>
+# See the file LICENSE.txt included with the distribution for
+# software license details.
+
+require 'ci/reporter/core'
+
+require 'minitest/unit'
+
+module CI
+ module Reporter
+ class Failure
+ def self.new(fault, type = nil, meth = nil)
+ return MiniTestSkipped.new(fault) if type == :skip
+ return MiniTestFailure.new(fault, meth) if type == :failure
+ MiniTestError.new(fault)
+ end
+ end
+
+ class FailureCore
+ def location(e)
+ last_before_assertion = ""
+ e.backtrace.reverse_each do |s|
+ break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
+ last_before_assertion = s
+ end
+ last_before_assertion.sub(/:in .*$/, '')
+ end
+ end
+
+ class MiniTestSkipped < FailureCore
+ def initialize(fault) @fault = fault end
+ def failure?() false end
+ def error?() false end
+ def name() @fault.class.name end
+ def message() @fault.message end
+ def location() super @fault end
+ end
+
+ class MiniTestFailure < FailureCore
+ def initialize(fault, meth) @fault = fault; @meth = meth end
+ def failure?() true end
+ def error?() false end
+ def name() @meth end
+ def message() @fault.message end
+ def location() super @fault end
+ end
+
+ class MiniTestError < FailureCore
+ def initialize(fault) @fault = fault end
+ def failure?() false end
+ def error?() true end
+ def name() @fault.exception.class.name end
+ def message() @fault.exception.message end
+ def location() @fault.exception.backtrace.join("\n") end
+ end
+
+ class Runner < MiniTest::Unit
+
+ @@out = $stdout
+
+ def initialize
+ super
+ @report_manager = ReportManager.new("test")
+ end
+
+ def _run_anything(type)
+ suites = MiniTest::Unit::TestCase.send "#{type}_suites"
+ return if suites.empty?
+
+ started_anything type
+
+ sync = output.respond_to? :"sync=" # stupid emacs
+ old_sync, output.sync = output.sync, true if sync
+
+ _run_suites(suites, type)
+
+ output.sync = old_sync if sync
+
+ finished_anything(type)
+ end
+
+ def _run_suites(suites, type)
+ suites.map { |suite| _run_suite suite, type }
+ end
+
+ def _run_suite(suite, type)
+ start_suite(suite)
+
+ header = "#{type}_suite_header"
+ puts send(header, suite) if respond_to? header
+
+ filter_suite_methods(suite, type).each do |method|
+ _run_test(suite, method)
+ end
+
+ finish_suite
+ end
+
+ def _run_test(suite, method)
+ start_case(method)
+
+ result = run_test(suite, method)
+
+ @assertion_count += result._assertions
+ @test_count += 1
+
+ finish_case
+ end
+
+ def puke(klass, meth, e)
+ e = case e
+ when MiniTest::Skip then
+ @skips += 1
+ fault(e, :skip)
+ return "S" unless @verbose
+ "Skipped:\n#{meth}(#{klass}) [#{location e}]:\n#{e.message}\n"
+ when MiniTest::Assertion then
+ @failures += 1
+ fault(e, :failure, meth)
+ "Failure:\n#{meth}(#{klass}) [#{location e}]:\n#{e.message}\n"
+ else
+ @errors += 1
+ fault(e, :error)
+ bt = MiniTest::filter_backtrace(e.backtrace).join "\n "
+ "Error:\n#{meth}(#{klass}):\n#{e.class}: #{e.message}\n #{bt}\n"
+ end
+ @report << e
+ e[0, 1]
+ end
+
+ private
+
+ def started_anything(type)
+ @test_count = 0
+ @assertion_count = 0
+ @last_assertion_count = 0
+ @result_assertion_count = 0
+ @start = Time.now
+
+ puts
+ puts "# Running #{type}s:"
+ puts
+ end
+
+ def finished_anything(type)
+ t = Time.now - @start
+ puts
+ puts
+ puts "Finished #{type}s in %.6fs, %.4f tests/s, %.4f assertions/s." %
+ [t, @test_count / t, @assertion_count / t]
+
+ report.each_with_index do |msg, i|
+ puts "\n%3d) %s" % [i + 1, msg]
+ end
+
+ puts
+
+ status
+ end
+
+ def filter_suite_methods(suite, type)
+ filter = options[:filter] || '/./'
+ filter = Regexp.new $1 if filter =~ /\/(.*)\//
+
+ suite.send("#{type}_methods").grep(filter)
+ end
+
+ def run_test(suite, method)
+ inst = suite.new method
+ inst._assertions = 0
+
+ print "#{suite}##{method} = " if @verbose
+
+ @start_time = Time.now
+ result = inst.run self
+ time = Time.now - @start_time
+
+ print "%.2f s = " % time if @verbose
+ print result
+ puts if @verbose
+
+ return inst
+ end
+
+ def start_suite(suite_name)
+ @current_suite = CI::Reporter::TestSuite.new(suite_name)
+ @current_suite.start
+ end
+
+ def finish_suite
+ if @current_suite
+ @current_suite.finish
+ @current_suite.assertions = @assertion_count - @last_assertion_count
+ @last_assertion_count = @assertion_count
+ @report_manager.write_report(@current_suite)
+ end
+ end
+
+ def start_case(test_name)
+ tc = CI::Reporter::TestCase.new(test_name)
+ tc.start
+ @current_suite.testcases << tc
+ end
+
+ def finish_case
+ tc = @current_suite.testcases.last
+ tc.finish
+ tc.assertions = @assertion_count - @result_assertion_count
+ @result_assertion_count = @assertion_count
+ end
+
+ def fault(fault, type = nil, meth = nil)
+ tc = @current_suite.testcases.last
+ tc.failures << Failure.new(fault, type, meth)
+ end
+
+ end
+
+ end
+end
View
15 lib/ci/reporter/rake/minitest.rb
@@ -0,0 +1,15 @@
+# Copyright (c) 2012 Alexander Shcherbinin <alexander.shcherbinin@gmail.com>
+# See the file LICENSE.txt included with the distribution for
+# software license details.
+
+require File.expand_path('../utils', __FILE__)
+
+namespace :ci do
+ namespace :setup do
+ task :minitest do
+ rm_rf ENV["CI_REPORTS"] || "test/reports"
+ test_loader = CI::Reporter.maybe_quote_filename "#{File.dirname(__FILE__)}/minitest_loader.rb"
+ ENV["TESTOPTS"] = "#{ENV["TESTOPTS"]} #{test_loader}"
+ end
+ end
+end
View
9 lib/ci/reporter/rake/minitest_loader.rb
@@ -0,0 +1,9 @@
+# Copyright (c) 2012 Alexander Shcherbinin <alexander.shcherbinin@gmail.com>
+# See the file LICENSE.txt included with the distribution for
+# software license details.
+
+$: << File.dirname(__FILE__) + "/../../.."
+require 'ci/reporter/minitest'
+
+# set defaults
+MiniTest::Unit.runner = CI::Reporter::Runner.new
View
2  lib/ci/reporter/test_suite.rb
@@ -140,7 +140,7 @@ def to_xml(builder)
failures.each do |failure|
tag = case failure.class.name
when /TestUnitSkipped/ then :skipped
- when /TestUnitError/ then :error
+ when /TestUnitError/, /MiniTestError/ then :error
else :failure end
builder.tag!(tag, :type => builder.trunc!(failure.name), :message => builder.trunc!(failure.message)) do
View
3  stub.rake
@@ -2,7 +2,7 @@
# See the file LICENSE.txt included with the distribution for
# software license details.
#
-# Use this stub rakefile as a wrapper around a regular Rakefile. Run in the
+# Use this stub rakefile as a wrapper around a regular Rakefile. Run in the
# same directory as the real Rakefile.
#
# rake -f /path/to/ci_reporter/lib/ci/reporter/rake/stub.rake ci:setup:rspec default
@@ -11,4 +11,5 @@
load File.dirname(__FILE__) + '/lib/ci/reporter/rake/rspec.rb'
load File.dirname(__FILE__) + '/lib/ci/reporter/rake/cucumber.rb'
load File.dirname(__FILE__) + '/lib/ci/reporter/rake/test_unit.rb'
+load File.dirname(__FILE__) + '/lib/ci/reporter/rake/minitest.rb'
load 'Rakefile'
View
2  tasks/ci_reporter.rake
@@ -10,9 +10,11 @@ end
require 'ci/reporter/rake/rspec'
require 'ci/reporter/rake/cucumber'
require 'ci/reporter/rake/test_unit'
+require 'ci/reporter/rake/minitest'
namespace :ci do
task :setup_rspec => "ci:setup:rspec"
task :setup_cucumber => "ci:setup:cucumber"
task :setup_testunit => "ci:setup:testunit"
+ task :setup_minitest => "ci:setup:minitest"
end
Something went wrong with that request. Please try again.