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 from
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.