Skip to content

Instantly share code, notes, and snippets.

@RasPhilCo
Created November 3, 2016 23:41
Show Gist options
  • Save RasPhilCo/1fd3fce25302f759af3cd9ac3ff788fd to your computer and use it in GitHub Desktop.
Save RasPhilCo/1fd3fce25302f759af3cd9ac3ff788fd to your computer and use it in GitHub Desktop.
Sandi Metz's Magic Tricks of Testing
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
@RasPhilCo
Copy link
Author

Run tests with:
$ ruby magic_tricks_of_testing.rb

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment