opal-minitest 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,571 @@
1
+ module Minitest
2
+ ##
3
+ # Represents anything "runnable", like Test, Spec, Benchmark, or
4
+ # whatever you can dream up.
5
+ #
6
+ # Subclasses of this are automatically registered and available in
7
+ # Runnable.runnables.
8
+
9
+ class Runnable
10
+ ##
11
+ # Number of assertions executed in this run.
12
+
13
+ attr_accessor :assertions
14
+
15
+ ##
16
+ # An assertion raised during the run, if any.
17
+
18
+ attr_accessor :failures
19
+
20
+ ##
21
+ # Name of the run.
22
+
23
+ def name
24
+ @NAME
25
+ end
26
+
27
+ ##
28
+ # Set the name of the run.
29
+
30
+ def name= o
31
+ @NAME = o
32
+ end
33
+
34
+ def self.inherited klass # :nodoc:
35
+ self.runnables << klass
36
+ super
37
+ end
38
+
39
+ ##
40
+ # Returns all instance methods matching the pattern +re+.
41
+
42
+ def self.methods_matching re
43
+ public_instance_methods(true).grep(re).map(&:to_s)
44
+ end
45
+
46
+ def self.reset # :nodoc:
47
+ @@runnables = []
48
+ end
49
+
50
+ reset
51
+
52
+ ##
53
+ # Responsible for running all runnable methods in a given class,
54
+ # each in its own instance. Each instance is passed to the
55
+ # reporter to record.
56
+
57
+ def self.run reporter, options = {}
58
+ filter = options[:filter] || '/./'
59
+ filter = Regexp.new $1 if filter =~ /\/(.*)\//
60
+
61
+ filtered_methods = self.runnable_methods.find_all { |m|
62
+ filter === m || filter === "#{self}##{m}"
63
+ }
64
+
65
+ with_info_handler reporter do
66
+ filtered_methods.each do |method_name|
67
+ run_one_method self, method_name, reporter
68
+ end
69
+ end
70
+ end
71
+
72
+ def self.run_one_method klass, method_name, reporter
73
+ reporter.record Minitest.run_one_method(klass, method_name)
74
+ end
75
+
76
+ def self.with_info_handler reporter, &block # :nodoc:
77
+ handler = lambda do
78
+ unless reporter.passed? then
79
+ warn "Current results:"
80
+ warn ""
81
+ warn reporter.reporters.first
82
+ warn ""
83
+ end
84
+ end
85
+
86
+ on_signal "INFO", handler, &block
87
+ end
88
+
89
+ def self.on_signal name, action # :nodoc:
90
+ # OMT: modified
91
+ #supported = Signal.list[name]
92
+
93
+ #old_trap = trap name do
94
+ # old_trap.call if old_trap.respond_to? :call
95
+ # action.call
96
+ #end if supported
97
+
98
+ #yield
99
+ #ensure
100
+ #trap name, old_trap if supported
101
+
102
+ yield
103
+ end
104
+
105
+ ##
106
+ # Each subclass of Runnable is responsible for overriding this
107
+ # method to return all runnable methods. See #methods_matching.
108
+
109
+ def self.runnable_methods
110
+ raise NotImplementedError, "subclass responsibility"
111
+ end
112
+
113
+ ##
114
+ # Returns all subclasses of Runnable.
115
+
116
+ def self.runnables
117
+ @@runnables
118
+ end
119
+
120
+ def marshal_dump # :nodoc:
121
+ [self.name, self.failures, self.assertions]
122
+ end
123
+
124
+ def marshal_load ary # :nodoc:
125
+ self.name, self.failures, self.assertions = ary
126
+ end
127
+
128
+ def failure # :nodoc:
129
+ self.failures.first
130
+ end
131
+
132
+ def initialize name # :nodoc:
133
+ self.name = name
134
+ self.failures = []
135
+ self.assertions = 0
136
+ end
137
+
138
+ ##
139
+ # Runs a single method. Needs to return self.
140
+
141
+ def run
142
+ raise NotImplementedError, "subclass responsibility"
143
+ end
144
+
145
+ ##
146
+ # Did this run pass?
147
+ #
148
+ # Note: skipped runs are not considered passing, but they don't
149
+ # cause the process to exit non-zero.
150
+
151
+ def passed?
152
+ raise NotImplementedError, "subclass responsibility"
153
+ end
154
+
155
+ ##
156
+ # Returns a single character string to print based on the result
157
+ # of the run. Eg ".", "F", or "E".
158
+
159
+ def result_code
160
+ raise NotImplementedError, "subclass responsibility"
161
+ end
162
+
163
+ ##
164
+ # Was this run skipped? See #passed? for more information.
165
+
166
+ def skipped?
167
+ raise NotImplementedError, "subclass responsibility"
168
+ end
169
+ end
170
+
171
+ ##
172
+ # Defines the API for Reporters. Subclass this and override whatever
173
+ # you want. Go nuts.
174
+
175
+ class AbstractReporter
176
+ # OMT: unsupported
177
+ #include Mutex_m
178
+
179
+ ##
180
+ # Starts reporting on the run.
181
+
182
+ def start
183
+ end
184
+
185
+ ##
186
+ # Record a result and output the Runnable#result_code. Stores the
187
+ # result of the run if the run did not pass.
188
+
189
+ def record result
190
+ end
191
+
192
+ ##
193
+ # Outputs the summary of the run.
194
+
195
+ def report
196
+ end
197
+
198
+ ##
199
+ # Did this run pass?
200
+
201
+ def passed?
202
+ true
203
+ end
204
+ end
205
+
206
+ class Reporter < AbstractReporter # :nodoc:
207
+ ##
208
+ # The IO used to report.
209
+
210
+ attr_accessor :io
211
+
212
+ ##
213
+ # Command-line options for this run.
214
+
215
+ attr_accessor :options
216
+
217
+ def initialize io = $stdout, options = {} # :nodoc:
218
+ super()
219
+ self.io = io
220
+ self.options = options
221
+ end
222
+ end
223
+
224
+ ##
225
+ # A very simple reporter that prints the "dots" during the run.
226
+ #
227
+ # This is added to the top-level CompositeReporter at the start of
228
+ # the run. If you want to change the output of minitest via a
229
+ # plugin, pull this out of the composite and replace it with your
230
+ # own.
231
+
232
+ class ProgressReporter < Reporter
233
+ def record result # :nodoc:
234
+ io.print "%s#%s = %.2f s = " % [result.class, result.name, result.time] if
235
+ options[:verbose]
236
+ io.print result.result_code
237
+ io.puts if options[:verbose]
238
+ end
239
+ end
240
+
241
+ ##
242
+ # A reporter that gathers statistics about a test run. Does not do
243
+ # any IO because meant to be used as a parent class for a reporter
244
+ # that does.
245
+ #
246
+ # If you want to create an entirely different type of output (eg,
247
+ # CI, HTML, etc), this is the place to start.
248
+
249
+ class StatisticsReporter < Reporter
250
+ # :stopdoc:
251
+ attr_accessor :assertions
252
+ attr_accessor :count
253
+ attr_accessor :results
254
+ attr_accessor :start_time
255
+ attr_accessor :total_time
256
+ attr_accessor :failures
257
+ attr_accessor :errors
258
+ attr_accessor :skips
259
+ # :startdoc:
260
+
261
+ def initialize io = $stdout, options = {} # :nodoc:
262
+ super
263
+
264
+ self.assertions = 0
265
+ self.count = 0
266
+ self.results = []
267
+ self.start_time = nil
268
+ self.total_time = nil
269
+ self.failures = nil
270
+ self.errors = nil
271
+ self.skips = nil
272
+ end
273
+
274
+ def passed? # :nodoc:
275
+ results.all?(&:skipped?)
276
+ end
277
+
278
+ def start # :nodoc:
279
+ self.start_time = Time.now
280
+ end
281
+
282
+ def record result # :nodoc:
283
+ self.count += 1
284
+ self.assertions += result.assertions
285
+
286
+ results << result if not result.passed? or result.skipped?
287
+ end
288
+
289
+ def report # :nodoc:
290
+ aggregate = results.group_by { |r| r.failure.class }
291
+ aggregate.default = [] # dumb. group_by should provide this
292
+
293
+ self.total_time = Time.now - start_time
294
+ self.failures = aggregate[Assertion].size
295
+ self.errors = aggregate[UnexpectedError].size
296
+ self.skips = aggregate[Skip].size
297
+ end
298
+ end
299
+
300
+ ##
301
+ # A reporter that prints the header, summary, and failure details at
302
+ # the end of the run.
303
+ #
304
+ # This is added to the top-level CompositeReporter at the start of
305
+ # the run. If you want to change the output of minitest via a
306
+ # plugin, pull this out of the composite and replace it with your
307
+ # own.
308
+
309
+ class SummaryReporter < StatisticsReporter
310
+ # :stopdoc:
311
+ attr_accessor :sync
312
+ attr_accessor :old_sync
313
+ # :startdoc:
314
+
315
+ def start # :nodoc:
316
+ super
317
+
318
+ io.puts "Run options: #{options[:args]}"
319
+ io.puts
320
+ io.puts "# Running:"
321
+ io.puts
322
+
323
+ self.sync = io.respond_to? :"sync=" # stupid emacs
324
+ self.old_sync, io.sync = io.sync, true if self.sync
325
+ end
326
+
327
+ def report # :nodoc:
328
+ super
329
+
330
+ # OMT: unsupported
331
+ #io.sync = self.old_sync
332
+
333
+ io.puts unless options[:verbose] # finish the dots
334
+ io.puts
335
+ io.puts statistics
336
+ io.puts aggregated_results
337
+ io.puts summary
338
+ end
339
+
340
+ def statistics # :nodoc:
341
+ "Finished in %.6fs, %.4f runs/s, %.4f assertions/s." %
342
+ [total_time, count / total_time, assertions / total_time]
343
+ end
344
+
345
+ def aggregated_results # :nodoc:
346
+ filtered_results = results.dup
347
+ filtered_results.reject!(&:skipped?) unless options[:verbose]
348
+
349
+ filtered_results.each_with_index.map do |result, i|
350
+ "\n%3d) %s" % [i+1, result]
351
+ end.join("\n") + "\n"
352
+ end
353
+
354
+ alias to_s aggregated_results
355
+
356
+ def summary # :nodoc:
357
+ extra = ""
358
+
359
+ extra = "\n\nYou have skipped tests. Run with --verbose for details." if
360
+ results.any?(&:skipped?) unless options[:verbose] or ENV["MT_NO_SKIP_MSG"]
361
+
362
+ "%d runs, %d assertions, %d failures, %d errors, %d skips%s" %
363
+ [count, assertions, failures, errors, skips, extra]
364
+ end
365
+ end
366
+
367
+ ##
368
+ # Dispatch to multiple reporters as one.
369
+
370
+ class CompositeReporter < AbstractReporter
371
+ ##
372
+ # The list of reporters to dispatch to.
373
+
374
+ attr_accessor :reporters
375
+
376
+ def initialize *reporters # :nodoc:
377
+ super()
378
+ self.reporters = reporters
379
+ end
380
+
381
+ ##
382
+ # Add another reporter to the mix.
383
+
384
+ def << reporter
385
+ self.reporters << reporter
386
+ end
387
+
388
+ def passed? # :nodoc:
389
+ self.reporters.all?(&:passed?)
390
+ end
391
+
392
+ def start # :nodoc:
393
+ self.reporters.each(&:start)
394
+ end
395
+
396
+ def record result # :nodoc:
397
+ self.reporters.each do |reporter|
398
+ reporter.record result
399
+ end
400
+ end
401
+
402
+ def report # :nodoc:
403
+ self.reporters.each(&:report)
404
+ end
405
+ end
406
+
407
+ ##
408
+ # Represents run failures.
409
+
410
+ # OMT: modified
411
+ #class Assertion < Exception
412
+ class Assertion
413
+ def error # :nodoc:
414
+ self
415
+ end
416
+
417
+ ##
418
+ # Where was this run before an assertion was raised?
419
+
420
+ def location
421
+ last_before_assertion = ""
422
+ self.backtrace.reverse_each do |s|
423
+ break if s =~ /in .(assert|refute|flunk|pass|fail|raise|must|wont)/
424
+ last_before_assertion = s
425
+ end
426
+ last_before_assertion.sub(/:in .*$/, "")
427
+ end
428
+
429
+ def result_code # :nodoc:
430
+ result_label[0, 1]
431
+ end
432
+
433
+ def result_label # :nodoc:
434
+ "Failure"
435
+ end
436
+
437
+ # OMT: added
438
+ def initialize(message = '')
439
+ @message = message
440
+ end
441
+
442
+ # OMT: added
443
+ attr_reader :message
444
+
445
+ # OMT: added
446
+ def backtrace
447
+ []
448
+ end
449
+
450
+ # OMT: added
451
+ def inspect
452
+ "#<#{self.class.name}: '#@message'>"
453
+ end
454
+
455
+ # OMT: added
456
+ alias to_s message
457
+ end
458
+
459
+ ##
460
+ # Assertion raised when skipping a run.
461
+
462
+ class Skip < Assertion
463
+ def result_label # :nodoc:
464
+ "Skipped"
465
+ end
466
+ end
467
+
468
+ ##
469
+ # Assertion wrapping an unexpected error that was raised during a run.
470
+
471
+ class UnexpectedError < Assertion
472
+ attr_accessor :exception # :nodoc:
473
+
474
+ def initialize exception # :nodoc:
475
+ super
476
+ self.exception = exception
477
+ end
478
+
479
+ def backtrace # :nodoc:
480
+ self.exception.backtrace
481
+ end
482
+
483
+ def error # :nodoc:
484
+ self.exception
485
+ end
486
+
487
+ def message # :nodoc:
488
+ bt = Minitest::filter_backtrace(self.backtrace).join "\n "
489
+ "#{self.exception.class}: #{self.exception.message}\n #{bt}"
490
+ end
491
+
492
+ def result_label # :nodoc:
493
+ "Error"
494
+ end
495
+ end
496
+
497
+ ##
498
+ # Provides a simple set of guards that you can use in your tests
499
+ # to skip execution if it is not applicable. These methods are
500
+ # mixed into Test as both instance and class methods so you
501
+ # can use them inside or outside of the test methods.
502
+ #
503
+ # def test_something_for_mri
504
+ # skip "bug 1234" if jruby?
505
+ # # ...
506
+ # end
507
+ #
508
+ # if windows? then
509
+ # # ... lots of test methods ...
510
+ # end
511
+
512
+ module Guard
513
+
514
+ ##
515
+ # Is this running on opal?
516
+ # OMT: added
517
+
518
+ def opal? platform = RUBY_PLATFORM
519
+ "opal" == platform
520
+ end
521
+
522
+ ##
523
+ # Is this running on jruby?
524
+
525
+ def jruby? platform = RUBY_PLATFORM
526
+ "java" == platform
527
+ end
528
+
529
+ ##
530
+ # Is this running on maglev?
531
+
532
+ def maglev? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
533
+ "maglev" == platform
534
+ end
535
+
536
+ ##
537
+ # Is this running on mri?
538
+
539
+ def mri? platform = RUBY_DESCRIPTION
540
+ /^ruby/ =~ platform
541
+ end
542
+
543
+ ##
544
+ # Is this running on rubinius?
545
+
546
+ def rubinius? platform = defined?(RUBY_ENGINE) && RUBY_ENGINE
547
+ "rbx" == platform
548
+ end
549
+
550
+ ##
551
+ # Is this running on windows?
552
+
553
+ def windows? platform = RUBY_PLATFORM
554
+ /mswin|mingw/ =~ platform
555
+ end
556
+ end
557
+
558
+ class BacktraceFilter # :nodoc:
559
+ def filter bt
560
+ return ["No backtrace"] unless bt
561
+
562
+ return bt.dup if $DEBUG
563
+
564
+ new_bt = bt.take_while { |line| line !~ /lib\/minitest/ }
565
+ new_bt = bt.select { |line| line !~ /lib\/minitest/ } if new_bt.empty?
566
+ new_bt = bt.dup if new_bt.empty?
567
+
568
+ new_bt
569
+ end
570
+ end
571
+ end