rspec-unit 0.9.22

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.
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source :gemcutter
2
+
3
+ # gem 'bundler', '>= 0.9.16'
4
+ gem 'rspec', '= 2.0.0.beta.22'
5
+
6
+ group :test do
7
+ gem 'rake', '>= 0.8.7'
8
+ gem 'rcov', '>= 0.9.9'
9
+ end
10
+
11
+ group :release do
12
+ gem 'jeweler', '>= 1.4.0'
13
+ end
14
+
@@ -0,0 +1,34 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ gemcutter (0.6.1)
6
+ git (1.2.5)
7
+ jeweler (1.4.0)
8
+ gemcutter (>= 0.1.0)
9
+ git (>= 1.2.5)
10
+ rubyforge (>= 2.0.0)
11
+ json_pure (1.4.6)
12
+ rake (0.8.7)
13
+ rcov (0.9.9)
14
+ rspec (2.0.0.beta.22)
15
+ rspec-core (= 2.0.0.beta.22)
16
+ rspec-expectations (= 2.0.0.beta.22)
17
+ rspec-mocks (= 2.0.0.beta.22)
18
+ rspec-core (2.0.0.beta.22)
19
+ rspec-expectations (2.0.0.beta.22)
20
+ diff-lcs (>= 1.1.2)
21
+ rspec-mocks (2.0.0.beta.22)
22
+ rspec-core (= 2.0.0.beta.22)
23
+ rspec-expectations (= 2.0.0.beta.22)
24
+ rubyforge (2.0.4)
25
+ json_pure (>= 1.1.7)
26
+
27
+ PLATFORMS
28
+ ruby
29
+
30
+ DEPENDENCIES
31
+ jeweler (>= 1.4.0)
32
+ rake (>= 0.8.7)
33
+ rcov (>= 0.9.9)
34
+ rspec (= 2.0.0.beta.22)
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009, 2010 Glenn Vanderburg
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,121 @@
1
+ # rspec-unit
2
+
3
+ test/unit compatibility for RSpec 2.
4
+
5
+ ## Summary
6
+
7
+ rspec-unit adds support for test/unit-style assertions and test
8
+ cases to RSpec 2. This is useful for piecemeal conversions of your
9
+ test suite (in either direction), mixing styles, or if you simply
10
+ want to use test/unit-style assertions occasionally in your specs.
11
+
12
+ Just add this to your code:
13
+
14
+ require 'rspec/unit'
15
+
16
+ and then you can write test classes like this:
17
+
18
+ class FooTest < RSpec::Unit::TestCase
19
+ def test_foo
20
+ assert_equal 3, Foo::major_version
21
+ end
22
+ end
23
+
24
+ Using the `test_info` method, you can attach metadata to the next
25
+ defined test (this works much the same way Rake's `desc` method
26
+ attaches a description string to the next defined task):
27
+
28
+ test_info :speed => 'slow', :run => 'nightly'
29
+ def test_tarantula_multipass
30
+ # ...
31
+ end
32
+
33
+ You can also attach metadata to the entire class with the
34
+ `test_case_info` method:
35
+
36
+ class BarTest < RSpec::Unit::TestCase
37
+ test_case_info :integration => true
38
+
39
+ # ...
40
+ end
41
+
42
+ Each instance of `Rspec::Unit::TestCase` is equivalent to an
43
+ RSpec `describe` block, so it can also include `example` blocks,
44
+ `before` and `after` blocks, and nested `describe` blocks. Test
45
+ methods and `example` blocks can contain either assertions or `should`
46
+ expressions. `test` blocks (as found in Rails 2.x) also work.
47
+
48
+ Additionally, assertions can be used inside ordinary RSpec
49
+ examples.
50
+
51
+ ## Rationale
52
+
53
+ This gem is the rough equivalent, for RSpec 2, of the test/unit
54
+ compatibility that was a part of the core RSpec gem in RSpec 1.
55
+ The new RSpec runner design makes it quite easy to implement this
56
+ functionality as a separate gem, which seems like a better choice
57
+ in many ways.
58
+
59
+ Currently, test/unit compatibility is much more limited than in
60
+ RSpec 1. The goal is not to make RSpec 2 a drop-in replacement for
61
+ test/unit; rather, we have two more limited goals:
62
+
63
+ 1. to allow RSpec 2 examples to easily make use of test/unit assertions
64
+ in cases where those assertions are valuable, or where assertions
65
+ might be the best way to express particular expectations.
66
+ 2. to make it *easy* for a project to switch an existing test/unit
67
+ suite over to run under RSpec, as the start of a gradual, piecemeal
68
+ conversion to RSpec.
69
+
70
+ As such, there are some things we don''t support:
71
+
72
+ * The top-level module name is different. For example, one requires
73
+ `rspec/unit` rather than `test/unit`, and extends `RSpec::Unit::TestCase`
74
+ rather than `Test::Unit::TestCase`.
75
+ * TestSuite is not supported. The RSpec 2 metadata features are
76
+ far more flexible than test/unit-style suites.
77
+ * Because of the very different implementation, many test/unit extensions
78
+ will not run properly.
79
+ * All test output and summaries are in RSpec style; test/unit-compatible
80
+ output is not supported.
81
+
82
+ We will certainly consider supporting those things if there is demand.
83
+
84
+ I originally wrote this test/unit compatibility gem for Micronaut, a
85
+ lightweight RSpec clone by Chad Humphries. Micronaut has been rolled
86
+ into RSpec as the core of RSpec 2, and I was able to move the test/unit
87
+ compatibility over with minimal changes.
88
+
89
+ The point of this gem is not that I think test/unit is a better way
90
+ to write tests than the RSpec style. I admit that I'm a TDD oldtimer
91
+ who sees RSpec as mostly a cosmetic (rather than fundamental) change,
92
+ but that doesn't mean it's not an important change. My curmudgeonly
93
+ nature has its limits, and I do find specs a big improvement.
94
+
95
+ So why rspec-unit? Three reasons:
96
+
97
+ 1. I wanted to show off the generality of Micronaut's (and now RSpec's)
98
+ architecture. I hope rspec-unit can serve as an example for anyone
99
+ who wants to experiment with new ways of expressing tests and specs
100
+ on top of RSpec.
101
+ 2. Many projects with existing test/unit test suites might want to
102
+ benefit from the [metadata goodness][metadata] in RSpec 2, or begin
103
+ a gradual, piecemeal change to an RSpec style. That's pretty
104
+ easy to do with rspec-unit.
105
+ 3. Even when writing specs and examples, I frequently encounter
106
+ cases where an assertion is more expressive than a `should`
107
+ expression. It's nice just to have assertions supported within
108
+ RSpec examples.
109
+
110
+ [uth]: http://blog.thinkrelevance.com/2009/4/1/micronaut-innovation-under-the-hood
111
+ [metadata]: http://blog.thinkrelevance.com/2009/3/26/introducing-micronaut-a-lightweight-bdd-framework
112
+
113
+ ## To Do
114
+
115
+ It would be nice to try using the assertion code from minitest,
116
+ which is much more compact and seems less coupled than that from
117
+ test/unit.
118
+
119
+ ### Copyright
120
+
121
+ Copyright (c) 2009, 2010 Glenn Vanderburg. See LICENSE for details.
@@ -0,0 +1,49 @@
1
+ require 'bundler/setup'
2
+
3
+ begin
4
+ require 'jeweler'
5
+ Jeweler::Tasks.new do |gem|
6
+ gem.name = "rspec-unit"
7
+ gem.summary = %Q{test/unit compatibility for RSpec 2.}
8
+ gem.description = gem.summary # File.read('README.md').sub(/\A.*^## Summary\s*$\s*(.*?)\s*^#+\s.*\Z/m, '\1')
9
+ gem.email = "glv@vanderburg.org"
10
+ gem.homepage = "http://github.com/glv/rspec-unit"
11
+ gem.authors = ["Glenn Vanderburg"]
12
+ gem.rubyforge_project = "rspec-unit"
13
+ gem.add_dependency('rspec', '~> 2.0')
14
+ gem.has_rdoc = false
15
+ gem.files = FileList["[A-Z]*", "{bin,lib,spec}/**/*"]
16
+ gem.rubyforge_project = 'glv'
17
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
18
+ end
19
+
20
+ Jeweler::RubyforgeTasks.new
21
+ Jeweler::GemcutterTasks.new
22
+ rescue LoadError
23
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
24
+ end
25
+
26
+ require 'rspec/core/rake_task'
27
+ RSpec::Core::RakeTask.new(:spec) do |spec|
28
+ spec.pattern = 'spec/**/*_spec.rb'
29
+ spec.ruby_opts = '-Ilib -Ispec'
30
+ end
31
+
32
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
33
+ spec.pattern = 'spec/**/*_spec.rb'
34
+ spec.rcov_opts = '-Ilib -Ispec -x ' + "'#{Regexp.escape(Bundler.settings.path)},^spec/'"
35
+ spec.rcov = true
36
+ end
37
+
38
+ task :default => :spec
39
+
40
+ require 'rake/rdoctask'
41
+ Rake::RDocTask.new do |rdoc|
42
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
43
+
44
+ rdoc.rdoc_dir = 'rdoc'
45
+ rdoc.title = "rspec-unit #{version}"
46
+ rdoc.rdoc_files.include('README*')
47
+ rdoc.rdoc_files.include('lib/**/*.rb')
48
+ end
49
+
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 9
4
+ :patch: 22
@@ -0,0 +1 @@
1
+ require 'rspec/unit'
@@ -0,0 +1,3 @@
1
+ # This file may be the starting point in some cases, so pull in all of micronaut:
2
+ require 'rspec'
3
+ require 'rspec/unit/test_case'
@@ -0,0 +1,651 @@
1
+ # Author:: Nathaniel Talbott.
2
+ # Copyright:: Copyright (c) 2000-2003 Nathaniel Talbott. All rights reserved.
3
+ # License:: Ruby license.
4
+
5
+ module RSpec
6
+ module Unit
7
+
8
+ ##
9
+ # Test::Unit::Assertions contains the standard Test::Unit assertions.
10
+ # Assertions is included in Test::Unit::TestCase.
11
+ #
12
+ # To include it in your own code and use its functionality, you simply
13
+ # need to rescue Test::Unit::AssertionFailedError. Additionally you may
14
+ # override add_assertion to get notified whenever an assertion is made.
15
+ #
16
+ # Notes:
17
+ # * The message to each assertion, if given, will be propagated with the
18
+ # failure.
19
+ # * It is easy to add your own assertions based on assert_block().
20
+ #
21
+ # = Example Custom Assertion
22
+ #
23
+ # def deny(boolean, message = nil)
24
+ # message = build_message message, '<?> is not false or nil.', boolean
25
+ # assert_block message do
26
+ # not boolean
27
+ # end
28
+ # end
29
+
30
+ module Assertions
31
+
32
+ ##
33
+ # The assertion upon which all other assertions are based. Passes if the
34
+ # block yields true.
35
+ #
36
+ # Example:
37
+ # assert_block "Couldn't do the thing" do
38
+ # do_the_thing
39
+ # end
40
+
41
+ public
42
+ def assert_block(message="assert_block failed.") # :yields:
43
+ _wrap_assertion do
44
+ if (! yield)
45
+ raise AssertionFailedError.new(message.to_s)
46
+ end
47
+ end
48
+ end
49
+
50
+ ##
51
+ # Asserts that +boolean+ is not false or nil.
52
+ #
53
+ # Example:
54
+ # assert [1, 2].include?(5)
55
+
56
+ public
57
+ def assert(boolean, message=nil)
58
+ _wrap_assertion do
59
+ assert_block("assert should not be called with a block.") { !block_given? }
60
+ assert_block(build_message(message, "<?> is not true.", boolean)) { boolean }
61
+ end
62
+ end
63
+
64
+ ##
65
+ # Passes if +expected+ == +actual.
66
+ #
67
+ # Note that the ordering of arguments is important, since a helpful
68
+ # error message is generated when this one fails that tells you the
69
+ # values of expected and actual.
70
+ #
71
+ # Example:
72
+ # assert_equal 'MY STRING', 'my string'.upcase
73
+
74
+ public
75
+ def assert_equal(expected, actual, message=nil)
76
+ full_message = build_message(message, <<EOT, expected, actual)
77
+ <?> expected but was
78
+ <?>.
79
+ EOT
80
+ assert_block(full_message) { expected == actual }
81
+ end
82
+
83
+ private
84
+ def _check_exception_class(args) # :nodoc:
85
+ args.partition do |klass|
86
+ next if klass.instance_of?(Module)
87
+ assert(Exception >= klass, "Should expect a class of exception, #{klass}")
88
+ true
89
+ end
90
+ end
91
+
92
+ private
93
+ def _expected_exception?(actual_exception, exceptions, modules) # :nodoc:
94
+ exceptions.include?(actual_exception.class) or
95
+ modules.any? {|mod| actual_exception.is_a?(mod)}
96
+ end
97
+
98
+ ##
99
+ # Passes if the block raises one of the given exceptions.
100
+ #
101
+ # Example:
102
+ # assert_raise RuntimeError, LoadError do
103
+ # raise 'Boom!!!'
104
+ # end
105
+
106
+ public
107
+ def assert_raise(*args)
108
+ _wrap_assertion do
109
+ if Module === args.last
110
+ message = ""
111
+ else
112
+ message = args.pop
113
+ end
114
+ exceptions, modules = _check_exception_class(args)
115
+ expected = args.size == 1 ? args.first : args
116
+ actual_exception = nil
117
+ full_message = build_message(message, "<?> exception expected but none was thrown.", expected)
118
+ assert_block(full_message) do
119
+ begin
120
+ yield
121
+ rescue Exception => actual_exception
122
+ break
123
+ end
124
+ false
125
+ end
126
+ full_message = build_message(message, "<?> exception expected but was\n?", expected, actual_exception)
127
+ assert_block(full_message) {_expected_exception?(actual_exception, exceptions, modules)}
128
+ actual_exception
129
+ end
130
+ end
131
+
132
+ ##
133
+ # Alias of assert_raise.
134
+ #
135
+ # Will be deprecated in 1.9, and removed in 2.0.
136
+
137
+ public
138
+ def assert_raises(*args, &block)
139
+ assert_raise(*args, &block)
140
+ end
141
+
142
+ ##
143
+ # Passes if +object+ .instance_of? +klass+
144
+ #
145
+ # Example:
146
+ # assert_instance_of String, 'foo'
147
+
148
+ public
149
+ def assert_instance_of(klass, object, message="")
150
+ _wrap_assertion do
151
+ assert_equal(Class, klass.class, "assert_instance_of takes a Class as its first argument")
152
+ full_message = build_message(message, <<EOT, object, klass, object.class)
153
+ <?> expected to be an instance of
154
+ <?> but was
155
+ <?>.
156
+ EOT
157
+ assert_block(full_message){object.instance_of?(klass)}
158
+ end
159
+ end
160
+
161
+ ##
162
+ # Passes if +object+ is nil.
163
+ #
164
+ # Example:
165
+ # assert_nil [1, 2].uniq!
166
+
167
+ public
168
+ def assert_nil(object, message="")
169
+ assert_equal(nil, object, message)
170
+ end
171
+
172
+ ##
173
+ # Passes if +object+ .kind_of? +klass+
174
+ #
175
+ # Example:
176
+ # assert_kind_of Object, 'foo'
177
+
178
+ public
179
+ def assert_kind_of(klass, object, message="")
180
+ _wrap_assertion do
181
+ assert(klass.kind_of?(Module), "The first parameter to assert_kind_of should be a kind_of Module.")
182
+ full_message = build_message(message, "<?>\nexpected to be kind_of\\?\n<?> but was\n<?>.", object, klass, object.class)
183
+ assert_block(full_message){object.kind_of?(klass)}
184
+ end
185
+ end
186
+
187
+ ##
188
+ # Passes if +object+ .respond_to? +method+
189
+ #
190
+ # Example:
191
+ # assert_respond_to 'bugbear', :slice
192
+
193
+ public
194
+ def assert_respond_to(object, method, message="")
195
+ _wrap_assertion do
196
+ full_message = build_message(nil, "<?>\ngiven as the method name argument to #assert_respond_to must be a Symbol or #respond_to\\?(:to_str).", method)
197
+
198
+ assert_block(full_message) do
199
+ method.kind_of?(Symbol) || method.respond_to?(:to_str)
200
+ end
201
+ full_message = build_message(message, <<EOT, object, object.class, method)
202
+ <?>
203
+ of type <?>
204
+ expected to respond_to\\?<?>.
205
+ EOT
206
+ assert_block(full_message) { object.respond_to?(method) }
207
+ end
208
+ end
209
+
210
+ ##
211
+ # Passes if +string+ =~ +pattern+.
212
+ #
213
+ # Example:
214
+ # assert_match(/\d+/, 'five, 6, seven')
215
+
216
+ public
217
+ def assert_match(pattern, string, message="")
218
+ _wrap_assertion do
219
+ pattern = case(pattern)
220
+ when String
221
+ Regexp.new(Regexp.escape(pattern))
222
+ else
223
+ pattern
224
+ end
225
+ full_message = build_message(message, "<?> expected to be =~\n<?>.", string, pattern)
226
+ assert_block(full_message) { string =~ pattern }
227
+ end
228
+ end
229
+
230
+ ##
231
+ # Passes if +actual+ .equal? +expected+ (i.e. they are the same
232
+ # instance).
233
+ #
234
+ # Example:
235
+ # o = Object.new
236
+ # assert_same o, o
237
+
238
+ public
239
+ def assert_same(expected, actual, message="")
240
+ full_message = build_message(message, <<EOT, expected, expected.__id__, actual, actual.__id__)
241
+ <?>
242
+ with id <?> expected to be equal\\? to
243
+ <?>
244
+ with id <?>.
245
+ EOT
246
+ assert_block(full_message) { actual.equal?(expected) }
247
+ end
248
+
249
+ ##
250
+ # Compares the +object1+ with +object2+ using +operator+.
251
+ #
252
+ # Passes if object1.__send__(operator, object2) is true.
253
+ #
254
+ # Example:
255
+ # assert_operator 5, :>=, 4
256
+
257
+ public
258
+ def assert_operator(object1, operator, object2, message="")
259
+ _wrap_assertion do
260
+ full_message = build_message(nil, "<?>\ngiven as the operator for #assert_operator must be a Symbol or #respond_to\\?(:to_str).", operator)
261
+ assert_block(full_message){operator.kind_of?(Symbol) || operator.respond_to?(:to_str)}
262
+ full_message = build_message(message, <<EOT, object1, AssertionMessage.literal(operator), object2)
263
+ <?> expected to be
264
+ ?
265
+ <?>.
266
+ EOT
267
+ assert_block(full_message) { object1.__send__(operator, object2) }
268
+ end
269
+ end
270
+
271
+ ##
272
+ # Passes if block does not raise an exception.
273
+ #
274
+ # Example:
275
+ # assert_nothing_raised do
276
+ # [1, 2].uniq
277
+ # end
278
+
279
+ public
280
+ def assert_nothing_raised(*args)
281
+ _wrap_assertion do
282
+ if Module === args.last
283
+ message = ""
284
+ else
285
+ message = args.pop
286
+ end
287
+ exceptions, modules = _check_exception_class(args)
288
+ begin
289
+ yield
290
+ rescue Exception => e
291
+ if ((args.empty? && !e.instance_of?(AssertionFailedError)) ||
292
+ _expected_exception?(e, exceptions, modules))
293
+ assert_block(build_message(message, "Exception raised:\n?", e)){false}
294
+ else
295
+ raise
296
+ end
297
+ end
298
+ nil
299
+ end
300
+ end
301
+
302
+ ##
303
+ # Flunk always fails.
304
+ #
305
+ # Example:
306
+ # flunk 'Not done testing yet.'
307
+
308
+ public
309
+ def flunk(message="Flunked")
310
+ assert_block(build_message(message)){false}
311
+ end
312
+
313
+ ##
314
+ # Passes if ! +actual+ .equal? +expected+
315
+ #
316
+ # Example:
317
+ # assert_not_same Object.new, Object.new
318
+
319
+ public
320
+ def assert_not_same(expected, actual, message="")
321
+ full_message = build_message(message, <<EOT, expected, expected.__id__, actual, actual.__id__)
322
+ <?>
323
+ with id <?> expected to not be equal\\? to
324
+ <?>
325
+ with id <?>.
326
+ EOT
327
+ assert_block(full_message) { !actual.equal?(expected) }
328
+ end
329
+
330
+ ##
331
+ # Passes if +expected+ != +actual+
332
+ #
333
+ # Example:
334
+ # assert_not_equal 'some string', 5
335
+
336
+ public
337
+ def assert_not_equal(expected, actual, message="")
338
+ full_message = build_message(message, "<?> expected to be != to\n<?>.", expected, actual)
339
+ assert_block(full_message) { expected != actual }
340
+ end
341
+
342
+ ##
343
+ # Passes if ! +object+ .nil?
344
+ #
345
+ # Example:
346
+ # assert_not_nil '1 two 3'.sub!(/two/, '2')
347
+
348
+ public
349
+ def assert_not_nil(object, message="")
350
+ full_message = build_message(message, "<?> expected to not be nil.", object)
351
+ assert_block(full_message){!object.nil?}
352
+ end
353
+
354
+ ##
355
+ # Passes if +regexp+ !~ +string+
356
+ #
357
+ # Example:
358
+ # assert_no_match(/two/, 'one 2 three')
359
+
360
+ public
361
+ def assert_no_match(regexp, string, message="")
362
+ _wrap_assertion do
363
+ assert_instance_of(Regexp, regexp, "The first argument to assert_no_match should be a Regexp.")
364
+ full_message = build_message(message, "<?> expected to not match\n<?>.", regexp, string)
365
+ assert_block(full_message) { regexp !~ string }
366
+ end
367
+ end
368
+
369
+ UncaughtThrow = {NameError => /^uncaught throw \`(.+)\'$/,
370
+ ThreadError => /^uncaught throw \`(.+)\' in thread /} #`
371
+
372
+ ##
373
+ # Passes if the block throws +expected_symbol+
374
+ #
375
+ # Example:
376
+ # assert_throws :done do
377
+ # throw :done
378
+ # end
379
+
380
+ public
381
+ def assert_throws(expected_symbol, message="", &proc)
382
+ _wrap_assertion do
383
+ assert_instance_of(Symbol, expected_symbol, "assert_throws expects the symbol that should be thrown for its first argument")
384
+ assert_block("Should have passed a block to assert_throws."){block_given?}
385
+ caught = true
386
+ begin
387
+ catch(expected_symbol) do
388
+ proc.call
389
+ caught = false
390
+ end
391
+ full_message = build_message(message, "<?> should have been thrown.", expected_symbol)
392
+ assert_block(full_message){caught}
393
+ rescue NameError, ThreadError => error
394
+ if UncaughtThrow[error.class] !~ error.message
395
+ raise error
396
+ end
397
+ full_message = build_message(message, "<?> expected to be thrown but\n<?> was thrown.", expected_symbol, $1.intern)
398
+ flunk(full_message)
399
+ end
400
+ end
401
+ end
402
+
403
+ ##
404
+ # Passes if block does not throw anything.
405
+ #
406
+ # Example:
407
+ # assert_nothing_thrown do
408
+ # [1, 2].uniq
409
+ # end
410
+
411
+ public
412
+ def assert_nothing_thrown(message="", &proc)
413
+ _wrap_assertion do
414
+ assert(block_given?, "Should have passed a block to assert_nothing_thrown")
415
+ begin
416
+ proc.call
417
+ rescue NameError, ThreadError => error
418
+ if UncaughtThrow[error.class] !~ error.message
419
+ raise error
420
+ end
421
+ full_message = build_message(message, "<?> was thrown when nothing was expected", $1.intern)
422
+ flunk(full_message)
423
+ end
424
+ assert(true, "Expected nothing to be thrown")
425
+ end
426
+ end
427
+
428
+ ##
429
+ # Passes if +expected_float+ and +actual_float+ are equal
430
+ # within +delta+ tolerance.
431
+ #
432
+ # Example:
433
+ # assert_in_delta 0.05, (50000.0 / 10**6), 0.00001
434
+
435
+ public
436
+ def assert_in_delta(expected_float, actual_float, delta, message="")
437
+ _wrap_assertion do
438
+ {expected_float => "first float", actual_float => "second float", delta => "delta"}.each do |float, name|
439
+ assert_respond_to(float, :to_f, "The arguments must respond to to_f; the #{name} did not")
440
+ end
441
+ assert_operator(delta, :>=, 0.0, "The delta should not be negative")
442
+ full_message = build_message(message, <<EOT, expected_float, actual_float, delta)
443
+ <?> and
444
+ <?> expected to be within
445
+ <?> of each other.
446
+ EOT
447
+ assert_block(full_message) { (expected_float.to_f - actual_float.to_f).abs <= delta.to_f }
448
+ end
449
+ end
450
+
451
+ ##
452
+ # Passes if the method send returns a true value.
453
+ #
454
+ # +send_array+ is composed of:
455
+ # * A receiver
456
+ # * A method
457
+ # * Arguments to the method
458
+ #
459
+ # Example:
460
+ # assert_send [[1, 2], :include?, 4]
461
+
462
+ public
463
+ def assert_send(send_array, message="")
464
+ _wrap_assertion do
465
+ assert_instance_of(Array, send_array, "assert_send requires an array of send information")
466
+ assert(send_array.size >= 2, "assert_send requires at least a receiver and a message name")
467
+ full_message = build_message(message, <<EOT, send_array[0], AssertionMessage.literal(send_array[1].to_s), send_array[2..-1])
468
+ <?> expected to respond to
469
+ <?(?)> with a true value.
470
+ EOT
471
+ assert_block(full_message) { send_array[0].__send__(send_array[1], *send_array[2..-1]) }
472
+ end
473
+ end
474
+
475
+ ##
476
+ # Builds a failure message. +head+ is added before the +template+ and
477
+ # +arguments+ replaces the '?'s positionally in the template.
478
+
479
+ public
480
+ def build_message(head, template=nil, *arguments)
481
+ template &&= template.chomp
482
+ return AssertionMessage.new(head, template, arguments)
483
+ end
484
+
485
+ private
486
+ def _wrap_assertion
487
+ @_assertion_wrapped ||= false
488
+ unless (@_assertion_wrapped)
489
+ @_assertion_wrapped = true
490
+ begin
491
+ add_assertion
492
+ return yield
493
+ ensure
494
+ @_assertion_wrapped = false
495
+ end
496
+ else
497
+ return yield
498
+ end
499
+ end
500
+
501
+ ##
502
+ # Called whenever an assertion is made. Define this in classes that
503
+ # include Test::Unit::Assertions to record assertion counts.
504
+
505
+ private
506
+ def add_assertion
507
+ end
508
+
509
+ ##
510
+ # Select whether or not to use the pretty-printer. If this option is set
511
+ # to false before any assertions are made, pp.rb will not be required.
512
+
513
+ public
514
+ def self.use_pp=(value)
515
+ AssertionMessage.use_pp = value
516
+ end
517
+
518
+ # :stopdoc:
519
+
520
+ class AssertionMessage
521
+ @use_pp = true
522
+ class << self
523
+ attr_accessor :use_pp
524
+ end
525
+
526
+ class Literal
527
+ def initialize(value)
528
+ @value = value
529
+ end
530
+
531
+ def inspect
532
+ @value.to_s
533
+ end
534
+ end
535
+
536
+ class Template
537
+ def self.create(string)
538
+ parts = (string ? string.scan(/(?=[^\\])\?|(?:\\\?|[^\?])+/m) : [])
539
+ self.new(parts)
540
+ end
541
+
542
+ attr_reader :count
543
+
544
+ def initialize(parts)
545
+ @parts = parts
546
+ @count = parts.find_all{|e| e == '?'}.size
547
+ end
548
+
549
+ def result(parameters)
550
+ raise "The number of parameters does not match the number of substitutions." if(parameters.size != count)
551
+ params = parameters.dup
552
+ @parts.collect{|e| e == '?' ? params.shift : e.gsub(/\\\?/m, '?')}.join('')
553
+ end
554
+ end
555
+
556
+ def self.literal(value)
557
+ Literal.new(value)
558
+ end
559
+
560
+ def initialize(head, template_string, parameters)
561
+ @head = head
562
+ @template_string = template_string
563
+ @parameters = parameters
564
+ end
565
+
566
+ def convert(object)
567
+ case object
568
+ when Exception
569
+ <<EOM.chop
570
+ Class: <#{convert(object.class)}>
571
+ Message: <#{convert(object.message)}>
572
+ ---Backtrace---
573
+ #{filter_backtrace(object.backtrace).join("\n")}
574
+ ---------------
575
+ EOM
576
+ else
577
+ if(self.class.use_pp)
578
+ begin
579
+ require 'pp'
580
+ rescue LoadError
581
+ self.class.use_pp = false
582
+ return object.inspect
583
+ end unless(defined?(PP))
584
+ PP.pp(object, '').chomp
585
+ else
586
+ object.inspect
587
+ end
588
+ end
589
+ end
590
+
591
+ def template
592
+ @template ||= Template.create(@template_string)
593
+ end
594
+
595
+ def add_period(string)
596
+ (string =~ /\.\Z/ ? string : string + '.')
597
+ end
598
+
599
+ def to_s
600
+ message_parts = []
601
+ if (@head)
602
+ head = @head.to_s
603
+ unless(head.empty?)
604
+ message_parts << add_period(head)
605
+ end
606
+ end
607
+ tail = template.result(@parameters.collect{|e| convert(e)})
608
+ message_parts << tail unless(tail.empty?)
609
+ message_parts.join("\n")
610
+ end
611
+
612
+ MICRONAUTUNIT_FILE_SEPARATORS = %r{[\\/:]}
613
+ MICRONAUTUNIT_PREFIX = __FILE__.split(MICRONAUTUNIT_FILE_SEPARATORS)[0..-3]
614
+ MICRONAUTUNIT_RB_FILE = /\.rb\Z/
615
+
616
+ def filter_backtrace(backtrace, prefix=nil)
617
+ return ["No backtrace"] unless(backtrace)
618
+ split_p = if(prefix)
619
+ prefix.split(MICRONAUTUNIT_FILE_SEPARATORS)
620
+ else
621
+ MICRONAUTUNIT_PREFIX
622
+ end
623
+ match = proc do |e|
624
+ split_e = e.split(MICRONAUTUNIT_FILE_SEPARATORS)[0, split_p.size]
625
+ next false unless(split_e[0..-2] == split_p[0..-2])
626
+ split_e[-1].sub(MICRONAUTUNIT_RB_FILE, '') == split_p[-1]
627
+ end
628
+ return backtrace unless(backtrace.detect(&match))
629
+ found_prefix = false
630
+ new_backtrace = backtrace.reverse.reject do |e|
631
+ if(match[e])
632
+ found_prefix = true
633
+ true
634
+ elsif(found_prefix)
635
+ false
636
+ else
637
+ true
638
+ end
639
+ end.reverse
640
+ new_backtrace = (new_backtrace.empty? ? backtrace : new_backtrace)
641
+ new_backtrace = new_backtrace.reject(&match)
642
+ new_backtrace.empty? ? backtrace : new_backtrace
643
+ end
644
+
645
+ end
646
+
647
+ # :startdoc:
648
+
649
+ end
650
+ end
651
+ end