spec 5.0.19 → 5.3.3

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/History.txt +106 -0
  3. data/Manifest.txt +1 -1
  4. data/README.txt +83 -37
  5. data/Rakefile +3 -56
  6. data/lib/minitest.rb +58 -156
  7. data/lib/minitest/assertions.rb +13 -1
  8. data/lib/minitest/benchmark.rb +3 -3
  9. data/lib/minitest/hell.rb +1 -1
  10. data/lib/minitest/mock.rb +2 -2
  11. data/lib/minitest/parallel.rb +40 -0
  12. data/lib/minitest/pride_plugin.rb +1 -2
  13. data/lib/minitest/spec.rb +23 -22
  14. data/lib/minitest/test.rb +19 -8
  15. data/lib/spec.rb +156 -2
  16. data/readme.md +1 -1
  17. data/spec.gemspec +2 -2
  18. data/test/manual/simple.rb +10 -15
  19. data/test/minitest/metametameta.rb +4 -2
  20. data/test/minitest/test_minitest_benchmark.rb +7 -1
  21. data/test/minitest/test_minitest_mock.rb +12 -2
  22. data/test/minitest/test_minitest_reporter.rb +0 -1
  23. data/test/minitest/test_minitest_spec.rb +41 -4
  24. data/test/minitest/test_minitest_unit.rb +38 -20
  25. metadata +15 -37
  26. data/lib/minitest/parallel_each.rb +0 -120
  27. data/release_notes.md +0 -80
  28. data/test/manual/after_run.rb +0 -17
  29. data/test/manual/appium.rb +0 -14
  30. data/test/manual/appium_after_last.rb +0 -24
  31. data/test/manual/appium_before_first.rb +0 -23
  32. data/test/manual/assert.rb +0 -61
  33. data/test/manual/before_first_0.rb +0 -27
  34. data/test/manual/before_first_1.rb +0 -29
  35. data/test/manual/ctrl_c.rb +0 -11
  36. data/test/manual/debug.rb +0 -37
  37. data/test/manual/do_end.rb +0 -31
  38. data/test/manual/raise.rb +0 -61
  39. data/test/manual/run2.rb +0 -74
  40. data/test/manual/run3.rb +0 -91
  41. data/test/manual/setup.rb +0 -13
  42. data/test/manual/simple2.rb +0 -20
  43. data/test/manual/skip.rb +0 -15
  44. data/test/manual/t.rb +0 -11
  45. data/test/manual/trace.rb +0 -19
  46. data/test/manual/trace2.rb +0 -15
  47. data/test/minitest/test_helper.rb +0 -20
@@ -6,7 +6,7 @@ module Minitest
6
6
  # printed if the assertion fails.
7
7
  #
8
8
  # Protocol: Nearly everything here boils up to +assert+, which
9
- # expects to be able to increment an instance variable named
9
+ # expects to be able to increment an instance accessor named
10
10
  # +assertions+. This is not provided by Assertions and must be
11
11
  # provided by the thing including Assertions. See Minitest::Runnable
12
12
  # for an example.
@@ -131,6 +131,10 @@ module Minitest
131
131
  true
132
132
  end
133
133
 
134
+ def _synchronize # :nodoc:
135
+ yield
136
+ end
137
+
134
138
  ##
135
139
  # Fails unless +obj+ is empty.
136
140
 
@@ -393,6 +397,8 @@ module Minitest
393
397
  # that.
394
398
 
395
399
  def capture_io
400
+ _synchronize do
401
+ begin
396
402
  require 'stringio'
397
403
 
398
404
  captured_stdout, captured_stderr = StringIO.new, StringIO.new
@@ -406,6 +412,8 @@ module Minitest
406
412
  ensure
407
413
  $stdout = orig_stdout
408
414
  $stderr = orig_stderr
415
+ end
416
+ end
409
417
  end
410
418
 
411
419
  ##
@@ -424,6 +432,8 @@ module Minitest
424
432
  # only use it when you need to test the output of a subprocess.
425
433
 
426
434
  def capture_subprocess_io
435
+ _synchronize do
436
+ begin
427
437
  require 'tempfile'
428
438
 
429
439
  captured_stdout, captured_stderr = Tempfile.new("out"), Tempfile.new("err")
@@ -443,6 +453,8 @@ module Minitest
443
453
  captured_stderr.unlink
444
454
  $stdout.reopen orig_stdout
445
455
  $stderr.reopen orig_stderr
456
+ end
457
+ end
446
458
  end
447
459
 
448
460
  ##
@@ -376,7 +376,7 @@ module Minitest
376
376
  ##
377
377
  # Create a benchmark that verifies that the performance is linear.
378
378
  #
379
- # describe "my class" do
379
+ # describe "my class Bench" do
380
380
  # bench_performance_linear "fast_algorithm", 0.9999 do |n|
381
381
  # @obj.fast_algorithm(n)
382
382
  # end
@@ -391,7 +391,7 @@ module Minitest
391
391
  ##
392
392
  # Create a benchmark that verifies that the performance is constant.
393
393
  #
394
- # describe "my class" do
394
+ # describe "my class Bench" do
395
395
  # bench_performance_constant "zoom_algorithm!" do |n|
396
396
  # @obj.zoom_algorithm!(n)
397
397
  # end
@@ -406,7 +406,7 @@ module Minitest
406
406
  ##
407
407
  # Create a benchmark that verifies that the performance is exponential.
408
408
  #
409
- # describe "my class" do
409
+ # describe "my class Bench" do
410
410
  # bench_performance_exponential "algorithm" do |n|
411
411
  # @obj.algorithm(n)
412
412
  # end
@@ -1,4 +1,4 @@
1
- require "minitest/parallel_each"
1
+ require "minitest/parallel"
2
2
 
3
3
  class Minitest::Test
4
4
  class << self
@@ -109,7 +109,7 @@ module Minitest # :nodoc:
109
109
  true
110
110
  end
111
111
 
112
- def method_missing(sym, *args) # :nodoc:
112
+ def method_missing(sym, *args, &block) # :nodoc:
113
113
  unless @expected_calls.has_key?(sym) then
114
114
  raise NoMethodError, "unmocked method %p, expected one of %p" %
115
115
  [sym, @expected_calls.keys.sort_by(&:to_s)]
@@ -128,7 +128,7 @@ module Minitest # :nodoc:
128
128
 
129
129
  if val_block then
130
130
  raise MockExpectationError, "mocked method %p failed block w/ %p" %
131
- [sym, args] unless val_block.call(args)
131
+ [sym, args] unless val_block.call(*args, &block)
132
132
 
133
133
  # keep "verify" happy
134
134
  @actual_calls[sym] << expected_call
@@ -0,0 +1,40 @@
1
+ module Minitest
2
+ module Parallel
3
+ class Executor
4
+ attr_reader :size
5
+
6
+ def initialize size
7
+ @size = size
8
+ @queue = Queue.new
9
+ @pool = size.times.map {
10
+ Thread.new(@queue) do |queue|
11
+ Thread.current.abort_on_exception = true
12
+ while job = queue.pop
13
+ klass, method, reporter = job
14
+ result = Minitest.run_one_method klass, method
15
+ reporter.synchronize { reporter.record result }
16
+ end
17
+ end
18
+ }
19
+ end
20
+
21
+ def << work; @queue << work; end
22
+
23
+ def shutdown
24
+ size.times { @queue << nil }
25
+ @pool.each(&:join)
26
+ end
27
+ end
28
+
29
+ module Test
30
+ def _synchronize; Test.io_lock.synchronize { yield }; end
31
+
32
+ module ClassMethods
33
+ def run_one_method klass, method_name, reporter
34
+ Minitest.parallel_executor << [klass, method_name, reporter]
35
+ end
36
+ def test_order; :parallel; end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,4 +1,4 @@
1
- require "minitest/autorun"
1
+ require "minitest"
2
2
 
3
3
  module Minitest
4
4
  def self.plugin_pride_options opts, options # :nodoc:
@@ -52,7 +52,6 @@ module Minitest
52
52
  @colors ||= (31..36).to_a
53
53
  @size = @colors.size
54
54
  @index = 0
55
- # io.sync = true
56
55
  end
57
56
 
58
57
  ##
@@ -1,5 +1,3 @@
1
- #!/usr/bin/ruby -w
2
-
3
1
  require 'minitest/unit'
4
2
 
5
3
  class Module # :nodoc:
@@ -8,10 +6,10 @@ class Module # :nodoc:
8
6
  self.class_eval <<-EOM
9
7
  def #{new_name} *args
10
8
  case
11
- when Proc === self then
12
- Minitest::Spec.current.#{meth}(*args, &self)
13
9
  when #{!!dont_flip} then
14
10
  Minitest::Spec.current.#{meth}(self, *args)
11
+ when Proc === self then
12
+ Minitest::Spec.current.#{meth}(*args, &self)
15
13
  else
16
14
  Minitest::Spec.current.#{meth}(args.first, self, *args[1..-1])
17
15
  end
@@ -161,13 +159,6 @@ class Minitest::Spec < Minitest::Test
161
159
  end
162
160
  end
163
161
 
164
- def before_first type = nil, &block
165
- define_method :before_first_method do
166
- super()
167
- self.instance_eval(&block)
168
- end
169
- end
170
-
171
162
  ##
172
163
  # Define a 'before' action. Inherits the way normal methods should.
173
164
  #
@@ -196,13 +187,6 @@ class Minitest::Spec < Minitest::Test
196
187
  end
197
188
  end
198
189
 
199
- def after_last type = nil, &block
200
- define_method :after_last_method do
201
- self.instance_eval(&block)
202
- super()
203
- end
204
- end
205
-
206
190
  ##
207
191
  # Define an expectation with name +desc+. Name gets morphed to a
208
192
  # proper test method name. For some freakish reason, people who
@@ -211,7 +195,7 @@ class Minitest::Spec < Minitest::Test
211
195
  #
212
196
  # This is also aliased to #specify and doesn't require a +desc+ arg.
213
197
  #
214
- # Hint: If you _do_ want inheritence, use minitest/test. You can mix
198
+ # Hint: If you _do_ want inheritance, use minitest/test. You can mix
215
199
  # and match between assertions and expectations as much as you want.
216
200
 
217
201
  def it desc = "anonymous", &block
@@ -231,15 +215,20 @@ class Minitest::Spec < Minitest::Test
231
215
  name
232
216
  end
233
217
 
234
- alias_method :t, :it
235
-
236
218
  ##
237
219
  # Essentially, define an accessor for +name+ with +block+.
238
220
  #
239
221
  # Why use let instead of def? I honestly don't know.
240
222
 
241
223
  def let name, &block
242
- raise ArgumentError, 'name cannot begin with "test"' if name.to_s =~ /\Atest/
224
+ name = name.to_s
225
+ pre, post = "let '#{name}' cannot ", ". Please use another name."
226
+ methods = Minitest::Spec.instance_methods.map(&:to_s) - %w[subject]
227
+ raise ArgumentError, "#{pre}begin with 'test'#{post}" if
228
+ name =~ /\Atest/
229
+ raise ArgumentError, "#{pre}override a method in Minitest::Spec#{post}" if
230
+ methods.include? name
231
+
243
232
  define_method name do
244
233
  @_memoized ||= {}
245
234
  @_memoized.fetch(name) { |k| @_memoized[k] = instance_eval(&block) }
@@ -278,6 +267,18 @@ class Minitest::Spec < Minitest::Test
278
267
  # :stopdoc:
279
268
  attr_reader :desc
280
269
  alias :specify :it
270
+
271
+ module InstanceMethods
272
+ def before_setup
273
+ super
274
+ Thread.current[:current_spec] = self
275
+ end
276
+ end
277
+
278
+ def self.extended obj
279
+ obj.send :include, InstanceMethods
280
+ end
281
+
281
282
  # :startdoc:
282
283
  end
283
284
 
@@ -14,6 +14,9 @@ module Minitest
14
14
  PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, # :nodoc:
15
15
  Interrupt, SystemExit]
16
16
 
17
+ class << self; attr_accessor :io_lock; end
18
+ self.io_lock = Mutex.new
19
+
17
20
  ##
18
21
  # Call this at the top of your tests when you absolutely
19
22
  # positively need to have ordered tests. In doing so, you're
@@ -46,19 +49,27 @@ module Minitest
46
49
  # and your tests are awesome.
47
50
 
48
51
  def self.parallelize_me!
49
- require "minitest/parallel_each"
50
-
51
- class << self
52
- undef_method :test_order if method_defined? :test_order
53
- define_method :test_order do :parallel end
54
- end
52
+ include Minitest::Parallel::Test
53
+ extend Minitest::Parallel::Test::ClassMethods
55
54
  end
56
55
 
57
56
  ##
58
- # Returns all instance methods starting with "test_".
57
+ # Returns all instance methods starting with "test_". Based on
58
+ # #test_order, the methods are either sorted, randomized
59
+ # (default), or run in parallel.
59
60
 
60
61
  def self.runnable_methods
61
- methods_matching(/^test_/)
62
+ methods = methods_matching(/^test_/)
63
+
64
+ case self.test_order
65
+ when :random, :parallel then
66
+ max = methods.size
67
+ methods.sort.sort_by { rand max }
68
+ when :alpha, :sorted then
69
+ methods.sort
70
+ else
71
+ raise "Unknown test_order: #{self.test_order.inspect}"
72
+ end
62
73
  end
63
74
 
64
75
  ##
@@ -1,3 +1,157 @@
1
1
  # enable require 'spec'
2
- require File.expand_path '../minitest.rb', __FILE__
3
- require File.expand_path '../minitest/spec.rb', __FILE__
2
+ require_relative 'minitest'
3
+ require_relative 'minitest/spec'
4
+
5
+ # patches to enable Appium spec
6
+
7
+ require 'rubygems'
8
+ require 'chronic_duration'
9
+
10
+
11
+ module Minitest
12
+ # override minitest.rb __run so tests execute serially
13
+ def self.__run reporter, options
14
+ Runnable.runnables.each do |runnable|
15
+ runnable.run reporter, options
16
+ end
17
+ end
18
+
19
+ ##
20
+ # Trace file source to :io (default $stdout)
21
+ #
22
+ # spec_opts = {}
23
+ #
24
+ # @param :trace [Array<String>] the files to trace
25
+ # @param :io [IO] io to print to
26
+ def self.trace_specs spec_opts
27
+ targets = []
28
+ files = {}
29
+ last_file = ''
30
+ last_line = -1
31
+
32
+ files_to_trace = spec_opts.fetch(:trace, []);
33
+ io = spec_opts.fetch(:io, $stdout)
34
+ color = spec_opts.fetch(:color, "\e[32m") # ANSI.green default
35
+ # target only existing readable files
36
+ files_to_trace.each do |f|
37
+ if File.exists?(f) && File.readable?(f)
38
+ targets.push File.expand_path f
39
+ targets.push File.basename f # sometimes the file is relative
40
+ end
41
+ end
42
+ return if targets.empty?
43
+
44
+ set_trace_func(lambda do |event, file, line, id, binding, classname|
45
+ return unless targets.include?(file)
46
+
47
+ # never repeat a line
48
+ return if file == last_file && line == last_line
49
+
50
+ file_sym = file.intern
51
+ files[file_sym] = IO.readlines(file) if files[file_sym].nil?
52
+ lines = files[file_sym]
53
+
54
+ # arrays are 0 indexed and line numbers start at one.
55
+ io.print color if color # ANSI code
56
+ io.puts lines[line - 1]
57
+ io.print "\e[0m" if color # ANSI.clear
58
+
59
+ last_file = file
60
+ last_line = line
61
+
62
+ end)
63
+ end
64
+
65
+ def self.on_exit exit_code
66
+ @@after_run.reverse_each(&:call)
67
+ exit exit_code || false
68
+ end
69
+
70
+ ##
71
+ # Run specs. Does not print dots (ProgressReporter)
72
+ #
73
+ # spec_opts
74
+ # @param :io [Array<String>] defaults to $stdout
75
+ # @param :trace [Array<String>] files to trace
76
+ def self.run_specs spec_opts={}
77
+ options = { :io => spec_opts.fetch(:io, $stdout),
78
+ :verbose => spec_opts.fetch(:verbose, false) }
79
+ reporter = Minitest::CompositeReporter.new
80
+ reporter << Minitest::SummaryReporter.new(options[:io], options)
81
+ reporter.start
82
+
83
+ at_exit { on_exit reporter.passed? }
84
+ # exit on ctrl+c to trigger at_exit
85
+ trap('SIGINT') { exit }
86
+
87
+ trace_specs spec_opts
88
+
89
+ Minitest.__run reporter, options
90
+ reporter.reporters.each { |r| r.report }
91
+ end
92
+
93
+ ##
94
+ # Responsible for running all runnable methods in a given class,
95
+ # each in its own instance. Each instance is passed to the
96
+ # reporter to record.
97
+
98
+ def self.run reporter, options = {}
99
+ filter = options[:filter] || '/./'
100
+ filter = Regexp.new $1 if filter =~ /\/(.*)\//
101
+
102
+ filtered_methods = self.runnable_methods.find_all { |m|
103
+ filter === m || filter === "#{self}##{m}"
104
+ }
105
+
106
+ with_info_handler reporter do
107
+ filtered_methods.each do |method_name|
108
+
109
+ method = self.new(method_name)
110
+ matched_name = method_name.match /test_(\d+)_/
111
+ if matched_name
112
+ test_number = matched_name[1].to_i
113
+ test_name = method_name.split(/_\d+_/).last
114
+ file_path, line_number = method.method(method_name).source_location
115
+ # /5/4/3/2/1/test.rb => 2/1/test.rb
116
+ file_path = file_path.split(File::SEPARATOR).reject(&:empty?)
117
+ file_path = (file_path.length >= 3 ? file_path[-3..-1] :
118
+ file_path).join(File::SEPARATOR)
119
+ # 36 = cyan, 0 = clear
120
+ test_output_title = "\e[36m#{test_name} | #{test_number} |" +
121
+ "#{file_path}:#{line_number}\e[0m"
122
+ io.puts test_output_title
123
+ end
124
+
125
+ run_one_method self, method_name, reporter
126
+ end
127
+ end
128
+ end
129
+
130
+ class Test < Runnable
131
+ # override lib/minitest/test.rb so methods execute in the exact order they are defined
132
+ def self.runnable_methods
133
+ methods_matching(/^test_/)
134
+ end
135
+ end
136
+
137
+ class SummaryReporter < StatisticsReporter
138
+ # remove dots
139
+ def start # :nodoc:
140
+ super
141
+
142
+ self.sync = io.respond_to? :"sync=" # stupid emacs
143
+ self.old_sync, io.sync = io.sync, true if self.sync
144
+ end
145
+
146
+ # customize stats
147
+ def statistics # :nodoc:
148
+ "Finished in #{ChronicDuration.output(total_time.round) || '0s'}"
149
+ end
150
+ end
151
+
152
+ class Minitest::Spec < Minitest::Test
153
+ module DSL
154
+ alias_method :t, :it
155
+ end
156
+ end
157
+ end