opal-minitest 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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