Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 144 lines (126 sloc) 4.859 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
# Copyright (c) 2006-2012 Nick Sieger <nicksieger@gmail.com>
# See the file LICENSE.txt included with the distribution for
# software license details.

require 'ci/reporter/core'
require 'test/unit'
require 'test/unit/ui/console/testrunner'

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)
        return TestUnitFailure.new(fault) if fault.kind_of?(Test::Unit::Failure)
        return TestUnitSkipped.new(fault) if Test::Unit.const_defined?(:Omission, false) && (fault.kind_of?(Test::Unit::Omission) || fault.kind_of?(Test::Unit::Pending))
        return TestUnitNotification.new(fault) if Test::Unit.const_defined?(:Notification, false) && fault.kind_of?(Test::Unit::Notification)
        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 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

    # 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 end
      def failure?() true end
      def error?() false end
      def name() Test::Unit::AssertionFailedError.name end
      def message() @fault.message end
      def location() @fault.location.join("\n") end
    end

    # Wrapper around a <code>Test::Unit</code> 2.0 omission.
    class TestUnitSkipped
      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() @fault.location.join("\n") end
    end

    # Wrapper around a <code>Test::Unit</code> 2.0 notification.
    class TestUnitNotification
      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() @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)
        @report_manager = report_mgr || ReportManager.new("test")
        add_listener(Test::Unit::UI::TestRunnerMediator::STARTED, &method(:started))
        add_listener(Test::Unit::TestCase::STARTED, &method(:test_started))
        add_listener(Test::Unit::TestCase::FINISHED, &method(:test_finished))
        add_listener(Test::Unit::TestResult::FAULT, &method(:fault))
        add_listener(Test::Unit::UI::TestRunnerMediator::FINISHED, &method(:finished))
      end

      def started(result)
        @suite_result = result
        @last_assertion_count = 0
        @current_suite = nil
        @unknown_count = 0
        @result_assertion_count = 0
      end

      def test_started(name)
        test_name, suite_name = extract_names(name)
        unless @current_suite && @current_suite.name == suite_name
          finish_suite
          start_suite(suite_name)
        end
        start_test(test_name)
      end

      def test_finished(name)
        finish_test
      end

      def fault(fault)
        tc = @current_suite.testcases.last
        tc.failures << Failure.new(fault)
      end

      def finished(elapsed_time)
        finish_suite
      end

      private
      def extract_names(name)
        match = name.match(/(.*)\(([^)]*)\)/)
        if match
          [match[1], match[2]]
        else
          @unknown_count += 1
          [name, "unknown-#{@unknown_count}"]
        end
      end

      def start_suite(suite_name)
        @current_suite = TestSuite.new(suite_name)
        @current_suite.start
      end

      def finish_suite
        if @current_suite
          @current_suite.finish
          @current_suite.assertions = @suite_result.assertion_count - @last_assertion_count
          @last_assertion_count = @suite_result.assertion_count
          @report_manager.write_report(@current_suite)
        end
      end

      def start_test(test_name)
        tc = TestCase.new(test_name)
        tc.start
        @current_suite.testcases << tc
      end

      def finish_test
        tc = @current_suite.testcases.last
        tc.finish
        tc.assertions = @suite_result.assertion_count - @result_assertion_count
        @result_assertion_count = @suite_result.assertion_count
      end
    end
  end
end
Something went wrong with that request. Please try again.