Ruby on Rails on Minitest 1
Setting Expectations Introductory Talk. Very Little Code. Not going to teach testing or TDD. What & why, not how. 218 Slides, 5.45 SPM. 2
WTF is minitest? 3
What is Minitest? Replacement for ruby 1.8 s test/unit. Originally 90 lines of code, only test/unit basics. Available as a gem, and ships with ruby 1.9.1 & up. Meant to be small, clean, and very fast. Now ~1600 loc, unit, spec, benchmarks, mock/stub, plugins, etc. 4
6 Parts of Minitest runner The heart of the machine minitest/unit TDD API minitest/spec BDD API minitest/mock Simple mocking API minitest/pride IO pipelining example minitest/bench Abstract benchmark API 5
2 Parts of Minitest runner The heart of the machine minitest/unit TDD API minitest/spec BDD API minitest/mock Simple mocking API minitest/pride IO pipelining example minitest/bench Abstract benchmark API 6
minitest/test 7
Test Cases are Classes 8
Tests are Methods 9
Test Example require "minitest/autorun" class TestThingy < Minitest::Test def test_do_the_thing assert_equal 42, Thingy.do_the_thing end end 10
Test Example require "minitest/autorun" Simple Subclass class TestThingy < Minitest::Test def test_do_the_thing assert_equal 42, Thingy.do_the_thing end end 10
Test Example require "minitest/autorun" Simple Subclass class TestThingy < Minitest::Test def test_do_the_thing assert_equal 42, Thingy.do_the_thing end end Simple Method 10
Test Example require "minitest/autorun" Simple Subclass class TestThingy < Minitest::Test def test_do_the_thing assert_equal 42, Thingy.do_the_thing end end Simple Method Magic Free! 10
Positive Assertions assert assert_kind_of assert_respond_to assert_empty assert_match assert_same assert_equal assert_nil assert_send* assert_in_delta assert_operator assert_silent*+ assert_in_epsilon+ assert_output*+ assert_throws* assert_includes+ assert_instance_of assert_predicate+ assert_raises* 11 +not in testunit *no negative equiv
Negative Assertions refute+ refute_kind_of+ refute_respond_to+ refute_empty+ refute_match refute_same refute_equal refute_nil refute_send refute_in_delta+ refute_operator+ refute_silent refute_in_epsilon+ refute_output refute_throws refute_includes+ refute_instance_of+ refute_predicate+ refute_raises 12 +not in testunit
Why all these extra assertions? They're more expressive! assert! obj refute obj assert collection.include? obj assert_includes obj, collection out, err = capture_io do do_something end assert_equal "output", out assert_equal "", err assert_output "output", "" do do_something end 13
assert_equal diffs: 1) Failure: test_failing_simple(testsimple) [example.rb:8]: Expected: 42 Actual: 24 2) Failure: test_failing_complex(testcomplex) [example.rb:23]: --- expected +++ actual @@ -22,7 +22,7 @@ "line 22", "line 23", "line 24", - "line 25", + "something unexpected", "line 26", "line 27", "line 28", 14
But... 15
Where is refute_raises? 16
Same place as refute_silent. 17
refute_silent This block of code must print something. What it is, I don't care. How is this assertion of value to anyone? Assert for the specific output you need. 18
refute_silent This block of code must print something. What it is, I don't care. How is this assertion of value to anyone? Assert for the specific output you need. 19
refute_raises This block of code must do something. What it is, I don't care. How is this assertion of value to anyone? Assert for the specific result you need. 20
It's Useful No it isn't. Implies side effects and/or return values have been checked. Or aren't important (always false otherwise, why write the code?). Falsely bumps code coverage metrics. False sense of security. 21
It's More Expressive No it isn't. Writing the test was the act of expression. It is an explicit contract in any test framework that unhandled exceptions are an error. The test's mere existence explicitly states: "there are no unhandled exceptions via these pathways". 22
I've been having this argument for years 23
Some people will never be convinced 24
Stand Back 25
def check_everything assert_something_output do assert_nothing_raised do assert_some_side_effect do assert_some_response do yield end end end end end 26
def check_everything assert_something_output do assert_nothing_raised do assert_some_side_effect do assert_some_response do yield end end end end end 2015 Ryan Davis All Rights Reserved ISO 9001 Enterprise Certified Available for $$$$ 26
27
minitest/spec 28
Testing DSL 29
Test Cases are `describe` blocks 30
Tests are `it` blocks 31
Spec Example require "minitest/autorun" describe Thingy do it "must do the thing" do _(Thingy.do_the_thing).must_equal 42 end end 32
But 33
In Reality 34
`describe` blocks are Classes 35
`it` blocks are Methods 36
Spec Example require "minitest/autorun" describe Thingy do it "must do the thing" do _(Thingy.do_the_thing).must_equal 42 end end 37
Specs Transform: require "minitest/autorun" class TestThingy < Minitest::Test def test_0001_must_do_the_thing _(Thingy.do_the_thing).must_equal 42 end end 38
Specs Transform: require "minitest/autorun" Simple Subclass class TestThingy < Minitest::Test def test_0001_must_do_the_thing _(Thingy.do_the_thing).must_equal 42 end end 38
Specs Transform: require "minitest/autorun" Simple Subclass class TestThingy < Minitest::Test def test_0001_must_do_the_thing _(Thingy.do_the_thing).must_equal 42 end end Simple Method 38
Specs Transform: require "minitest/autorun" Simple Subclass class TestThingy < Minitest::Test def test_0001_must_do_the_thing _(Thingy.do_the_thing).must_equal 42 end end Simple Method Magic Free! 38
Positive Expectations must_be must_be_close_to must_be_empty must_be_instance_of must_be_kind_of must_be_nil must_be_same_as must_be_silent* must_be_within_delta must_be_within_epsilon must_equal must_include must_match must_output* must_raise* must_respond_to must_send* must_throw* 39
Negative Expectations wont_be wont_be_close_to wont_be_empty wont_be_instance_of wont_be_kind_of wont_be_nil wont_be_same_as wont_be_silent wont_be_within_delta wont_be_within_epsilon wont_equal wont_include wont_match wont_output wont_raise wont_respond_to wont_send wont_throw 40
All for Free must_equal is assert_equal wont_equal is refute_equal etc. 41
Advanced Testing 42
Randomization Baked In 43
Preventing Test Order Dependencies 44
parallelize_me! 45
Use gem, not stdlib Randomize Test Order 5 4 Write custom assertions 6 7 Refactor to reusable testcases 8 Benchmark Tests Turn up the test + spec 3 9 Forced Parallelization Disallow meaningless assertions 2 Fast Test Runner 1 0 11 10??? Require Proof of Success? test levels 46
Design Rationale 47
It's Just Ruby 48
Look! Ruby! require "minitest/autorun" class TestThingy < Minitest::Test def test_do_the_thing assert_equal 42, Thingy.do_the_thing end end 49
Less is More 50
assert_in_delta def assert_in_delta e, a, d = 0.001, m = nil n = (e - a).abs msg = message(m) { "... failure message..." } assert delta >= n, msg end 51
assert_in_delta def assert_in_delta e, a, d = 0.001, m = nil n = (e - a).abs msg = message(m) { "... failure message..." } assert delta >= n, msg end message takes a block to defer calculation until an assertion fails 51
assert_in_delta def assert_in_delta e, a, d = 0.001, m = nil n = (e - a).abs msg = message(m) { "... failure message..." } assert delta >= n, msg end message takes a simple assertion is all that is needed block to defer calculation until an assertion fails 51
assert_in_delta def assert_in_delta e, a, d = 0.001, m = nil n = (e - a).abs msg = message(m) { "... failure message..." } assert delta >= n, msg end Only 2 other methods need to be understood: assert (9) & message (6) simple assertion is all that is needed message takes a block to defer calculation until an assertion fails 51
Indirection is the Enemy 52
Just 2 Hops module Minitest::Expectation def must_equal(*args) ctx.assert_equal(*args) end end module Minitest::Assertions def assert_equal exp, act, msg = nil msg = message(msg, E) { diff exp, act } assert exp == act, msg end end 53
No Magic Allowed 54
Thriving Plugin Ecosystem minitest-chef-handler minitest-metadata minitest-reporters minitest-rails-capybara minitest-rails minitest-matchers guard-minitest capybara_minitest_spec minitest-spec-rails minitest-colorize minitest-capybara minitest-rg spork-minitest minitest-ci (& many more) 55
Rails & Minitest 56
The Official Rails Stack uses Minitest 57
Each Release 58
Peels back the testing onion https://www.flickr.com/photos/darwinbell/303874154 59
Encouraging better testing practices 60
Peeling onions make you cry https://www.flickr.com/photos/marleahjoy/13153221935 61
Right? 62
(Hopefully) Not Here 63
Rails 4.0 minitest 4.x 64
Impact? Zero 65
Rails 4.1 minitest 5.x 66
Impact? Zero 67
Rails 4.2 random order 68
Some Impact? 69
Good Thing! 70
Future Rails Should track minitest. 71
As a Rails Dev 72
What does all of this mean? 73
Hopefully... 74
Nothing 75
ActiveSupport ::TestCase 76
Basic Architecture Minitest::Test ActiveSupport::TestCase MyThingyTest 77
Per-test database transactions 78
Fixtures # In fixtures/categories.yml about: name: About # In fixtures/articles.yml one: title: Welcome to Rails! body: Hello world! category: about 79
Declarative Forms setup do end #... teardown do end #... test test name do end #... 80
Extra Assertions assert_difference assert_valid_keys assert_deprecated assert_nothing_raised 81
Wait? What?!? 82
Don't Worry! def assert_nothing_raised(*args) end yield 83
Don't Worry! def assert_nothing_raised(*args) end yield Actual Implementation 83
Unit Testing require 'test_helper' class ArticleTest < ActiveSupport::TestCase test "should not save article without title" do article = Article.new refute article.save end end 84
ActionController ::TestCase 85
Basic Architecture Minitest::Test ActiveSupport::TestCase ActionController::TestCase MyControllerTest 86
Actions get post delete etc 87
State request response session flash 88
Assertions assert_response assert_redirected_to assert_template 89
Functional Testing class ArticlesControllerTest < ActionController::TestCase test "should get index" do get :index assert_response :success assert_not_nil assigns(:articles) end end 90
ActiveDispatch ::IntegrationTest 91
Architecture Minitest::Test ActiveSupport::TestCase ActionDispatch::IntegrationTest MyIntegrationTest 92
Assertions Tons 93
Integration Testing class UserFlowsTest < ActionDispatch::IntegrationTest test "login and browse site" do https! get "/login" assert_response :success david = users :david post_via_redirect "/login", username: david.username, password: david.password assert_equal '/welcome', path assert_equal 'Welcome david!', flash[:notice] https! false get "/articles/all" assert_response :success assert assigns :articles end end 94
http:// guides.rubyonrails.org/ testing.html 95
Very Simple 96
Very Powerful 97
Leverages Minitest 98
Test Randomization 99
Parallelization 100
Enforce Better Testing 101
Troubleshooting 102
I want to use minitest, but I prefer spec-style 103
Simple 104
minitest-rails 105
minitest-spec-rails 106
Lets you do this: describe User do let(:user) { User.create!... } it "does the thing to the stuff" do user.username.must_match(/.../) end end 107
I upgraded to rails 4.2 and now I have failures 108
AKA: you broke all my shit 109
Not as Simple 110
Test-Order Dependency Bug 111
ran: a, b, c = pass ran: b, a, c = fail 112
Easy! 113
But, I have hundreds of tests! 114
Not so Easy 115
minitest-bisect 116
Helps you isolate and debug random test failures 117
118
118
I'm used to RSpec + factory-girl + this + that + kitchen sink + everything 119
A lot of stuff Just Works 120
Look for plugins in readme / gems 121
My Suggestion? 122
Less Complicated Testing 123
Try It 124
You Might Like It 125
Change Takes Time 126
Why use minitest? 127
Why Test? aka It slows me down 128
Not Going to Bother 129
Lost Cause 130
I'd rather help other people 131
Everyone Uses RSpec 132
Obviously Not 133
The Official Rails Stack uses Minitest 134
DHH uses minitest 135
tenderlove uses minitest 136
Jeff Casimir & cohort teach minitest at Turing School 137
nokogiri, haml, god, newrelic_rpm, sqlite3 138
etc 139
Functional Differences with RSpec 140
Unique Features of RSpec Test metadata & metadata filtering. Implicit subject, described_class, etc. Fancier expectations, negation, etc. before(:all) & around(:each). Shared contexts & example groups. Fancier mocking. Fancier reporting. 141
Unique Features of RSpec Test metadata & metadata filtering. Implicit subject, described_class, etc. Fancier expectations, negation, etc. before(:all) & around(:each). Shared contexts & example groups. Fancier mocking. Fancier reporting. 141 Basically, it's Fancier
Unique Features of Minitest Unit & Spec Style Testing. Über-Duper fast and lightweight. Easy to understand whole library. minitest/pride. Benchmark tests. First to randomize parallelize_me! & minitest/hell Clean & easy plugin system. Smallest mock/stub framework. 142
Unique Features of Minitest Unit & Spec Style Testing. Über-Duper fast and lightweight. Easy to understand whole library. minitest/pride. Benchmark tests. First to randomize parallelize_me! & minitest/hell Clean & easy plugin system. Smallest mock/stub framework. Simple, Pragmatic 142
Unique Features of Minitest Unit & Spec Style Testing. Über-Duper fast and lightweight. Easy to understand whole library. minitest/pride. Benchmark tests. First to randomize parallelize_me! & minitest/hell Clean & easy plugin system. Smallest mock/stub framework. Simple, Pragmatic and a bit Snarky 142
Cognitive differences with RSpec 143
Myron Marston 144
Great Comparison 145
I'm one of the RSpec developers, and have never used minitest, so take my biases into account when reading this answer. By and large, RSpec's power comes from the fact that it reifies so many testing concepts into first class objects. Where Test::Unit and Minitest use simple methods for making assertions, RSpec uses first-class matcher objects that support negation, self-description and more. RSpec's examples are first-class objects that support rich metadata; minitest/spec compiles it blocks down into simple methods, which don't support the same sort of rich metadata. RSpec supports specifying shared behaviors using a first-class construct (shared example groups) that accepts arguments; w/ minitest you can use inheritance or a mixin to re-use tests, but it doesn't have the same sort of first-class support. RSpec has an explicit formatter API (and there are many third party formatters that use it); I'm not aware of minitest having the same sort of first-class formatter API. As somebody who is constantly running tests and practicing TDD all day long, I find the power RSpec gives me to be very useful. Many people find it to be overkill, though, and there is an added cognitive cost to the extra abstractions. Here are some specific features RSpec has that I believe minitest lacks: before(:all) hooks (note this is a power user feature of RSpec that should rarely be used; I've only used it on a few occasions in many years of using RSpec) around(:each) hooks Shared example groups Shared contexts Rich metadata support that can be used to control which examples get run, which example groups shared contexts get included in, which example groups modules get mixed into and more. 146 Integrated support for a wide range of mocking features w/ rspec-mocks; Minitest::Mock
2 Answers I'm one of the RSpec developers, and have never used minitest, so take my biases into account when reading this answer. By and large, RSpec's power comes from the fact that it reifies so many testing concepts into first class objects. Where Test::Unit and Minitest use simple methods for making assertions, RSpec uses first-class matcher objects that support negation, self-description and more. RSpec's examples are first-class objects that support rich metadata; minitest/spec compiles it blocks down into simple methods, which don't support the same sort of rich metadata. RSpec supports specifying shared behaviors using a first-class construct (shared example groups) that accepts arguments; w/ minitest you can use inheritance or a mixin to re-use tests, but it doesn't have the same sort of first-class support. RSpec has an explicit formatter API (and there are many third party formatters that use it); I'm not aware of minitest having the same sort of first-class formatter API. As somebody who is constantly running tests and practicing TDD all day long, I find the power RSpec gives me to be very useful. Many people find it to be overkill, though, and there 146
Ruby on Rails on Minitest Apparently, I'm @tenderlove https://farm4.staticflickr.com/3522/3274006022_0c72c24508_o.jpg 147
Ruby on Rails on Minitest Apparently, I'm @tenderlove https://farm4.staticflickr.com/3522/3274006022_0c72c24508_o.jpg 147
TL;DR 148
By and large, RSpec's power comes from the fact that it reifies so many testing concepts into first class objects. Where Test::Unit and Minitest use simple methods for making assertions, RSpec uses first-class matcher objects that support negation, self-description and more. RSpec's examples are firstclass objects that support rich metadata; minitest/spec compiles it blocks down into simple methods, which don't support the same sort of rich metadata. RSpec supports specifying shared behaviors using a first-class construct (shared example groups) that accepts arguments; w/ minitest you can use inheritance or a mixin to re-use tests, but it doesn't have the same sort of firstclass support. http://stackoverflow.com/questions/12470601/minitest-and-rspec 149
Myron thinks this is why RSpec is great 150
I think it is everything wrong with RSpec 151
We're Both Right 152
"Do I contradict myself? Very well, then I contradict myself, I am large, I contain multitudes." Walt Whitman 153
By and large, RSpec's power comes from the fact that it reifies so many testing concepts into first class objects. Where Test::Unit and Minitest use simple methods for making assertions, RSpec uses first-class matcher objects that support negation, self-description and more. RSpec's examples are firstclass objects that support rich metadata; minitest/spec compiles it blocks down into simple methods, which don't support the same sort of rich metadata. RSpec supports specifying shared behaviors using a first-class construct (shared example groups) that accepts arguments; w/ minitest you can use inheritance or a mixin to re-use tests, but it doesn't have the same sort of firstclass support. http://stackoverflow.com/questions/12470601/minitest-and-rspec 154
Minitest RSpec Example Groups Examples Reuse Expectations 155 * my interpretation, not a quote
Minitest RSpec Example Groups compiles describe blocks down into simple classes* reifies testing concepts into first class objects* Examples Reuse Expectations 155 * my interpretation, not a quote
Minitest RSpec Example Groups compiles describe blocks down into simple classes* reifies testing concepts into first class objects* Examples compiles it blocks down into simple methods examples are first-class objects Reuse Expectations 155 * my interpretation, not a quote
Minitest RSpec Example Groups compiles describe blocks down into simple classes* reifies testing concepts into first class objects* Examples compiles it blocks down into simple methods examples are first-class objects Reuse you can use inheritance or a mixin specifying shared behaviors using a first-class construct Expectations 155 * my interpretation, not a quote
Minitest RSpec Example Groups compiles describe blocks down into simple classes* reifies testing concepts into first class objects* Examples compiles it blocks down into simple methods examples are first-class objects Reuse you can use inheritance or a mixin specifying shared behaviors using a first-class construct Expectations use simple methods for making assertions uses first-class matcher objects 155 * my interpretation, not a quote
Minitest RSpec Example Groups compiles describe blocks down into simple methods reifies testing concepts into first class objects Examples compiles it blocks down into simple methods examples are first-class objects Reuse you can use inheritance or a mixin specifying shared behaviors using a first-class construct Expectations use simple methods for making assertions uses first-class matcher objects 156
Minitest RSpec compiles describe blocks Example Groups Class 1st Class Object down into simple methods reifies testing concepts into first class objects Examples compiles it blocks down into simple methods examples are first-class objects Reuse you can use inheritance or a mixin specifying shared behaviors using a first-class construct Expectations use simple methods for making assertions uses first-class matcher objects 156
Minitest RSpec compiles describe blocks Example Groups Class 1st Class Object down into simple methods reifies testing concepts into first class objects compiles it blocks down into Examples Method 1st Class Object simple methods examples are first-class objects Reuse you can use inheritance or a mixin specifying shared behaviors using a first-class construct Expectations use simple methods for making assertions uses first-class matcher objects 156
Minitest RSpec compiles describe blocks Example Groups Class 1st Class Object down into simple methods reifies testing concepts into first class objects compiles it blocks down into Examples Method 1st Class Object simple methods examples are first-class objects you can use inheritance or a Reuse Subclass or Include 1st Class Object mixin specifying shared behaviors using a first-class construct Expectations use simple methods for making assertions uses first-class matcher objects 156
Minitest RSpec compiles describe blocks Example Groups Class 1st Class Object down into simple methods reifies testing concepts into first class objects compiles it blocks down into Examples Method 1st Class Object simple methods examples are first-class objects you can use inheritance or a Reuse Subclass or Include 1st Class Object mixin specifying shared behaviors using a first-class construct use simple methods for Expectations Method Call 1st Class Object making assertions uses first-class matcher objects 156
Ruby on Rails on Minitest 1st Class You keep using that term. I do not think it means what you think it means. 157
A language construct is said to be a FirstClass value in that language when there are no restrictions on how it can be created and used: when the construct can be treated as a value without restrictions. FirstClass features can be stored in variables, passed as arguments to functions, created within functions and returned from functions. In dynamically typed languages, a FirstClass feature can also have its type examined at run-time. http://c2.com/cgi/wiki?firstclass 158
Minitest RSpec Example Groups Class 1st Class Object Examples Method 1st Class Object Reuse Subclass or Include 1st Class Object Expectations Method Call 1st Class Object 159
Minitest RSpec It's Just Ruby Example Groups Class 1st Class Object Examples Method 1st Class Object Reuse Subclass or Include 1st Class Object Expectations Method Call 1st Class Object 159
Minitest RSpec It's Just Ruby Reinvents the Wheel Example Groups Class 1st Class Object Examples Method 1st Class Object Reuse Subclass or Include 1st Class Object Expectations Method Call 1st Class Object 159
Nested Describes describe A do before { :a } it "runs :a" describe B do before { :b } it "runs :a, :b" end end 160
Nested Describes describe A do Inherited "methods" before { :a } it "runs :a" describe B do before { :b } it "runs :a, :b" end end 160
Nested Describes describe A do Inherited "methods" before { :a } it "runs :a" describe B do before { :b } it "runs :a, :b" end end NOT Inherited "methods" 160
Are A & B classes? Is Nesting like Subclassing? 161
Classes? class TestA < RSpec::Spec def before super :a end class TestB < TestA def before super :b end def test_runs_a; end undef_method :test_runs_a end end def test_runs_a_b; end 162
Classes? class TestA < RSpec::Spec def before super :a end class TestB < TestA def before super :b end def test_runs_a; end undef_method :test_runs_a end end def test_runs_a_b; end 162
Are before/after like included modules? 163
Modules? class TestA < RSpec::Spec module BeforeAfter def setup super if respond_to? :super :a end end class TestB < RSpec::Spec module BeforeAfter def setup super if respond_to? :super :b end end include TestA::BeforeAfter include TestA::BeforeAfter include TestB::BeforeAfter end def test_runs_a; end end def test_runs_a_b; end 164
This is basically Another Object Model 165
That's Confusing if you're just learning Ruby/OO 166
Encourages new users to handwave 167
To not know what #describe or #it actually are or do 168
Here's the Magic Incantation to do X 169
Any sufficiently advanced technology is indistinguishable from magic. A.C. Clarke 170
RSpec: It s actually Magic
Many people find it to be overkill, though, and there is an added cognitive cost to the extra abstractions. Myron Marsten, from previous post 172
Indeed 173
*/lib Minitest RSpec Multiplier # Files 14 177 12.64 Flog 2,005.0 13,274.3 6.62 Lines of Code 1,589 15,095 9.50 Lines of Comment 1,063 7,566 7.12 Comment + Code 2,652 22,661 8.54 Comment/Code 0.66 0.50 N/A 174
14000.0 Flog 10500.0 7000.0 3500.0 0.0 Minitest RSpec 175
30,000 Lines of Code Lines of Comment 22,500 15,000 7,500 0 Minitest RSpec 176
177
TEST TEST TEST TEST 177
TEST TEST TEST vs TEST 177
TEST TEST TEST vs TEST 177
Many people find it to be overkill, though, and there is an added cognitive cost to the extra abstractions. Myron Marsten, from previous post 178
Not just cognitive! 179
Performance differences with RSpec 180
All those abstractions? 181
Reinventing the wheel? 182
Has a Real Cost 183
Combined RSpec Results Combined Minitest Results 100.00 pos rs time 1neg rs time 50neg rs time 100neg rs time pos rs memory 1neg rs memory 50neg rs memory 100neg rs memory 300.00 1.80 pos mt time 1neg mt time 50neg mt time 100neg mt time pos mt memory 1neg mt memory 50neg mt memory 100neg mt memory 100.00 75.00 225.00 1.35 75.00 Time (s) 50.00 150.00 Memory (MB) Time (s) 0.90 50.00 Memory (MB) 25.00 75.00 0.45 25.00 0.00 500 1500 2500 3500 4500 5500 6500 7500 8500 9500 0.00 0.00 500 1500 2500 3500 4500 5500 6500 7500 8500 9500 0.00 # tests # tests 184
Combined RSpec Results Combined Minitest Results 100.00 pos rs time 1neg rs time 50neg rs time 100neg rs time pos rs memory 1neg rs memory 50neg rs memory 100neg rs memory 300.00 100.00 pos mt time 1neg mt time 50neg mt time 100neg mt time pos mt memory 1neg mt memory 50neg mt memory 100neg mt memory 300.00 75.00 225.00 75.02 225.00 Time (s) 50.00 150.00 Memory (MB) Time (s) 50.04 150.00 Memory (MB) 25.00 75.00 25.06 75.00 0.00 500 1500 2500 3500 4500 5500 6500 7500 8500 9500 0.00 0.08 500 1500 2500 3500 4500 5500 6500 7500 8500 9500 0.00 # tests # tests 185
But Ryan... 186
Who cares? 187
Passing rspec is fast enough 188
Bug? 189
Bug? Refactor? 189
Bug? Refactor? Anything else goes wrong? 189
You Pay 190
For Completeness: 191
Minitest vs RSpec, time & memory (assertions) 0.60 mt time rs time 0.45 Expectation Time (s) 0.30 0.15 Speed 0.00 1000 6000 11000 16000 21000 26000 31000 1 test, # assertions 36000 41000 46000 50000 192
Minitest vs RSpec, time 9.00 6.75 mt time rs time Method Time (s) 4.50 Execution 2.25 0.00 1000 5000 9000 # tests, 0 assertions 13000 17000 21000 25000 29000 33000 37000 41000 45000 49000 193 Speed
Linear 194
Don't reduce examples or expectations 195
If you want a speed up 196
Switch to minitest 197
Or never, ever refactor. 198
Summary 199
At the end of the day 200
As long as you test 201
I don't care what you use 202
Use the best tool for your job 203
Hopefully, I've shown 204
The technical merits of Minitest 205
Choose what works for you 206
Not because it seems popular 207
Maybe there's fewer articles about MT because there's less need for them? 208
MT is much easier to understand. 209
MT users aren't missing. 210
They're busy Getting Stuff Done. 211
Choose what works for you 212
Who knows? 213
Try It 214
You might like it 215
After All 216
It's Just Ruby 217
Thank You 218
Thank You (hire me) 218