Created
November 3, 2016 23:41
-
-
Save RasPhilCo/1fd3fce25302f759af3cd9ac3ff788fd to your computer and use it in GitHub Desktop.
Sandi Metz's Magic Tricks of Testing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'minitest/autorun' | |
require 'minitest/mock' | |
# From the Queen herself, Sandi Metz | |
# https://www.youtube.com/watch?v=URSWYvyc42M | |
# http://jnoconor.github.io/images/unit-testing-chart-sandi-metz.png | |
class Gear | |
attr_reader :chainring, :cog, :wheel, :observer | |
def initialize chainring: nil, cog: nil, wheel: nil, observer: Obs.new | |
@chainring = chainring | |
@cog = cog | |
@wheel = wheel | |
@observer = observer | |
end | |
# incoming query (w/ sent-to-self & outgoing query) | |
def gear_inches | |
ratio * wheel.diameter | |
end | |
# incoming command (w/ sent-to-self w/ outgoing command) | |
def set_cog new_cog | |
@cog = new_cog | |
changed | |
cog | |
end | |
private | |
def ratio | |
chainring / cog.to_f | |
end | |
def changed | |
observer.changed(chainring, cog) | |
end | |
end | |
class Wheel | |
attr_reader :rim, :tire | |
def initialize rim, tire | |
@rim = rim | |
@tire = tire | |
end | |
# incoming query | |
def diameter | |
rim + (tire * 2) | |
end | |
end | |
class Obs | |
# incoming command | |
def changed _, __ | |
# lots of public side-effects here, like | |
# saving a bunch of data in the db | |
end | |
end | |
class WheelTest < MiniTest::Test | |
# incoming query | |
def test_calculates_diamter | |
wheel = Wheel.new(26, 1.5) | |
assert_in_delta(29, #<< assert result | |
wheel.diameter, | |
0.01) | |
end | |
end | |
class GearTest < MiniTest::Test | |
# incoming query | |
def test_calculates_gear_inches | |
gear = Gear.new( | |
chainring: 52, | |
cog: 11, | |
wheel: Wheel.new(26, 1.5)) | |
assert_in_delta(137.1, #<< assert result | |
gear.gear_inches, | |
0.01) | |
# not expecting or asserting private #ratio | |
# not expecting or asserting Wheel's #diameter | |
end | |
## set_cog tests | |
# incoming command | |
def test_set_cog | |
gear = Gear.new | |
gear.set_cog 27 | |
assert(27, gear.cog) #<< assert direct public side effects | |
end | |
# outgoing command | |
def test_notifies_observers_when_cogs_change | |
observer = MiniTest::Mock.new # mock, for speed | |
gear = Gear.new( | |
chainring: 52, | |
cog: 11, | |
observer: observer) | |
observer.expect(:changed, true, [52,27]) # setup mock's expect | |
gear.set_cog 27 | |
observer.verify #<< expect message got sent | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Run tests with:
$ ruby magic_tricks_of_testing.rb