spec 5.0.14

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 (51) hide show
  1. checksums.yaml +7 -0
  2. data/.autotest +34 -0
  3. data/.gitignore +3 -0
  4. data/History.txt +911 -0
  5. data/Manifest.txt +26 -0
  6. data/README.txt +497 -0
  7. data/Rakefile +214 -0
  8. data/design_rationale.rb +52 -0
  9. data/lib/hoe/minitest.rb +26 -0
  10. data/lib/minitest/assertions.rb +649 -0
  11. data/lib/minitest/autorun.rb +12 -0
  12. data/lib/minitest/benchmark.rb +423 -0
  13. data/lib/minitest/expectations.rb +268 -0
  14. data/lib/minitest/hell.rb +11 -0
  15. data/lib/minitest/mock.rb +220 -0
  16. data/lib/minitest/parallel_each.rb +120 -0
  17. data/lib/minitest/pride.rb +4 -0
  18. data/lib/minitest/pride_plugin.rb +143 -0
  19. data/lib/minitest/spec.rb +292 -0
  20. data/lib/minitest/test.rb +272 -0
  21. data/lib/minitest/unit.rb +45 -0
  22. data/lib/minitest.rb +839 -0
  23. data/lib/spec.rb +3 -0
  24. data/readme.md +7 -0
  25. data/release_notes.md +49 -0
  26. data/spec.gemspec +36 -0
  27. data/test/manual/appium.rb +14 -0
  28. data/test/manual/appium_after_last.rb +24 -0
  29. data/test/manual/appium_before_first.rb +23 -0
  30. data/test/manual/assert.rb +61 -0
  31. data/test/manual/before_first_0.rb +27 -0
  32. data/test/manual/before_first_1.rb +29 -0
  33. data/test/manual/debug.rb +37 -0
  34. data/test/manual/do_end.rb +31 -0
  35. data/test/manual/raise.rb +61 -0
  36. data/test/manual/run2.rb +74 -0
  37. data/test/manual/run3.rb +91 -0
  38. data/test/manual/setup.rb +13 -0
  39. data/test/manual/simple.rb +19 -0
  40. data/test/manual/simple2.rb +20 -0
  41. data/test/manual/t.rb +11 -0
  42. data/test/manual/trace.rb +19 -0
  43. data/test/manual/trace2.rb +15 -0
  44. data/test/minitest/metametameta.rb +78 -0
  45. data/test/minitest/test_helper.rb +20 -0
  46. data/test/minitest/test_minitest_benchmark.rb +131 -0
  47. data/test/minitest/test_minitest_mock.rb +490 -0
  48. data/test/minitest/test_minitest_reporter.rb +270 -0
  49. data/test/minitest/test_minitest_spec.rb +794 -0
  50. data/test/minitest/test_minitest_unit.rb +1846 -0
  51. metadata +147 -0
@@ -0,0 +1,220 @@
1
+ class MockExpectationError < StandardError; end # :nodoc:
2
+
3
+ module Minitest # :nodoc:
4
+
5
+ ##
6
+ # A simple and clean mock object framework.
7
+ #
8
+ # All mock objects are an instance of Mock
9
+
10
+ class Mock
11
+ alias :__respond_to? :respond_to?
12
+
13
+ overridden_methods = %w(
14
+ ===
15
+ inspect
16
+ object_id
17
+ public_send
18
+ respond_to_missing?
19
+ send
20
+ to_s
21
+ )
22
+
23
+ instance_methods.each do |m|
24
+ undef_method m unless overridden_methods.include?(m.to_s) || m =~ /^__/
25
+ end
26
+
27
+ overridden_methods.map(&:to_sym).each do |method_id|
28
+ define_method method_id do |*args, &b|
29
+ if @expected_calls.has_key? method_id then
30
+ method_missing(method_id, *args, &b)
31
+ else
32
+ super(*args, &b)
33
+ end
34
+ end
35
+ end
36
+
37
+ def initialize # :nodoc:
38
+ @expected_calls = Hash.new { |calls, name| calls[name] = [] }
39
+ @actual_calls = Hash.new { |calls, name| calls[name] = [] }
40
+ end
41
+
42
+ ##
43
+ # Expect that method +name+ is called, optionally with +args+ or a
44
+ # +blk+, and returns +retval+.
45
+ #
46
+ # @mock.expect(:meaning_of_life, 42)
47
+ # @mock.meaning_of_life # => 42
48
+ #
49
+ # @mock.expect(:do_something_with, true, [some_obj, true])
50
+ # @mock.do_something_with(some_obj, true) # => true
51
+ #
52
+ # @mock.expect(:do_something_else, true) do |a1, a2|
53
+ # a1 == "buggs" && a2 == :bunny
54
+ # end
55
+ #
56
+ # +args+ is compared to the expected args using case equality (ie, the
57
+ # '===' operator), allowing for less specific expectations.
58
+ #
59
+ # @mock.expect(:uses_any_string, true, [String])
60
+ # @mock.uses_any_string("foo") # => true
61
+ # @mock.verify # => true
62
+ #
63
+ # @mock.expect(:uses_one_string, true, ["foo"])
64
+ # @mock.uses_one_string("bar") # => true
65
+ # @mock.verify # => raises MockExpectationError
66
+
67
+ def expect(name, retval, args=[], &blk)
68
+ name = name.to_sym
69
+
70
+ if block_given?
71
+ raise ArgumentError, "args ignored when block given" unless args.empty?
72
+ @expected_calls[name] << { :retval => retval, :block => blk }
73
+ else
74
+ raise ArgumentError, "args must be an array" unless Array === args
75
+ @expected_calls[name] << { :retval => retval, :args => args }
76
+ end
77
+ self
78
+ end
79
+
80
+ def __call name, data # :nodoc:
81
+ case data
82
+ when Hash then
83
+ "#{name}(#{data[:args].inspect[1..-2]}) => #{data[:retval].inspect}"
84
+ else
85
+ data.map { |d| __call name, d }.join ", "
86
+ end
87
+ end
88
+
89
+ ##
90
+ # Verify that all methods were called as expected. Raises
91
+ # +MockExpectationError+ if the mock object was not called as
92
+ # expected.
93
+
94
+ def verify
95
+ @expected_calls.each do |name, calls|
96
+ calls.each do |expected|
97
+ msg1 = "expected #{__call name, expected}"
98
+ msg2 = "#{msg1}, got [#{__call name, @actual_calls[name]}]"
99
+
100
+ raise MockExpectationError, msg2 if
101
+ @actual_calls.has_key?(name) and
102
+ not @actual_calls[name].include?(expected)
103
+
104
+ raise MockExpectationError, msg1 unless
105
+ @actual_calls.has_key?(name) and
106
+ @actual_calls[name].include?(expected)
107
+ end
108
+ end
109
+ true
110
+ end
111
+
112
+ def method_missing(sym, *args) # :nodoc:
113
+ unless @expected_calls.has_key?(sym) then
114
+ raise NoMethodError, "unmocked method %p, expected one of %p" %
115
+ [sym, @expected_calls.keys.sort_by(&:to_s)]
116
+ end
117
+
118
+ index = @actual_calls[sym].length
119
+ expected_call = @expected_calls[sym][index]
120
+
121
+ unless expected_call then
122
+ raise MockExpectationError, "No more expects available for %p: %p" %
123
+ [sym, args]
124
+ end
125
+
126
+ expected_args, retval, val_block =
127
+ expected_call.values_at(:args, :retval, :block)
128
+
129
+ if val_block then
130
+ raise MockExpectationError, "mocked method %p failed block w/ %p" %
131
+ [sym, args] unless val_block.call(args)
132
+
133
+ # keep "verify" happy
134
+ @actual_calls[sym] << expected_call
135
+ return retval
136
+ end
137
+
138
+ if expected_args.size != args.size then
139
+ raise ArgumentError, "mocked method %p expects %d arguments, got %d" %
140
+ [sym, expected_args.size, args.size]
141
+ end
142
+
143
+ fully_matched = expected_args.zip(args).all? { |mod, a|
144
+ mod === a or mod == a
145
+ }
146
+
147
+ unless fully_matched then
148
+ raise MockExpectationError, "mocked method %p called with unexpected arguments %p" %
149
+ [sym, args]
150
+ end
151
+
152
+ @actual_calls[sym] << {
153
+ :retval => retval,
154
+ :args => expected_args.zip(args).map { |mod, a| mod === a ? mod : a }
155
+ }
156
+
157
+ retval
158
+ end
159
+
160
+ def respond_to?(sym, include_private = false) # :nodoc:
161
+ return true if @expected_calls.has_key? sym.to_sym
162
+ return __respond_to?(sym, include_private)
163
+ end
164
+ end
165
+ end
166
+
167
+ class Object # :nodoc:
168
+
169
+ ##
170
+ # Add a temporary stubbed method replacing +name+ for the duration
171
+ # of the +block+. If +val_or_callable+ responds to #call, then it
172
+ # returns the result of calling it, otherwise returns the value
173
+ # as-is. If stubbed method yields a block, +block_args+ will be
174
+ # passed along. Cleans up the stub at the end of the +block+. The
175
+ # method +name+ must exist before stubbing.
176
+ #
177
+ # def test_stale_eh
178
+ # obj_under_test = Something.new
179
+ # refute obj_under_test.stale?
180
+ #
181
+ # Time.stub :now, Time.at(0) do
182
+ # assert obj_under_test.stale?
183
+ # end
184
+ # end
185
+ #
186
+
187
+ def stub name, val_or_callable, *block_args, &block
188
+ new_name = "__minitest_stub__#{name}"
189
+
190
+ metaclass = class << self; self; end
191
+
192
+ if respond_to? name and not methods.map(&:to_s).include? name.to_s then
193
+ metaclass.send :define_method, name do |*args|
194
+ super(*args)
195
+ end
196
+ end
197
+
198
+ metaclass.send :alias_method, new_name, name
199
+
200
+ metaclass.send :define_method, name do |*args, &blk|
201
+
202
+ ret = if val_or_callable.respond_to? :call then
203
+ val_or_callable.call(*args)
204
+ else
205
+ val_or_callable
206
+ end
207
+
208
+ blk.call(*block_args) if blk
209
+
210
+ ret
211
+ end
212
+
213
+ yield self
214
+ ensure
215
+ metaclass.send :undef_method, name
216
+ metaclass.send :alias_method, name, new_name
217
+ metaclass.send :undef_method, new_name
218
+ end
219
+
220
+ end
@@ -0,0 +1,120 @@
1
+ ##
2
+ # Provides a parallel #each that lets you enumerate using N threads.
3
+ # Use environment variable N to customize. Defaults to 2. Enumerable,
4
+ # so all the goodies come along (tho not all are wrapped yet to
5
+ # return another ParallelEach instance).
6
+
7
+ class Minitest::ParallelEach
8
+ require 'thread'
9
+ include Enumerable
10
+
11
+ ##
12
+ # How many Threads to use for this parallel #each.
13
+
14
+ N = (ENV['N'] || 2).to_i
15
+
16
+ ##
17
+ # Create a new ParallelEach instance over +list+.
18
+
19
+ def initialize list
20
+ @queue = Queue.new # *sigh*... the Queue api sucks sooo much...
21
+
22
+ list.each { |i| @queue << i }
23
+ N.times { @queue << nil }
24
+ end
25
+
26
+ def select(&block) # :nodoc:
27
+ self.class.new super
28
+ end
29
+
30
+ alias find_all select # :nodoc:
31
+
32
+ ##
33
+ # Starts N threads that yield each element to your block. Joins the
34
+ # threads at the end.
35
+
36
+ def each
37
+ threads = N.times.map {
38
+ Thread.new do
39
+ Thread.current.abort_on_exception = true
40
+ while job = @queue.pop
41
+ yield job
42
+ end
43
+ end
44
+ }
45
+ threads.map(&:join)
46
+ end
47
+
48
+ def count # :nodoc:
49
+ [@queue.size - N, 0].max
50
+ end
51
+
52
+ alias_method :size, :count # :nodoc:
53
+ end
54
+
55
+ module Minitest
56
+ class << self
57
+ remove_method :__run
58
+ end
59
+
60
+ class Test
61
+ @mutex = Mutex.new
62
+
63
+ def self.synchronize # :nodoc:
64
+ if @mutex then # see parallel_each.rb
65
+ @mutex.synchronize { yield }
66
+ else
67
+ yield
68
+ end
69
+ end
70
+
71
+ alias :simple_capture_io :capture_io
72
+
73
+ def capture_io(&b)
74
+ Test.synchronize do
75
+ simple_capture_io(&b)
76
+ end
77
+ end
78
+
79
+ alias :simple_capture_subprocess_io :capture_subprocess_io
80
+
81
+ def capture_subprocess_io(&b)
82
+ Test.synchronize do
83
+ simple_capture_subprocess_io(&b)
84
+ end
85
+ end
86
+ end
87
+
88
+ class Reporter
89
+ @mutex = Mutex.new
90
+
91
+ def self.synchronize # :nodoc:
92
+ if @mutex then # see parallel_each.rb
93
+ @mutex.synchronize { yield }
94
+ else
95
+ yield
96
+ end
97
+ end
98
+
99
+ alias :simple_record :record
100
+
101
+ def record result
102
+ Reporter.synchronize do
103
+ simple_record result
104
+ end
105
+ end
106
+ end
107
+
108
+ ##
109
+ # Runs all the +suites+ for a given +type+. Runs suites declaring
110
+ # a test_order of +:parallel+ in parallel, and everything else
111
+ # serial.
112
+
113
+ def self.__run reporter, options
114
+ suites = Runnable.runnables
115
+ parallel, serial = suites.partition { |s| s.test_order == :parallel }
116
+
117
+ ParallelEach.new(parallel).map { |suite| suite.run reporter, options } +
118
+ serial.map { |suite| suite.run reporter, options }
119
+ end
120
+ end
@@ -0,0 +1,4 @@
1
+ require "minitest"
2
+
3
+ Minitest.load_plugins
4
+ Minitest::PrideIO.pride!
@@ -0,0 +1,143 @@
1
+ require "minitest/autorun"
2
+
3
+ module Minitest
4
+ def self.plugin_pride_options opts, options # :nodoc:
5
+ opts.on "-p", "--pride", "Pride. Show your testing pride!" do
6
+ PrideIO.pride!
7
+ end
8
+ end
9
+
10
+ def self.plugin_pride_init options # :nodoc:
11
+ if PrideIO.pride? then
12
+ klass = ENV["TERM"] =~ /^xterm|-256color$/ ? PrideLOL : PrideIO
13
+ io = klass.new options[:io]
14
+
15
+ self.reporter.reporters.grep(Minitest::Reporter).each do |rep|
16
+ rep.io = io
17
+ end
18
+ end
19
+ end
20
+
21
+ ##
22
+ # Show your testing pride!
23
+
24
+ class PrideIO
25
+ ##
26
+ # Activate the pride plugin. Called from both -p option and minitest/pride
27
+
28
+ def self.pride!
29
+ @pride = true
30
+ end
31
+
32
+ ##
33
+ # Are we showing our testing pride?
34
+
35
+ def self.pride?
36
+ @pride ||= false
37
+ end
38
+
39
+ # Start an escape sequence
40
+ ESC = "\e["
41
+
42
+ # End the escape sequence
43
+ NND = "#{ESC}0m"
44
+
45
+ # The IO we're going to pipe through.
46
+ attr_reader :io
47
+
48
+ def initialize io # :nodoc:
49
+ @io = io
50
+ # stolen from /System/Library/Perl/5.10.0/Term/ANSIColor.pm
51
+ # also reference http://en.wikipedia.org/wiki/ANSI_escape_code
52
+ @colors ||= (31..36).to_a
53
+ @size = @colors.size
54
+ @index = 0
55
+ # io.sync = true
56
+ end
57
+
58
+ ##
59
+ # Wrap print to colorize the output.
60
+
61
+ def print o
62
+ case o
63
+ when "." then
64
+ io.print pride o
65
+ when "E", "F" then
66
+ io.print "#{ESC}41m#{ESC}37m#{o}#{NND}"
67
+ when "S" then
68
+ io.print pride o
69
+ else
70
+ io.print o
71
+ end
72
+ end
73
+
74
+ def puts(*o) # :nodoc:
75
+ o.map! { |s|
76
+ s.to_s.sub(/Finished/) {
77
+ @index = 0
78
+ 'Fabulous run'.split(//).map { |c|
79
+ pride(c)
80
+ }.join
81
+ }
82
+ }
83
+
84
+ io.puts(*o)
85
+ end
86
+
87
+ ##
88
+ # Color a string.
89
+
90
+ def pride string
91
+ string = "*" if string == "."
92
+ c = @colors[@index % @size]
93
+ @index += 1
94
+ "#{ESC}#{c}m#{string}#{NND}"
95
+ end
96
+
97
+ def method_missing msg, *args # :nodoc:
98
+ io.send(msg, *args)
99
+ end
100
+ end
101
+
102
+ ##
103
+ # If you thought the PrideIO was colorful...
104
+ #
105
+ # (Inspired by lolcat, but with clean math)
106
+
107
+ class PrideLOL < PrideIO
108
+ PI_3 = Math::PI / 3 # :nodoc:
109
+
110
+ def initialize io # :nodoc:
111
+ # walk red, green, and blue around a circle separated by equal thirds.
112
+ #
113
+ # To visualize, type this into wolfram-alpha:
114
+ #
115
+ # plot (3*sin(x)+3), (3*sin(x+2*pi/3)+3), (3*sin(x+4*pi/3)+3)
116
+
117
+ # 6 has wide pretty gradients. 3 == lolcat, about half the width
118
+ @colors = (0...(6 * 7)).map { |n|
119
+ n *= 1.0 / 6
120
+ r = (3 * Math.sin(n ) + 3).to_i
121
+ g = (3 * Math.sin(n + 2 * PI_3) + 3).to_i
122
+ b = (3 * Math.sin(n + 4 * PI_3) + 3).to_i
123
+
124
+ # Then we take rgb and encode them in a single number using base 6.
125
+ # For some mysterious reason, we add 16... to clear the bottom 4 bits?
126
+ # Yes... they're ugly.
127
+
128
+ 36 * r + 6 * g + b + 16
129
+ }
130
+
131
+ super
132
+ end
133
+
134
+ ##
135
+ # Make the string even more colorful. Damnit.
136
+
137
+ def pride string
138
+ c = @colors[@index % @size]
139
+ @index += 1
140
+ "#{ESC}38;5;#{c}m#{string}#{NND}"
141
+ end
142
+ end
143
+ end