RSpec.describe 'Max.of' do
it { expect(Max.of(1)).to eq 1 }
end
Slide 35
Slide 35 text
RSpec.describe 'Max.of' do
it { expect(Max.of(1)).to eq 1 } ✘
end
module Max
def self.of(*numbers)
end
end
Slide 36
Slide 36 text
RSpec.describe 'Max.of' do
it { expect(Max.of(1)).to eq 1 } ✔
end
module Max
def self.of(*numbers)
1
end
end
Slide 37
Slide 37 text
RSpec.describe 'Max.of' do
it { expect(Max.of(1)).to eq 1 } ✔
it { expect(Max.of(2)).to eq 2 } ✘
end
module Max
def self.of(*numbers)
1
end
end
Slide 38
Slide 38 text
RSpec.describe 'Max.of' do
it { expect(Max.of(1)).to eq 1 } ✔
it { expect(Max.of(2)).to eq 2 } ✔
end
module Max
def self.of(*numbers)
numbers.first
end
end
Slide 39
Slide 39 text
RSpec.describe 'Max.of' do
it { expect(Max.of(1)).to eq 1 } ✔
it { expect(Max.of(2)).to eq 2 } ✔
it { expect(Max.of(4,5)).to eq 5 } ✘
end
module Max
def self.of(*numbers)
numbers.first
end
end
Slide 40
Slide 40 text
RSpec.describe 'Max.of' do
it { expect(Max.of(1)).to eq 1 } ✔
it { expect(Max.of(2)).to eq 2 } ✔
it { expect(Max.of(4,5)).to eq 5 } ✔
end
module Max
def self.of(*numbers)
current_max = numbers.first
numbers.each do |num|
if num > current_max
current_max = num
end
end
current_max
end
end
Slide 41
Slide 41 text
LET'S CHECK
COVERAGE
Slide 42
Slide 42 text
No content
Slide 43
Slide 43 text
NOW LET'S RUN
MUTANT
Slide 44
Slide 44 text
RSpec.describe 'Max.of' do
it { expect(Max.of(1)).to eq 1 } ✔
it { expect(Max.of(2)).to eq 2 } ✔
it { expect(Max.of(4,5)).to eq 5 } ✔
end
module Max
def self.of(*numbers)
current_max = numbers.first
numbers.each do |num|
if num > current_max
current_max = num
end
end
current_max
end
end
Slide 45
Slide 45 text
RSpec.describe 'Max.of' do
it { expect(Max.of(1)).to eq 1 } ✔
it { expect(Max.of(2)).to eq 2 } ✔
it { expect(Max.of(4,5)).to eq 5 } ✔
end
module Max
def self.of(*numbers)
current_max = numbers.first
numbers.each do |num|
if true
current_max = num
end
end
current_max
end
end
Mutation
Slide 46
Slide 46 text
RSpec.describe 'Max.of' do
it { expect(Max.of(1)).to eq 1 } ✔
it { expect(Max.of(2)).to eq 2 } ✔
it { expect(Max.of(4,5)).to eq 5 } ✔
end
module Max
def self.of(*numbers)
numbers.last
end
end
Slide 47
Slide 47 text
RSpec.describe 'Max.of' do
it { expect(Max.of(1)).to eq 1 } ✔
it { expect(Max.of(2)).to eq 2 } ✔
it { expect(Max.of(4,5)).to eq 5 } ✔
it { expect(Max.of(7,6)).to eq 7 } ✘
end
module Max
def self.of(*numbers)
numbers.last
end
end
Slide 48
Slide 48 text
RSpec.describe 'Max.of' do
it { expect(Max.of(1)).to eq 1 } ✔
it { expect(Max.of(2)).to eq 2 } ✔
it { expect(Max.of(4,5)).to eq 5 } ✔
it { expect(Max.of(7,6)).to eq 7 } ✔
end
module Max
def self.of(*numbers)
current_max = numbers.first
numbers.each do |num|
if num > current_max
current_max = num
end
end
current_max
end
end
TEST SELECTION
> mutant --include lib \
--require virtus \
--use rspec \
Virtus::Attribute#type
Longest RSpec example group descriptions’ prefix match
Slide 60
Slide 60 text
EQUIVALENT MUTATIONS
i = 10
while i != 0
do_something
i -= 1
end
i = 10
while i > 0
do_something
i -= 1
end
Slide 61
Slide 61 text
INFINITE RUNTIME
while expression
do_something
end
while true
do_something
end
Slide 62
Slide 62 text
USE TIMEOUTS
config.around(:each) do |example|
Timeout.timeout(5, &example)
end
Slide 63
Slide 63 text
DISADVANTAGES
• Can slow down your TDD rhythm
• May be very noisy
• Doesn't work with meta-programming
Slide 64
Slide 64 text
ADVANTAGES
• Influences code style
• Helps spot dead features
• Puts emphasis on minimal code to pass the test
• Encourages to write isolated unit tests
Slide 65
Slide 65 text
USAGE SCENARIOS
• Just run sometimes
• Continuous integration
• TDD with mutation testing only on new changes
• Add mutation testing to your legacy project, but do
not fail a build - produce warning report
Slide 66
Slide 66 text
SUMMARY
Code coverage highlights code that is not tested.
It shows which code you have executed in tests.
Slide 67
Slide 67 text
SUMMARY
Mutation testing highlights code that is tested.
It shows which code you have asserted in tests.