root / lib / test / unit / testcase.rb @ 16a276fdc77847a92cba21d060b9880eb1fe75bb

View | Annotate | Download (11.8 KB)

1
#--
2
#
3
# Author:: Nathaniel Talbott.
4
# Copyright::
5
#   * Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
6
#   * Copyright (c) 2008-2009 Kouhei Sutou <tt><kou@clear-code.com></tt>
7
# License:: Ruby license.
8
9
require 'test/unit/attribute'
10
require 'test/unit/fixture'
11
require 'test/unit/exceptionhandler'
12
require 'test/unit/assertions'
13
require 'test/unit/failure'
14
require 'test/unit/error'
15
require 'test/unit/pending'
16
require 'test/unit/omission'
17
require 'test/unit/notification'
18
require 'test/unit/priority'
19
require 'test/unit/testsuite'
20
require 'test/unit/assertionfailederror'
21
require 'test/unit/util/backtracefilter'
22
require 'test/unit/util/method-owner-finder'
23
24
module Test
25
  module Unit
26
27
    # Ties everything together. If you subclass and add your own
28
    # test methods, it takes care of making them into tests and
29
    # wrapping those tests into a suite. It also does the
30
    # nitty-gritty of actually running an individual test and
31
    # collecting its results into a Test::Unit::TestResult object.
32
    #
33
    # You can run two hooks before/after a TestCase run.
34
    #
35
    # Example:
36
    #   class TestMyClass < Test::Unit::TestCase
37
    #     class << self
38
    #       def startup
39
    #         ...
40
    #       end
41
    #
42
    #       def shutdown
43
    #         ...
44
    #       end
45
    #     end
46
    #
47
    #     def setup
48
    #       ...
49
    #     end
50
    #
51
    #     def teardown
52
    #       ...
53
    #     end
54
    #
55
    #     def test_my_method1
56
    #       ...
57
    #     end
58
    #
59
    #     def test_my_method2
60
    #       ...
61
    #     end
62
    #   end
63
    #
64
    # Here is a call order:
65
    # * startup
66
    # * setup
67
    # * test_my_method1
68
    # * teardown
69
    # * setup
70
    # * test_my_method2
71
    # * teardown
72
    # * shutdown
73
    class TestCase
74
      include Attribute
75
      include Fixture
76
      include ExceptionHandler
77
      include ErrorHandler
78
      include FailureHandler
79
      include TestCasePendingSupport
80
      include TestCaseOmissionSupport
81
      include TestCaseNotificationSupport
82
      include Priority
83
      include Assertions
84
      include Util::BacktraceFilter
85
86
      STARTED = name + "::STARTED" # :nodoc:
87
      FINISHED = name + "::FINISHED" # :nodoc:
88
89
      DESCENDANTS = [] # :nodoc:
90
      AVAILABLE_ORDERS = [:alphabetic, :random, :defined] # :nodoc:
91
92
      class << self
93
        def inherited(sub_class) # :nodoc:
94
          DESCENDANTS << sub_class
95
        end
96
97
        @@added_methods = []
98
        def method_added(name) # :nodoc:
99
          super
100
          @@added_methods << name.to_s
101
        end
102
103
        # Rolls up all of the test* methods in the fixture into
104
        # one suite, creating a new instance of the fixture for
105
        # each method.
106
        def suite
107
          suite = TestSuite.new(name, self)
108
          collect_test_names.each do |test|
109
            catch(:invalid_test) do
110
              suite << new(test)
111
            end
112
          end
113
          if suite.empty?
114
            catch(:invalid_test) do
115
              suite << new("default_test")
116
            end
117
          end
118
          suite
119
        end
120
121
        # Called before every test case runs. Can be used
122
        # to set up fixture information used in test case
123
        # scope.
124
        #
125
        # Here is an example test case:
126
        #   class TestMyClass < Test::Unit::TestCase
127
        #     class << self
128
        #       def startup
129
        #         ...
130
        #       end
131
        #     end
132
        #
133
        #     def setup
134
        #       ...
135
        #     end
136
        #
137
        #     def test_my_class1
138
        #       ...
139
        #     end
140
        #
141
        #     def test_my_class2
142
        #       ...
143
        #     end
144
        #   end
145
        #
146
        # Here is a call order:
147
        # * startup
148
        # * setup
149
        # * test_my_class1 (or test_my_class2)
150
        # * setup
151
        # * test_my_class2 (or test_my_class1)
152
        #
153
        # Note that you should not assume test order. Tests
154
        # should be worked in any order.
155
        def startup
156
        end
157
158
        # Called after every test case runs. Can be used to tear
159
        # down fixture information used in test case scope.
160
        #
161
        # Here is an example test case:
162
        #   class TestMyClass < Test::Unit::TestCase
163
        #     class << self
164
        #       def shutdown
165
        #         ...
166
        #       end
167
        #     end
168
        #
169
        #     def teardown
170
        #       ...
171
        #     end
172
        #
173
        #     def test_my_class1
174
        #       ...
175
        #     end
176
        #
177
        #     def test_my_class2
178
        #       ...
179
        #     end
180
        #   end
181
        #
182
        # Here is a call order:
183
        # * test_my_class1 (or test_my_class2)
184
        # * teardown
185
        # * test_my_class2 (or test_my_class1)
186
        # * teardown
187
        # * shutdown
188
        #
189
        # Note that you should not assume test order. Tests
190
        # should be worked in any order.
191
        def shutdown
192
        end
193
194
        @@test_order = AVAILABLE_ORDERS.first
195
196
        # Returns the current test order. This returns
197
        # +:alphabetic+ by default.
198
        def test_order
199
          @@test_order
200
        end
201
202
        # Sets the current test order.
203
        #
204
        # Here are the available _order_:
205
        # [:alphabetic]
206
        #   Default. Tests are sorted in alphabetic order.
207
        # [:random]
208
        #   Tests are sorted in random order.
209
        # [:defined]
210
        #   Tests are sorted in defined order.
211
        def test_order=(order)
212
          @@test_order = order
213
        end
214
215
        # Defines a test in declarative syntax.
216
        #
217
        # The following two test definitions are the same:
218
        #
219
        #   description "register user"
220
        #   def test_register_user
221
        #     ...
222
        #   end
223
        #
224
        #   test "register user" do
225
        #     ...
226
        #   end
227
        def test(test_description, &block)
228
          normalized_description = test_description.gsub(/[^a-zA-Z\d_]+/, '_')
229
          method_name = "test_#{normalized_description}".to_sym
230
          define_method(method_name, &block)
231
          description(test_description, method_name)
232
        end
233
234
        # Describes a test.
235
        #
236
        # The following example associates "register a
237
        # normal user" description with "test_register"
238
        # test.
239
        #
240
        #   description "register a normal user"
241
        #   def test_register
242
        #     ...
243
        #   end
244
        def description(value, target=nil)
245
          attribute(:description, value, {}, target || [])
246
        end
247
248
        # :stopdoc:
249
        private
250
        def collect_test_names
251
          method_names = public_instance_methods(true).collect do |name|
252
            name.to_s
253
          end
254
          test_names = method_names.find_all do |method_name|
255
            method_name =~ /^test./
256
          end
257
          send("sort_test_names_in_#{test_order}_order", test_names)
258
        end
259
260
        def sort_test_names_in_alphabetic_order(test_names)
261
          test_names.sort
262
        end
263
264
        def sort_test_names_in_random_order(test_names)
265
          test_names.sort_by {rand(test_names.size)}
266
        end
267
268
        def sort_test_names_in_defined_order(test_names)
269
          test_names.sort do |test1, test2|
270
            test1_defined_order = @@added_methods.index(test1)
271
            test2_defined_order = @@added_methods.index(test2)
272
            if test1_defined_order and test2_defined_order
273
              test1_defined_order <=> test2_defined_order
274
            elsif test1_defined_order
275
              1
276
            elsif test2_defined_order
277
              -1
278
            else
279
              test1 <=> test2
280
            end
281
          end
282
        end
283
        # :startdoc:
284
      end
285
286
      attr_reader :method_name
287
288
      # Creates a new instance of the fixture for running the
289
      # test represented by test_method_name.
290
      def initialize(test_method_name)
291
        throw :invalid_test unless respond_to?(test_method_name)
292
        test_method = method(test_method_name)
293
        throw :invalid_test if test_method.arity > 0
294
        owner = Util::MethodOwnerFinder.find(self, test_method_name)
295
        if owner.class != Module and self.class != owner
296
          throw :invalid_test
297
        end
298
        @method_name = test_method_name
299
        @test_passed = true
300
        @interrupted = false
301
      end
302
303
      # Runs the individual test method represented by this
304
      # instance of the fixture, collecting statistics, failures
305
      # and errors in result.
306
      def run(result)
307
        begin
308
          @_result = result
309
          yield(STARTED, name)
310
          begin
311
            run_setup
312
            run_test
313
          rescue Exception
314
            @interrupted = true
315
            raise unless handle_exception($!)
316
          ensure
317
            begin
318
              run_teardown
319
            rescue Exception
320
              raise unless handle_exception($!)
321
            end
322
          end
323
          result.add_run
324
          yield(FINISHED, name)
325
        ensure
326
          # @_result = nil # For test-spec's after_all :<
327
        end
328
      end
329
330
      # Called before every test method runs. Can be used
331
      # to set up fixture information.
332
      #
333
      # You can add additional setup tasks by the following
334
      # code:
335
      #   class TestMyClass < Test::Unit::TestCase
336
      #     def setup
337
      #       ...
338
      #     end
339
      #
340
      #     setup
341
      #     def my_setup1
342
      #       ...
343
      #     end
344
      #
345
      #     setup
346
      #     def my_setup2
347
      #       ...
348
      #     end
349
      #
350
      #     def test_my_class
351
      #       ...
352
      #     end
353
      #   end
354
      #
355
      # Here is a call order:
356
      # * setup
357
      # * my_setup1
358
      # * my_setup2
359
      # * test_my_class
360
      def setup
361
      end
362
363
      # Called after every test method runs. Can be used to tear
364
      # down fixture information.
365
      #
366
      # You can add additional teardown tasks by the following
367
      # code:
368
      #   class TestMyClass < Test::Unit::TestCase
369
      #     def teardown
370
      #       ...
371
      #     end
372
      #
373
      #     teardown
374
      #     def my_teardown1
375
      #       ...
376
      #     end
377
      #
378
      #     teardown
379
      #     def my_teardown2
380
      #       ...
381
      #     end
382
      #
383
      #     def test_my_class
384
      #       ...
385
      #     end
386
      #   end
387
      #
388
      # Here is a call order:
389
      # * test_my_class
390
      # * my_teardown2
391
      # * my_teardown1
392
      # * teardown
393
      def teardown
394
      end
395
396
      def default_test
397
        flunk("No tests were specified")
398
      end
399
400
      def size
401
        1
402
      end
403
404
      # Returns a human-readable name for the specific test that
405
      # this instance of TestCase represents.
406
      def name
407
        "#{@method_name}(#{self.class.name})"
408
      end
409
410
      # Returns a description for the test. A description
411
      # will be associated by Test::Unit::TestCase.test or
412
      # Test::Unit::TestCase.description.
413
      #
414
      # Returns a name for the test for no description test.
415
      def description
416
        self[:description] || name
417
      end
418
419
      # Overridden to return #name.
420
      def to_s
421
        name
422
      end
423
424
      # It's handy to be able to compare TestCase instances.
425
      def ==(other)
426
        return false unless(other.kind_of?(self.class))
427
        return false unless(@method_name == other.method_name)
428
        self.class == other.class
429
      end
430
431
      def interrupted?
432
        @interrupted
433
      end
434
435
      private
436
      def current_result
437
        @_result
438
      end
439
440
      def run_test
441
        __send__(@method_name)
442
      end
443
444
      def handle_exception(exception)
445
        self.class.exception_handlers.each do |handler|
446
          return true if send(handler, exception)
447
        end
448
        false
449
      end
450
451
      # Returns whether this individual test passed or
452
      # not. Primarily for use in teardown so that artifacts
453
      # can be left behind if the test fails.
454
      def passed?
455
        @test_passed
456
      end
457
458
      def problem_occurred
459
        @test_passed = false
460
      end
461
462
      def add_assertion
463
        current_result.add_assertion
464
      end
465
    end
466
  end
467
end