File: testrunnermediator.rb

package info (click to toggle)
ruby-test-unit 3.7.7-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,348 kB
  • sloc: ruby: 16,403; makefile: 9
file content (131 lines) | stat: -rw-r--r-- 4,386 bytes parent folder | download
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
#--
#
# Author:: Nathaniel Talbott.
# Copyright:: Copyright (c) 2000-2002 Nathaniel Talbott. All rights reserved.
# License:: Ruby license.

require_relative '../util/observable'
require_relative '../testresult'
require_relative '../worker-context'

module Test
  module Unit
    module UI

      # Provides an interface to write any given UI against,
      # hopefully making it easy to write new UIs.
      class TestRunnerMediator
        RESET = name + "::RESET"
        STARTED = name + "::STARTED"
        FINISHED = name + "::FINISHED"

        include Util::Observable

        # Creates a new TestRunnerMediator initialized to run
        # the passed suite.
        def initialize(suite, options={})
          @suite = suite
          @options = options
          @test_suite_runner_class = @options[:test_suite_runner_class]
          @test_suite_runner_class ||= TestSuiteRunner
        end

        # Runs the suite the TestRunnerMediator was created
        # with.
        def run
          AutoRunner.need_auto_run = false

          result = create_result
          options = @options.dup
          # We should not keep @suite in @options because @options may
          # be live longer than this instance. For example,
          # AutoRunner's @runner_options is @options in this instance
          # and AutoRunner is live longer than this instance. We can
          # dup @options to avoid @suite's life time longer.
          options[:test_suite] = @suite
          options[:event_listener] = lambda do |channel, value|
            notify_listeners(channel, value)
          end

          Test::Unit.run_at_start_hooks
          start_time = Time.now
          begin
            with_listener(result) do
              @test_suite_runner_class.run_all_tests(result, options) do |run_context|
                catch do |stop_tag|
                  result.stop_tag = stop_tag
                  notify_listeners(RESET, @suite.size)
                  notify_listeners(STARTED, result)

                  run_suite(result, run_context: run_context)
                end
              end
            end
          ensure
            elapsed_time = Time.now - start_time
            notify_listeners(FINISHED, elapsed_time)
          end
          Test::Unit.run_at_exit_hooks

          result
        end

        # Just for backward compatibility for NetBeans.
        # NetBeans should not use monkey patching. NetBeans
        # should use runner change public API.
        #
        # See GitHub#38
        #   https://github.com/test-unit/test-unit/issues/38
        def run_suite(result=nil, run_context: nil)
          if result.nil?
            run
          else
            worker_context = WorkerContext.new(nil, run_context, result)
            @suite.run(worker_context) do |channel, value|
              notify_listeners(channel, value)
            end
          end
        end

        private
        # A factory method to create the result the mediator
        # should run with. Can be overridden by subclasses if
        # one wants to use a different result.
        def create_result
          TestResult.new
        end

        def measure_time
          begin_time = Time.now
          yield
          Time.now - begin_time
        end

        def with_listener(result)
          finished_listener = result.add_listener(TestResult::FINISHED) do |*args|
            notify_listeners(TestResult::FINISHED, *args)
          end
          changed_listener = result.add_listener(TestResult::CHANGED) do |*args|
            notify_listeners(TestResult::CHANGED, *args)
          end
          pass_assertion_listener = result.add_listener(TestResult::PASS_ASSERTION) do |*args|
            notify_listeners(TestResult::PASS_ASSERTION, *args)
          end
          fault_listener = result.add_listener(TestResult::FAULT) do |*args|
            notify_listeners(TestResult::FAULT, *args)
          end

          begin
            yield
          ensure
            result.remove_listener(TestResult::FAULT, fault_listener)
            result.remove_listener(TestResult::CHANGED, changed_listener)
            result.remove_listener(TestResult::FINISHED, finished_listener)
            result.remove_listener(TestResult::PASS_ASSERTION,
                                   pass_assertion_listener)
          end
        end
      end
    end
  end
end