Project

General

Profile

Feature #9711 ยป copy-test-unit-minitest.patch

hsbt (Hiroshi SHIBATA), 04/26/2014 08:35 AM

View differences:

test/lib/minitest/.document
1
# Ignore README.txt, it is included in the minitest documentation.
2
*.rb
test/lib/minitest/README.txt
1
= minitest/{unit,spec,mock,benchmark}
2

  
3
home :: https://github.com/seattlerb/minitest
4
rdoc :: http://docs.seattlerb.org/minitest
5
vim  :: https://github.com/sunaku/vim-ruby-minitest
6

  
7
== DESCRIPTION:
8

  
9
minitest provides a complete suite of testing facilities supporting
10
TDD, BDD, mocking, and benchmarking.
11

  
12
    "I had a class with Jim Weirich on testing last week and we were
13
     allowed to choose our testing frameworks. Kirk Haines and I were
14
     paired up and we cracked open the code for a few test
15
     frameworks...
16

  
17
     I MUST say that minitest is *very* readable / understandable
18
     compared to the 'other two' options we looked at. Nicely done and
19
     thank you for helping us keep our mental sanity."
20

  
21
    -- Wayne E. Seguin
22

  
23
minitest/unit is a small and incredibly fast unit testing framework.
24
It provides a rich set of assertions to make your tests clean and
25
readable.
26

  
27
minitest/spec is a functionally complete spec engine. It hooks onto
28
minitest/unit and seamlessly bridges test assertions over to spec
29
expectations.
30

  
31
minitest/benchmark is an awesome way to assert the performance of your
32
algorithms in a repeatable manner. Now you can assert that your newb
33
co-worker doesn't replace your linear algorithm with an exponential
34
one!
35

  
36
minitest/mock by Steven Baker, is a beautifully tiny mock (and stub)
37
object framework.
38

  
39
minitest/pride shows pride in testing and adds coloring to your test
40
output. I guess it is an example of how to write IO pipes too. :P
41

  
42
minitest/unit is meant to have a clean implementation for language
43
implementors that need a minimal set of methods to bootstrap a working
44
test suite. For example, there is no magic involved for test-case
45
discovery.
46

  
47
    "Again, I can't praise enough the idea of a testing/specing
48
     framework that I can actually read in full in one sitting!"
49

  
50
    -- Piotr Szotkowski
51

  
52
Comparing to rspec:
53

  
54
    rspec is a testing DSL. minitest is ruby.
55

  
56
    -- Adam Hawkins, "Bow Before MiniTest"
57

  
58
minitest doesn't reinvent anything that ruby already provides, like:
59
classes, modules, inheritance, methods. This means you only have to
60
learn ruby to use minitest and all of your regular OO practices like
61
extract-method refactorings still apply.
62

  
63
== FEATURES/PROBLEMS:
64

  
65
* minitest/autorun - the easy and explicit way to run all your tests.
66
* minitest/unit - a very fast, simple, and clean test system.
67
* minitest/spec - a very fast, simple, and clean spec system.
68
* minitest/mock - a simple and clean mock/stub system.
69
* minitest/benchmark - an awesome way to assert your algorithm's performance.
70
* minitest/pride - show your pride in testing!
71
* Incredibly small and fast runner, but no bells and whistles.
72

  
73
== RATIONALE:
74

  
75
See design_rationale.rb to see how specs and tests work in minitest.
76

  
77
== SYNOPSIS:
78

  
79
Given that you'd like to test the following class:
80

  
81
  class Meme
82
    def i_can_has_cheezburger?
83
      "OHAI!"
84
    end
85

  
86
    def will_it_blend?
87
      "YES!"
88
    end
89
  end
90

  
91
=== Unit tests
92

  
93
  require 'minitest/autorun'
94

  
95
  class TestMeme < MiniTest::Unit::TestCase
96
    def setup
97
      @meme = Meme.new
98
    end
99

  
100
    def test_that_kitty_can_eat
101
      assert_equal "OHAI!", @meme.i_can_has_cheezburger?
102
    end
103

  
104
    def test_that_it_will_not_blend
105
      refute_match /^no/i, @meme.will_it_blend?
106
    end
107

  
108
    def test_that_will_be_skipped
109
      skip "test this later"
110
    end
111
  end
112

  
113
=== Specs
114

  
115
  require 'minitest/autorun'
116

  
117
  describe Meme do
118
    before do
119
      @meme = Meme.new
120
    end
121

  
122
    describe "when asked about cheeseburgers" do
123
      it "must respond positively" do
124
        @meme.i_can_has_cheezburger?.must_equal "OHAI!"
125
      end
126
    end
127

  
128
    describe "when asked about blending possibilities" do
129
      it "won't say no" do
130
        @meme.will_it_blend?.wont_match /^no/i
131
      end
132
    end
133
  end
134

  
135
For matchers support check out:
136

  
137
https://github.com/zenspider/minitest-matchers
138

  
139
=== Benchmarks
140

  
141
Add benchmarks to your regular unit tests. If the unit tests fail, the
142
benchmarks won't run.
143

  
144
  # optionally run benchmarks, good for CI-only work!
145
  require 'minitest/benchmark' if ENV["BENCH"]
146

  
147
  class TestMeme < MiniTest::Unit::TestCase
148
    # Override self.bench_range or default range is [1, 10, 100, 1_000, 10_000]
149
    def bench_my_algorithm
150
      assert_performance_linear 0.9999 do |n| # n is a range value
151
        @obj.my_algorithm(n)
152
      end
153
    end
154
  end
155

  
156
Or add them to your specs. If you make benchmarks optional, you'll
157
need to wrap your benchmarks in a conditional since the methods won't
158
be defined.
159

  
160
  describe Meme do
161
    if ENV["BENCH"] then
162
      bench_performance_linear "my_algorithm", 0.9999 do |n|
163
        100.times do
164
          @obj.my_algorithm(n)
165
        end
166
      end
167
    end
168
  end
169

  
170
outputs something like:
171

  
172
  # Running benchmarks:
173

  
174
  TestBlah	100	1000	10000
175
  bench_my_algorithm	 0.006167	 0.079279	 0.786993
176
  bench_other_algorithm	 0.061679	 0.792797	 7.869932
177

  
178
Output is tab-delimited to make it easy to paste into a spreadsheet.
179

  
180
=== Mocks
181

  
182
  class MemeAsker
183
    def initialize(meme)
184
      @meme = meme
185
    end
186

  
187
    def ask(question)
188
      method = question.tr(" ","_") + "?"
189
      @meme.__send__(method)
190
    end
191
  end
192

  
193
  require 'minitest/autorun'
194

  
195
  describe MemeAsker do
196
    before do
197
      @meme = MiniTest::Mock.new
198
      @meme_asker = MemeAsker.new @meme
199
    end
200

  
201
    describe "#ask" do
202
      describe "when passed an unpunctuated question" do
203
        it "should invoke the appropriate predicate method on the meme" do
204
          @meme.expect :will_it_blend?, :return_value
205
          @meme_asker.ask "will it blend"
206
          @meme.verify
207
        end
208
      end
209
    end
210
  end
211

  
212
=== Stubs
213

  
214
  def test_stale_eh
215
    obj_under_test = Something.new
216

  
217
    refute obj_under_test.stale?
218

  
219
    Time.stub :now, Time.at(0) do   # stub goes away once the block is done
220
      assert obj_under_test.stale?
221
    end
222
  end
223

  
224
A note on stubbing: In order to stub a method, the method must
225
actually exist prior to stubbing. Use a singleton method to create a
226
new non-existing method:
227

  
228
  def obj_under_test.fake_method
229
    ...
230
  end
231

  
232
=== Customizable Test Runner Types:
233

  
234
MiniTest::Unit.runner=(runner) provides an easy way of creating custom
235
test runners for specialized needs. Justin Weiss provides the
236
following real-world example to create an alternative to regular
237
fixture loading:
238

  
239
  class MiniTestWithHooks::Unit < MiniTest::Unit
240
    def before_suites
241
    end
242

  
243
    def after_suites
244
    end
245

  
246
    def _run_suites(suites, type)
247
      begin
248
        before_suites
249
        super(suites, type)
250
      ensure
251
        after_suites
252
      end
253
    end
254

  
255
    def _run_suite(suite, type)
256
      begin
257
        suite.before_suite
258
        super(suite, type)
259
      ensure
260
        suite.after_suite
261
      end
262
    end
263
  end
264

  
265
  module MiniTestWithTransactions
266
    class Unit < MiniTestWithHooks::Unit
267
      include TestSetupHelper
268

  
269
      def before_suites
270
        super
271
        setup_nested_transactions
272
        # load any data we want available for all tests
273
      end
274

  
275
      def after_suites
276
        teardown_nested_transactions
277
        super
278
      end
279
    end
280
  end
281

  
282
  MiniTest::Unit.runner = MiniTestWithTransactions::Unit.new
283

  
284
== FAQ
285

  
286
=== How to test SimpleDelegates?
287

  
288
The following implementation and test:
289

  
290
    class Worker < SimpleDelegator
291
      def work
292
      end
293
    end
294

  
295
    describe Worker do
296
      before do
297
        @worker = Worker.new(Object.new)
298
      end
299

  
300
      it "must respond to work" do
301
        @worker.must_respond_to :work
302
      end
303
    end
304

  
305
outputs a failure:
306

  
307
      1) Failure:
308
    Worker#test_0001_must respond to work [bug11.rb:16]:
309
    Expected #<Object:0x007f9e7184f0a0> (Object) to respond to #work.
310

  
311
Worker is a SimpleDelegate which in 1.9+ is a subclass of BasicObject.
312
Expectations are put on Object (one level down) so the Worker
313
(SimpleDelegate) hits `method_missing` and delegates down to the
314
`Object.new` instance. That object doesn't respond to work so the test
315
fails.
316

  
317
You can bypass `SimpleDelegate#method_missing` by extending the worker
318
with `MiniTest::Expectations`. You can either do that in your setup at
319
the instance level, like:
320

  
321
    before do
322
      @worker = Worker.new(Object.new)
323
      @worker.extend MiniTest::Expectations
324
    end
325

  
326
or you can extend the Worker class (within the test file!), like:
327

  
328
    class Worker
329
      include ::MiniTest::Expectations
330
    end
331

  
332
== Known Extensions:
333

  
334
capybara_minitest_spec      :: Bridge between Capybara RSpec matchers and MiniTest::Spec expectations (e.g. page.must_have_content('Title')).
335
minispec-metadata           :: Metadata for describe/it blocks
336
                               (e.g. `it 'requires JS driver', js: true do`)
337
minitest-ansi               :: Colorize minitest output with ANSI colors.
338
minitest-around             :: Around block for minitest. An alternative to setup/teardown dance.
339
minitest-capistrano         :: Assertions and expectations for testing Capistrano recipes
340
minitest-capybara           :: Capybara matchers support for minitest unit and spec
341
minitest-chef-handler       :: Run Minitest suites as Chef report handlers
342
minitest-ci                 :: CI reporter plugin for MiniTest.
343
minitest-colorize           :: Colorize MiniTest output and show failing tests instantly.
344
minitest-context            :: Defines contexts for code reuse in MiniTest
345
                               specs that share common expectations.
346
minitest-debugger           :: Wraps assert so failed assertions drop into
347
                               the ruby debugger.
348
minitest-display            :: Patches MiniTest to allow for an easily configurable output.
349
minitest-emoji              :: Print out emoji for your test passes, fails, and skips.
350
minitest-english            :: Semantically symmetric aliases for assertions and expectations.
351
minitest-excludes           :: Clean API for excluding certain tests you
352
                               don't want to run under certain conditions.
353
minitest-firemock           :: Makes your MiniTest mocks more resilient.
354
minitest-great_expectations :: Generally useful additions to minitest's assertions and expectations
355
minitest-growl              :: Test notifier for minitest via growl.
356
minitest-implicit-subject   :: Implicit declaration of the test subject.
357
minitest-instrument         :: Instrument ActiveSupport::Notifications when
358
                               test method is executed
359
minitest-instrument-db      :: Store information about speed of test
360
                               execution provided by minitest-instrument in database
361
minitest-libnotify          :: Test notifier for minitest via libnotify.
362
minitest-macruby            :: Provides extensions to minitest for macruby UI testing.
363
minitest-matchers           :: Adds support for RSpec-style matchers to minitest.
364
minitest-metadata           :: Annotate tests with metadata (key-value).
365
minitest-mongoid            :: Mongoid assertion matchers for MiniTest
366
minitest-must_not           :: Provides must_not as an alias for wont in MiniTest
367
minitest-nc                 :: Test notifier for minitest via Mountain Lion's Notification Center
368
minitest-predicates         :: Adds support for .predicate? methods
369
minitest-rails              :: MiniTest integration for Rails 3.x
370
minitest-rails-capybara     :: Capybara integration for MiniTest::Rails
371
minitest-reporters          :: Create customizable MiniTest output formats
372
minitest-should_syntax      :: RSpec-style +x.should == y+ assertions for MiniTest
373
minitest-shouldify          :: Adding all manner of shoulds to MiniTest (bad idea)
374
minitest-spec-context       :: Provides rspec-ish context method to MiniTest::Spec
375
minitest-spec-magic         :: Minitest::Spec extensions for Rails and beyond
376
minitest-spec-rails         :: Drop in MiniTest::Spec superclass for ActiveSupport::TestCase.
377
minitest-stub-const         :: Stub constants for the duration of a block
378
minitest-tags               :: add tags for minitest
379
minitest-wscolor            :: Yet another test colorizer.
380
minitest_owrapper           :: Get tests results as a TestResult object.
381
minitest_should             :: Shoulda style syntax for minitest test::unit.
382
minitest_tu_shim            :: minitest_tu_shim bridges between test/unit and minitest.
383
mongoid-minitest            :: MiniTest matchers for Mongoid.
384
pry-rescue                  :: A pry plugin w/ minitest support. See pry-rescue/minitest.rb.
385

  
386
== Unknown Extensions:
387

  
388
Authors... Please send me a pull request with a description of your minitest extension.
389

  
390
* assay-minitest
391
* detroit-minitest
392
* em-minitest-spec
393
* flexmock-minitest
394
* guard-minitest
395
* guard-minitest-decisiv
396
* minitest-activemodel
397
* minitest-ar-assertions
398
* minitest-capybara-unit
399
* minitest-colorer
400
* minitest-deluxe
401
* minitest-extra-assertions
402
* minitest-rails-shoulda
403
* minitest-spec
404
* minitest-spec-should
405
* minitest-sugar
406
* minitest_should
407
* mongoid-minitest
408
* spork-minitest
409

  
410
== REQUIREMENTS:
411

  
412
* Ruby 1.8, maybe even 1.6 or lower. No magic is involved.
413

  
414
== INSTALL:
415

  
416
  sudo gem install minitest
417

  
418
On 1.9, you already have it. To get newer candy you can still install
419
the gem, but you'll need to activate the gem explicitly to use it:
420

  
421
  require 'rubygems'
422
  gem 'minitest' # ensures you're using the gem, and not the built in MT
423
  require 'minitest/autorun'
424

  
425
  # ... usual testing stuffs ...
426

  
427
DO NOTE: There is a serious problem with the way that ruby 1.9/2.0
428
packages their own gems. They install a gem specification file, but
429
don't install the gem contents in the gem path. This messes up
430
Gem.find_files and many other things (gem which, gem contents, etc).
431

  
432
Just install minitest as a gem for real and you'll be happier.
433

  
434
== LICENSE:
435

  
436
(The MIT License)
437

  
438
Copyright (c) Ryan Davis, seattle.rb
439

  
440
Permission is hereby granted, free of charge, to any person obtaining
441
a copy of this software and associated documentation files (the
442
'Software'), to deal in the Software without restriction, including
443
without limitation the rights to use, copy, modify, merge, publish,
444
distribute, sublicense, and/or sell copies of the Software, and to
445
permit persons to whom the Software is furnished to do so, subject to
446
the following conditions:
447

  
448
The above copyright notice and this permission notice shall be
449
included in all copies or substantial portions of the Software.
450

  
451
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
452
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
453
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
454
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
455
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
456
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
457
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
test/lib/minitest/autorun.rb
1
# encoding: utf-8
2
######################################################################
3
# This file is imported from the minitest project.
4
# DO NOT make modifications in this repo. They _will_ be reverted!
5
# File a patch instead and assign it to Ryan Davis.
6
######################################################################
7

  
8
begin
9
  require 'rubygems'
10
  gem 'minitest'
11
rescue Gem::LoadError
12
  # do nothing
13
end
14

  
15
require 'minitest/unit'
16
require 'minitest/spec'
17
require 'minitest/mock'
18

  
19
MiniTest::Unit.autorun
test/lib/minitest/benchmark.rb
1
# encoding: utf-8
2
######################################################################
3
# This file is imported from the minitest project.
4
# DO NOT make modifications in this repo. They _will_ be reverted!
5
# File a patch instead and assign it to Ryan Davis.
6
######################################################################
7

  
8
require 'minitest/unit'
9
require 'minitest/spec'
10

  
11
class MiniTest::Unit # :nodoc:
12
  def run_benchmarks # :nodoc:
13
    _run_anything :benchmark
14
  end
15

  
16
  def benchmark_suite_header suite # :nodoc:
17
    "\n#{suite}\t#{suite.bench_range.join("\t")}"
18
  end
19

  
20
  class TestCase
21
    ##
22
    # Returns a set of ranges stepped exponentially from +min+ to
23
    # +max+ by powers of +base+. Eg:
24
    #
25
    #   bench_exp(2, 16, 2) # => [2, 4, 8, 16]
26

  
27
    def self.bench_exp min, max, base = 10
28
      min = (Math.log10(min) / Math.log10(base)).to_i
29
      max = (Math.log10(max) / Math.log10(base)).to_i
30

  
31
      (min..max).map { |m| base ** m }.to_a
32
    end
33

  
34
    ##
35
    # Returns a set of ranges stepped linearly from +min+ to +max+ by
36
    # +step+. Eg:
37
    #
38
    #   bench_linear(20, 40, 10) # => [20, 30, 40]
39

  
40
    def self.bench_linear min, max, step = 10
41
      (min..max).step(step).to_a
42
    rescue LocalJumpError # 1.8.6
43
      r = []; (min..max).step(step) { |n| r << n }; r
44
    end
45

  
46
    ##
47
    # Returns the benchmark methods (methods that start with bench_)
48
    # for that class.
49

  
50
    def self.benchmark_methods # :nodoc:
51
      public_instance_methods(true).grep(/^bench_/).map { |m| m.to_s }.sort
52
    end
53

  
54
    ##
55
    # Returns all test suites that have benchmark methods.
56

  
57
    def self.benchmark_suites
58
      TestCase.test_suites.reject { |s| s.benchmark_methods.empty? }
59
    end
60

  
61
    ##
62
    # Specifies the ranges used for benchmarking for that class.
63
    # Defaults to exponential growth from 1 to 10k by powers of 10.
64
    # Override if you need different ranges for your benchmarks.
65
    #
66
    # See also: ::bench_exp and ::bench_linear.
67

  
68
    def self.bench_range
69
      bench_exp 1, 10_000
70
    end
71

  
72
    ##
73
    # Runs the given +work+, gathering the times of each run. Range
74
    # and times are then passed to a given +validation+ proc. Outputs
75
    # the benchmark name and times in tab-separated format, making it
76
    # easy to paste into a spreadsheet for graphing or further
77
    # analysis.
78
    #
79
    # Ranges are specified by ::bench_range.
80
    #
81
    # Eg:
82
    #
83
    #   def bench_algorithm
84
    #     validation = proc { |x, y| ... }
85
    #     assert_performance validation do |n|
86
    #       @obj.algorithm(n)
87
    #     end
88
    #   end
89

  
90
    def assert_performance validation, &work
91
      range = self.class.bench_range
92

  
93
      io.print "#{__name__}"
94

  
95
      times = []
96

  
97
      range.each do |x|
98
        GC.start
99
        t0 = Time.now
100
        instance_exec(x, &work)
101
        t = Time.now - t0
102

  
103
        io.print "\t%9.6f" % t
104
        times << t
105
      end
106
      io.puts
107

  
108
      validation[range, times]
109
    end
110

  
111
    ##
112
    # Runs the given +work+ and asserts that the times gathered fit to
113
    # match a constant rate (eg, linear slope == 0) within a given
114
    # +threshold+. Note: because we're testing for a slope of 0, R^2
115
    # is not a good determining factor for the fit, so the threshold
116
    # is applied against the slope itself. As such, you probably want
117
    # to tighten it from the default.
118
    #
119
    # See http://www.graphpad.com/curvefit/goodness_of_fit.htm for
120
    # more details.
121
    #
122
    # Fit is calculated by #fit_linear.
123
    #
124
    # Ranges are specified by ::bench_range.
125
    #
126
    # Eg:
127
    #
128
    #   def bench_algorithm
129
    #     assert_performance_constant 0.9999 do |n|
130
    #       @obj.algorithm(n)
131
    #     end
132
    #   end
133

  
134
    def assert_performance_constant threshold = 0.99, &work
135
      validation = proc do |range, times|
136
        a, b, rr = fit_linear range, times
137
        assert_in_delta 0, b, 1 - threshold
138
        [a, b, rr]
139
      end
140

  
141
      assert_performance validation, &work
142
    end
143

  
144
    ##
145
    # Runs the given +work+ and asserts that the times gathered fit to
146
    # match a exponential curve within a given error +threshold+.
147
    #
148
    # Fit is calculated by #fit_exponential.
149
    #
150
    # Ranges are specified by ::bench_range.
151
    #
152
    # Eg:
153
    #
154
    #   def bench_algorithm
155
    #     assert_performance_exponential 0.9999 do |n|
156
    #       @obj.algorithm(n)
157
    #     end
158
    #   end
159

  
160
    def assert_performance_exponential threshold = 0.99, &work
161
      assert_performance validation_for_fit(:exponential, threshold), &work
162
    end
163

  
164
    ##
165
    # Runs the given +work+ and asserts that the times gathered fit to
166
    # match a logarithmic curve within a given error +threshold+.
167
    #
168
    # Fit is calculated by #fit_logarithmic.
169
    #
170
    # Ranges are specified by ::bench_range.
171
    #
172
    # Eg:
173
    #
174
    #   def bench_algorithm
175
    #     assert_performance_logarithmic 0.9999 do |n|
176
    #       @obj.algorithm(n)
177
    #     end
178
    #   end
179

  
180
    def assert_performance_logarithmic threshold = 0.99, &work
181
      assert_performance validation_for_fit(:logarithmic, threshold), &work
182
    end
183

  
184
    ##
185
    # Runs the given +work+ and asserts that the times gathered fit to
186
    # match a straight line within a given error +threshold+.
187
    #
188
    # Fit is calculated by #fit_linear.
189
    #
190
    # Ranges are specified by ::bench_range.
191
    #
192
    # Eg:
193
    #
194
    #   def bench_algorithm
195
    #     assert_performance_linear 0.9999 do |n|
196
    #       @obj.algorithm(n)
197
    #     end
198
    #   end
199

  
200
    def assert_performance_linear threshold = 0.99, &work
201
      assert_performance validation_for_fit(:linear, threshold), &work
202
    end
203

  
204
    ##
205
    # Runs the given +work+ and asserts that the times gathered curve
206
    # fit to match a power curve within a given error +threshold+.
207
    #
208
    # Fit is calculated by #fit_power.
209
    #
210
    # Ranges are specified by ::bench_range.
211
    #
212
    # Eg:
213
    #
214
    #   def bench_algorithm
215
    #     assert_performance_power 0.9999 do |x|
216
    #       @obj.algorithm
217
    #     end
218
    #   end
219

  
220
    def assert_performance_power threshold = 0.99, &work
221
      assert_performance validation_for_fit(:power, threshold), &work
222
    end
223

  
224
    ##
225
    # Takes an array of x/y pairs and calculates the general R^2 value.
226
    #
227
    # See: http://en.wikipedia.org/wiki/Coefficient_of_determination
228

  
229
    def fit_error xys
230
      y_bar  = sigma(xys) { |x, y| y } / xys.size.to_f
231
      ss_tot = sigma(xys) { |x, y| (y    - y_bar) ** 2 }
232
      ss_err = sigma(xys) { |x, y| (yield(x) - y) ** 2 }
233

  
234
      1 - (ss_err / ss_tot)
235
    end
236

  
237
    ##
238
    # To fit a functional form: y = ae^(bx).
239
    #
240
    # Takes x and y values and returns [a, b, r^2].
241
    #
242
    # See: http://mathworld.wolfram.com/LeastSquaresFittingExponential.html
243

  
244
    def fit_exponential xs, ys
245
      n     = xs.size
246
      xys   = xs.zip(ys)
247
      sxlny = sigma(xys) { |x,y| x * Math.log(y) }
248
      slny  = sigma(xys) { |x,y| Math.log(y)     }
249
      sx2   = sigma(xys) { |x,y| x * x           }
250
      sx    = sigma xs
251

  
252
      c = n * sx2 - sx ** 2
253
      a = (slny * sx2 - sx * sxlny) / c
254
      b = ( n * sxlny - sx * slny ) / c
255

  
256
      return Math.exp(a), b, fit_error(xys) { |x| Math.exp(a + b * x) }
257
    end
258

  
259
    ##
260
    # To fit a functional form: y = a + b*ln(x).
261
    #
262
    # Takes x and y values and returns [a, b, r^2].
263
    #
264
    # See: http://mathworld.wolfram.com/LeastSquaresFittingLogarithmic.html
265

  
266
    def fit_logarithmic xs, ys
267
      n     = xs.size
268
      xys   = xs.zip(ys)
269
      slnx2 = sigma(xys) { |x,y| Math.log(x) ** 2 }
270
      slnx  = sigma(xys) { |x,y| Math.log(x)      }
271
      sylnx = sigma(xys) { |x,y| y * Math.log(x)  }
272
      sy    = sigma(xys) { |x,y| y                }
273

  
274
      c = n * slnx2 - slnx ** 2
275
      b = ( n * sylnx - sy * slnx ) / c
276
      a = (sy - b * slnx) / n
277

  
278
      return a, b, fit_error(xys) { |x| a + b * Math.log(x) }
279
    end
280

  
281

  
282
    ##
283
    # Fits the functional form: a + bx.
284
    #
285
    # Takes x and y values and returns [a, b, r^2].
286
    #
287
    # See: http://mathworld.wolfram.com/LeastSquaresFitting.html
288

  
289
    def fit_linear xs, ys
290
      n   = xs.size
291
      xys = xs.zip(ys)
292
      sx  = sigma xs
293
      sy  = sigma ys
294
      sx2 = sigma(xs)  { |x|   x ** 2 }
295
      sxy = sigma(xys) { |x,y| x * y  }
296

  
297
      c = n * sx2 - sx**2
298
      a = (sy * sx2 - sx * sxy) / c
299
      b = ( n * sxy - sx * sy ) / c
300

  
301
      return a, b, fit_error(xys) { |x| a + b * x }
302
    end
303

  
304
    ##
305
    # To fit a functional form: y = ax^b.
306
    #
307
    # Takes x and y values and returns [a, b, r^2].
308
    #
309
    # See: http://mathworld.wolfram.com/LeastSquaresFittingPowerLaw.html
310

  
311
    def fit_power xs, ys
312
      n       = xs.size
313
      xys     = xs.zip(ys)
314
      slnxlny = sigma(xys) { |x, y| Math.log(x) * Math.log(y) }
315
      slnx    = sigma(xs)  { |x   | Math.log(x)               }
316
      slny    = sigma(ys)  { |   y| Math.log(y)               }
317
      slnx2   = sigma(xs)  { |x   | Math.log(x) ** 2          }
318

  
319
      b = (n * slnxlny - slnx * slny) / (n * slnx2 - slnx ** 2);
320
      a = (slny - b * slnx) / n
321

  
322
      return Math.exp(a), b, fit_error(xys) { |x| (Math.exp(a) * (x ** b)) }
323
    end
324

  
325
    ##
326
    # Enumerates over +enum+ mapping +block+ if given, returning the
327
    # sum of the result. Eg:
328
    #
329
    #   sigma([1, 2, 3])                # => 1 + 2 + 3 => 7
330
    #   sigma([1, 2, 3]) { |n| n ** 2 } # => 1 + 4 + 9 => 14
331

  
332
    def sigma enum, &block
333
      enum = enum.map(&block) if block
334
      enum.inject { |sum, n| sum + n }
335
    end
336

  
337
    ##
338
    # Returns a proc that calls the specified fit method and asserts
339
    # that the error is within a tolerable threshold.
340

  
341
    def validation_for_fit msg, threshold
342
      proc do |range, times|
343
        a, b, rr = send "fit_#{msg}", range, times
344
        assert_operator rr, :>=, threshold
345
        [a, b, rr]
346
      end
347
    end
348
  end
349
end
350

  
351
class MiniTest::Spec
352
  ##
353
  # This is used to define a new benchmark method. You usually don't
354
  # use this directly and is intended for those needing to write new
355
  # performance curve fits (eg: you need a specific polynomial fit).
356
  #
357
  # See ::bench_performance_linear for an example of how to use this.
358

  
359
  def self.bench name, &block
360
    define_method "bench_#{name.gsub(/\W+/, '_')}", &block
361
  end
362

  
363
  ##
364
  # Specifies the ranges used for benchmarking for that class.
365
  #
366
  #   bench_range do
367
  #     bench_exp(2, 16, 2)
368
  #   end
369
  #
370
  # See Unit::TestCase.bench_range for more details.
371

  
372
  def self.bench_range &block
373
    return super unless block
374

  
375
    meta = (class << self; self; end)
376
    meta.send :define_method, "bench_range", &block
377
  end
378

  
379
  ##
380
  # Create a benchmark that verifies that the performance is linear.
381
  #
382
  #   describe "my class" do
383
  #     bench_performance_linear "fast_algorithm", 0.9999 do |n|
384
  #       @obj.fast_algorithm(n)
385
  #     end
386
  #   end
387

  
388
  def self.bench_performance_linear name, threshold = 0.99, &work
389
    bench name do
390
      assert_performance_linear threshold, &work
391
    end
392
  end
393

  
394
  ##
395
  # Create a benchmark that verifies that the performance is constant.
396
  #
397
  #   describe "my class" do
398
  #     bench_performance_constant "zoom_algorithm!" do |n|
399
  #       @obj.zoom_algorithm!(n)
400
  #     end
401
  #   end
402

  
403
  def self.bench_performance_constant name, threshold = 0.99, &work
404
    bench name do
405
      assert_performance_constant threshold, &work
406
    end
407
  end
408

  
409
  ##
410
  # Create a benchmark that verifies that the performance is exponential.
411
  #
412
  #   describe "my class" do
413
  #     bench_performance_exponential "algorithm" do |n|
414
  #       @obj.algorithm(n)
415
  #     end
416
  #   end
417

  
418
  def self.bench_performance_exponential name, threshold = 0.99, &work
419
    bench name do
420
      assert_performance_exponential threshold, &work
421
    end
422
  end
423
end
test/lib/minitest/hell.rb
1
# encoding: utf-8
2
######################################################################
3
# This file is imported from the minitest project.
4
# DO NOT make modifications in this repo. They _will_ be reverted!
5
# File a patch instead and assign it to Ryan Davis.
6
######################################################################
7

  
8
require "minitest/parallel_each"
9

  
10
# :stopdoc:
11
class Minitest::Unit::TestCase
12
  class << self
13
    alias :old_test_order :test_order
14

  
15
    def test_order
16
      :parallel
17
    end
18
  end
19
end
20
# :startdoc:
test/lib/minitest/mock.rb
1
# encoding: utf-8
2
######################################################################
3
# This file is imported from the minitest project.
4
# DO NOT make modifications in this repo. They _will_ be reverted!
5
# File a patch instead and assign it to Ryan Davis.
6
######################################################################
7

  
8
class MockExpectationError < StandardError; end # :nodoc:
9

  
10
##
11
# A simple and clean mock object framework.
12

  
13
module MiniTest # :nodoc:
14

  
15
  ##
16
  # All mock objects are an instance of Mock
17

  
18
  class Mock
19
    alias :__respond_to? :respond_to?
20

  
21
    skip_methods = %w(object_id respond_to_missing? inspect === to_s)
22

  
23
    instance_methods.each do |m|
24
      undef_method m unless skip_methods.include?(m.to_s) || m =~ /^__/
25
    end
26

  
27
    def initialize # :nodoc:
28
      @expected_calls = Hash.new { |calls, name| calls[name] = [] }
29
      @actual_calls   = Hash.new { |calls, name| calls[name] = [] }
30
    end
31

  
32
    ##
33
    # Expect that method +name+ is called, optionally with +args+ or a
34
    # +blk+, and returns +retval+.
35
    #
36
    #   @mock.expect(:meaning_of_life, 42)
37
    #   @mock.meaning_of_life # => 42
38
    #
39
    #   @mock.expect(:do_something_with, true, [some_obj, true])
40
    #   @mock.do_something_with(some_obj, true) # => true
41
    #
42
    #   @mock.expect(:do_something_else, true) do |a1, a2|
43
    #     a1 == "buggs" && a2 == :bunny
44
    #   end
45
    #
46
    # +args+ is compared to the expected args using case equality (ie, the
47
    # '===' operator), allowing for less specific expectations.
48
    #
49
    #   @mock.expect(:uses_any_string, true, [String])
50
    #   @mock.uses_any_string("foo") # => true
51
    #   @mock.verify  # => true
52
    #
53
    #   @mock.expect(:uses_one_string, true, ["foo"]
54
    #   @mock.uses_one_string("bar") # => true
55
    #   @mock.verify  # => raises MockExpectationError
56

  
57
    def expect(name, retval, args=[], &blk)
58
      if block_given?
59
        raise ArgumentError, "args ignored when block given" unless args.empty?
60
        @expected_calls[name] << { :retval => retval, :block => blk }
61
      else
62
        raise ArgumentError, "args must be an array" unless Array === args
63
        @expected_calls[name] << { :retval => retval, :args => args }
64
      end
65
      self
66
    end
67

  
68
    def __call name, data # :nodoc:
69
      case data
70
      when Hash then
71
        "#{name}(#{data[:args].inspect[1..-2]}) => #{data[:retval].inspect}"
72
      else
73
        data.map { |d| __call name, d }.join ", "
74
      end
75
    end
76

  
77
    ##
78
    # Verify that all methods were called as expected. Raises
79
    # +MockExpectationError+ if the mock object was not called as
80
    # expected.
81

  
82
    def verify
83
      @expected_calls.each do |name, calls|
84
        calls.each do |expected|
85
          msg1 = "expected #{__call name, expected}"
86
          msg2 = "#{msg1}, got [#{__call name, @actual_calls[name]}]"
87

  
88
          raise MockExpectationError, msg2 if
89
            @actual_calls.has_key?(name) and
90
            not @actual_calls[name].include?(expected)
91

  
92
          raise MockExpectationError, msg1 unless
93
            @actual_calls.has_key?(name) and
94
            @actual_calls[name].include?(expected)
95
        end
96
      end
97
      true
98
    end
99

  
100
    def method_missing(sym, *args) # :nodoc:
101
      unless @expected_calls.has_key?(sym) then
102
        raise NoMethodError, "unmocked method %p, expected one of %p" %
103
          [sym, @expected_calls.keys.sort_by(&:to_s)]
104
      end
105

  
106
      index = @actual_calls[sym].length
107
      expected_call = @expected_calls[sym][index]
108

  
109
      unless expected_call then
110
        raise MockExpectationError, "No more expects available for %p: %p" %
111
          [sym, args]
112
      end
113

  
114
      expected_args, retval, val_block =
115
        expected_call.values_at(:args, :retval, :block)
116

  
117
      if val_block then
118
        raise MockExpectationError, "mocked method %p failed block w/ %p" %
119
          [sym, args] unless val_block.call(args)
120

  
121
        # keep "verify" happy
122
        @actual_calls[sym] << expected_call
123
        return retval
124
      end
125

  
126
      if expected_args.size != args.size then
127
        raise ArgumentError, "mocked method %p expects %d arguments, got %d" %
128
          [sym, expected_args.size, args.size]
129
      end
130

  
131
      fully_matched = expected_args.zip(args).all? { |mod, a|
132
        mod === a or mod == a
133
      }
134

  
135
      unless fully_matched then
136
        raise MockExpectationError, "mocked method %p called with unexpected arguments %p" %
137
          [sym, args]
138
      end
139

  
140
      @actual_calls[sym] << {
141
        :retval => retval,
142
        :args => expected_args.zip(args).map { |mod, a| mod === a ? mod : a }
143
      }
144

  
145
      retval
146
    end
147

  
148
    def respond_to?(sym, include_private = false) # :nodoc:
149
      return true if @expected_calls.has_key?(sym.to_sym)
150
      return __respond_to?(sym, include_private)
151
    end
152
  end
153
end
154

  
155
class Object # :nodoc:
156

  
157
  ##
158
  # Add a temporary stubbed method replacing +name+ for the duration
159
  # of the +block+. If +val_or_callable+ responds to #call, then it
160
  # returns the result of calling it, otherwise returns the value
161
  # as-is. Cleans up the stub at the end of the +block+. The method
162
  # +name+ must exist before stubbing.
163
  #
164
  #     def test_stale_eh
165
  #       obj_under_test = Something.new
166
  #       refute obj_under_test.stale?
167
  #
168
  #       Time.stub :now, Time.at(0) do
169
  #         assert obj_under_test.stale?
170
  #       end
171
  #     end
172

  
173
  def stub name, val_or_callable, &block
174
    new_name = "__minitest_stub__#{name}"
175

  
176
    metaclass = class << self; self; end
177

  
178
    if respond_to? name and not methods.map(&:to_s).include? name.to_s then
179
      metaclass.send :define_method, name do |*args|
180
        super(*args)
181
      end
182
    end
183

  
184
    metaclass.send :alias_method, new_name, name
185

  
186
    metaclass.send :define_method, name do |*args|
187
      if val_or_callable.respond_to? :call then
188
        val_or_callable.call(*args)
189
      else
190
        val_or_callable
191
      end
192
    end
193

  
194
    yield self
195
  ensure
196
    metaclass.send :undef_method, name
197
    metaclass.send :alias_method, name, new_name
198
    metaclass.send :undef_method, new_name
199
  end
200
end
test/lib/minitest/parallel_each.rb
1
# encoding: utf-8
2
######################################################################
3
# This file is imported from the minitest project.
4
# DO NOT make modifications in this repo. They _will_ be reverted!
5
# File a patch instead and assign it to Ryan Davis.
6
######################################################################
7

  
8
##
9
# Provides a parallel #each that lets you enumerate using N threads.
10
# Use environment variable N to customize. Defaults to 2. Enumerable,
11
# so all the goodies come along (tho not all are wrapped yet to
12
# return another ParallelEach instance).
13

  
14
class ParallelEach
15
  require 'thread'
16
  include Enumerable
17

  
18
  ##
19
  # How many Threads to use for this parallel #each.
20

  
21
  N = (ENV['N'] || 2).to_i
22

  
23
  ##
24
  # Create a new ParallelEach instance over +list+.
25

  
26
  def initialize list
27
    @queue = Queue.new # *sigh*... the Queue api sucks sooo much...
28

  
29
    list.each { |i| @queue << i }
30
    N.times { @queue << nil }
31
  end
32

  
33
  def grep pattern # :nodoc:
34
    self.class.new super
35
  end
36

  
37
  def select(&block) # :nodoc:
38
    self.class.new super
39
  end
40

  
41
  alias find_all select # :nodoc:
42

  
43
  ##
44
  # Starts N threads that yield each element to your block. Joins the
45
  # threads at the end.
46

  
47
  def each
48
    threads = N.times.map {
49
      Thread.new do
50
        Thread.current.abort_on_exception = true
51
        while job = @queue.pop
52
          yield job
53
        end
54
      end
55
    }
56
    threads.map(&:join)
57
  end
58

  
59
  def count
60
    [@queue.size - N, 0].max
61
  end
62

  
63
  alias_method :size, :count
64
end
65

  
66
class MiniTest::Unit
67
  alias _old_run_suites _run_suites
68

  
69
  ##
70
  # Runs all the +suites+ for a given +type+. Runs suites declaring
71
  # a test_order of +:parallel+ in parallel, and everything else
72
  # serial.
73

  
74
  def _run_suites suites, type
75
    parallel, serial = suites.partition { |s| s.test_order == :parallel }
76

  
77
    ParallelEach.new(parallel).map { |suite| _run_suite suite, type } +
78
     serial.map { |suite| _run_suite suite, type }
79
  end
80
end
test/lib/minitest/pride.rb
1
# encoding: utf-8
2
######################################################################
3
# This file is imported from the minitest project.
4
# DO NOT make modifications in this repo. They _will_ be reverted!
5
# File a patch instead and assign it to Ryan Davis.
6
######################################################################
7

  
8
require "minitest/unit"
9

  
10
##
11
# Show your testing pride!
12

  
13
class PrideIO
14

  
15
  # Start an escape sequence
16
  ESC = "\e["
17

  
18
  # End the escape sequence
19
  NND = "#{ESC}0m"
20

  
21
  # The IO we're going to pipe through.
22
  attr_reader :io
23

  
24
  def initialize io # :nodoc:
25
    @io = io
26
    # stolen from /System/Library/Perl/5.10.0/Term/ANSIColor.pm
27
    # also reference http://en.wikipedia.org/wiki/ANSI_escape_code
28
    @colors ||= (31..36).to_a
29
    @size   = @colors.size
30
    @index  = 0
31
    # io.sync = true
32
  end
33

  
34
  ##
35
  # Wrap print to colorize the output.
36

  
37
  def print o
38
    case o
39
    when "." then
40
      io.print pride o
41
    when "E", "F" then
42
      io.print "#{ESC}41m#{ESC}37m#{o}#{NND}"
43
    else
44
      io.print o
45
    end
46
  end
47

  
48
  def puts(*o) # :nodoc:
49
    o.map! { |s|
50
      s.to_s.sub(/Finished tests/) {
51
        @index = 0
52
        'Fabulous tests'.split(//).map { |c|
53
          pride(c)
54
        }.join
55
      }
56
    }
57

  
58
    super
59
  end
60

  
61
  ##
62
  # Color a string.
63

  
64
  def pride string
65
    string = "*" if string == "."
66
    c = @colors[@index % @size]
67
    @index += 1
68
    "#{ESC}#{c}m#{string}#{NND}"
69
  end
70

  
71
  def method_missing msg, *args # :nodoc:
72
    io.send(msg, *args)
73
  end
74
end
75

  
76
##
77
# If you thought the PrideIO was colorful...
78
#
79
# (Inspired by lolcat, but with clean math)
80

  
81
class PrideLOL < PrideIO
82
  PI_3 = Math::PI / 3 # :nodoc:
83

  
84
  def initialize io # :nodoc:
85
    # walk red, green, and blue around a circle separated by equal thirds.
86
    #
87
    # To visualize, type this into wolfram-alpha:
88
    #
89
    #   plot (3*sin(x)+3), (3*sin(x+2*pi/3)+3), (3*sin(x+4*pi/3)+3)
90

  
91
    # 6 has wide pretty gradients. 3 == lolcat, about half the width
92
    @colors = (0...(6 * 7)).map { |n|
93
      n *= 1.0 / 6
94
      r  = (3 * Math.sin(n           ) + 3).to_i
95
      g  = (3 * Math.sin(n + 2 * PI_3) + 3).to_i
96
      b  = (3 * Math.sin(n + 4 * PI_3) + 3).to_i
97

  
98
      # Then we take rgb and encode them in a single number using base 6.
99
      # For some mysterious reason, we add 16... to clear the bottom 4 bits?
100
      # Yes... they're ugly.
101

  
102
      36 * r + 6 * g + b + 16
103
    }
104

  
105
    super
106
  end
107

  
108
  ##
109
  # Make the string even more colorful. Damnit.
110

  
111
  def pride string
112
    c = @colors[@index % @size]
113
    @index += 1
114
    "#{ESC}38;5;#{c}m#{string}#{NND}"
115
  end
116
end
117

  
118
klass = ENV['TERM'] =~ /^xterm|-256color$/ ? PrideLOL : PrideIO
119
MiniTest::Unit.output = klass.new(MiniTest::Unit.output)
test/lib/minitest/spec.rb
1
# encoding: utf-8
2
######################################################################
3
# This file is imported from the minitest project.
4
# DO NOT make modifications in this repo. They _will_ be reverted!
5
# File a patch instead and assign it to Ryan Davis.
6
######################################################################
7

  
8
#!/usr/bin/ruby -w
9

  
10
require 'minitest/unit'
11

  
12
class Module # :nodoc:
13
  def infect_an_assertion meth, new_name, dont_flip = false # :nodoc:
14
    # warn "%-22p -> %p %p" % [meth, new_name, dont_flip]
15
    self.class_eval <<-EOM
16
      def #{new_name} *args
17
        case
18
        when Proc === self then
19
          MiniTest::Spec.current.#{meth}(*args, &self)
20
        when #{!!dont_flip} then
21
          MiniTest::Spec.current.#{meth}(self, *args)
22
        else
23
          MiniTest::Spec.current.#{meth}(args.first, self, *args[1..-1])
24
        end
25
      end
26
    EOM
27
  end
28

  
29
  ##
30
  # infect_with_assertions has been removed due to excessive clever.
31
  # Use infect_an_assertion directly instead.
32

  
33
  def infect_with_assertions(pos_prefix, neg_prefix,
34
                             skip_re,
35
                             dont_flip_re = /\c0/,
36
                             map = {})
37
    abort "infect_with_assertions is dead. Use infect_an_assertion directly"
38
  end
39
end
40

  
41
module Kernel # :nodoc:
42
  ##
43
  # Describe a series of expectations for a given target +desc+.
44
  #
45
  # TODO: find good tutorial url.
46
  #
47
  # Defines a test class subclassing from either MiniTest::Spec or
48
  # from the surrounding describe's class. The surrounding class may
49
  # subclass MiniTest::Spec manually in order to easily share code:
50
  #
51
  #     class MySpec < MiniTest::Spec
52
  #       # ... shared code ...
53
  #     end
54
  #
55
  #     class TestStuff < MySpec
56
  #       it "does stuff" do
57
  #         # shared code available here
58
  #       end
59
  #       describe "inner stuff" do
60
  #         it "still does stuff" do
61
  #           # ...and here
62
  #         end
63
  #       end
64
  #     end
65

  
66
  def describe desc, additional_desc = nil, &block # :doc:
67
    stack = MiniTest::Spec.describe_stack
68
    name  = [stack.last, desc, additional_desc].compact.join("::")
69
    sclas = stack.last || if Class === self && is_a?(MiniTest::Spec::DSL) then
70
                            self
71
                          else
72
                            MiniTest::Spec.spec_type desc
73
                          end
74

  
75
    cls = sclas.create name, desc
76

  
77
    stack.push cls
78
    cls.class_eval(&block)
79
    stack.pop
80
    cls
81
  end
82
  private :describe
83
end
84

  
85
##
86
# MiniTest::Spec -- The faster, better, less-magical spec framework!
87
#
88
# For a list of expectations, see MiniTest::Expectations.
89

  
90
class MiniTest::Spec < MiniTest::Unit::TestCase
91

  
92
  ##
93
  # Oh look! A MiniTest::Spec::DSL module! Eat your heart out DHH.
94

  
95
  module DSL
96
    ##
97
    # Contains pairs of matchers and Spec classes to be used to
98
    # calculate the superclass of a top-level describe. This allows for
99
    # automatically customizable spec types.
100
    #
101
    # See: register_spec_type and spec_type
102

  
103
    TYPES = [[//, MiniTest::Spec]]
104

  
105
    ##
106
    # Register a new type of spec that matches the spec's description.
107
    # This method can take either a Regexp and a spec class or a spec
108
    # class and a block that takes the description and returns true if
109
    # it matches.
110
    #
111
    # Eg:
112
    #
113
    #     register_spec_type(/Controller$/, MiniTest::Spec::Rails)
114
    #
115
    # or:
116
    #
117
    #     register_spec_type(MiniTest::Spec::RailsModel) do |desc|
118
    #       desc.superclass == ActiveRecord::Base
119
    #     end
120

  
121
    def register_spec_type(*args, &block)
122
      if block then
123
        matcher, klass = block, args.first
124
      else
125
        matcher, klass = *args
126
      end
127
      TYPES.unshift [matcher, klass]
... This diff was truncated because it exceeds the maximum size that can be displayed.