Testing Your Code
Robert Mosolgo
The Goal
🚦
📈
📖
🐛🔨
💰
Anatomy of a Unit Test
- Fixture
- Test Case
- Assertion
- (Test Suite)
Anatomy of a Unit Test
# in addition.rb
class Addition
def initialize(inputs: )
@inputs = inputs
end
def value
sum = 0
@inputs.each { |input| sum += input }
sum
end
end
# in addition_test.rb
class AdditionTest < Minitest::Test
def setup
@numbers = [1, 2, 3]
end
def test_result_equals_the_sum
addition = Addition.new(input: @numbers)
value = addition.value
assert(value == 6)
end
end
Test case
Fixtures
Assertion
MMaaS
Double Duty
Mirror, Mirror
Single Responsibility?
class BadExpression
def initialize(operation_name, inputs)
@operation_name = operation_name
@inputs = inputs
end
def value
method_name = "calculate_"+ @operation_name
send(method_name)
end
private
def calculate_largest_even
@inputs
.select {|i| i % 2 == 0}
.max
end
def calculate_double
calculate_addition * 2
end
def calculate_addition
@inputs.reduce(&:+)
end
end
class BadExpressionTest < Minitest::Test
def setup
@inputs = [2,3,4]
end
def test_it_does_addition
# ...
end
def test_it_does_multiplication
# ...
end
def test_it_does_double
# ...
end
def test_it_does_largest_even
# ...
end
end
Interface vs Implementation
# Return the largest multiple of 2
# from the inputs
class LargestEven
EVEN_NUMBERS = [
2, 4, 6, 8, 10,
12, 14, 16, 18, 20,
]
def initialize(inputs: )
@inputs = inputs
end
def value
evens = @inputs & EVEN_NUMBERS
evens.max
end
private_constant :EVEN_NUMBERS
end
class LargestEvenTest < Minitest::Test
def setup
@numbers = [2, 3, 4, 5]
end
def test_result_equals_the_sum
addition = LargestEven.new(
inputs: @numbers
)
value = addition.value
assert_equal(4, value)
end
end
# Return the largest multiple of 2
# from the inputs
class LargestEven
def initialize(inputs: )
@inputs = inputs
end
def value
evens = @inputs.select { |i| i.even? }
evens.max
end
end
class LargestEvenTest < Minitest::Test
def setup
@numbers = [2, 3, 4, 5]
@large_numbers = [
100, 505, 600, 437
]
end
def test_result_equals_the_sum
addition = LargestEven.new(
inputs: @numbers
)
value = addition.value
assert_equal(5, value)
end
def test_result_may_be_very_large
addition = LargestEven.new(
inputs: @large_numbers
)
value = addition.value
assert_equal(600, value)
end
end
Tests are Docs
👶💭 🔜
💁 🔜
👴❓
👬👫
Easy Tests 🍻 Good Code
Short, fast, readable tests 😊
Small units of work 🔨
Insulated behaviors 🔐
Comprehensive tests 🚦
Living documentation 📖
Confident changes 📈
Further Reading
Kent Beck, "RIP, Test-Driven Development"
Test Framework of Your Choice
Testing Your Code
By Robert Mosolgo
Testing Your Code
Test your code with more code! 🎉 (Full Stack North County, October 8, 2015)
- 1,451