Unit testing
The path from coffee to confidence
David Faulkenberry
CS 320 Geek Talk
April 24th, 2017
HTTP - Hypertext Transfer Protocol
Did you know?...
HTTP - Hypertext Transfer Protocol

April 1st, 1998 - IETF RFC 2324
Hyper
Text
Coffee
Pot
Control
Protocol
Did you know?...


January 5th, 2016 - Amazon.com
Test-driven development (TDD)
Define an expectation of your system
Minimally satisfy the expectation
Evaluate and introduce new expectations as needed
#spec/models/coffee_pot_spec.rb
describe CoffeePot do
end#spec/models/coffee_pot_spec.rb
describe CoffeePot do
it 'needs coffee grounds and water to be ready'
end#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
it 'needs coffee grounds and water to be ready'
end#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
end
enduninitialized constant CoffeePot (NameError)#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
end
end#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
end
end
#app/models/coffee_pot.rb
class CoffeePot < ActiveRecord::Base
endexpected #<CoffeePot ...> to respond to `ready?`#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
end
end
#app/models/coffee_pot.rb
class CoffeePot < ActiveRecord::Base
end#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
end
end
#app/models/coffee_pot.rb
class CoffeePot < ActiveRecord::Base
def ready?
end
end#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
end
end
#app/models/coffee_pot.rb
class CoffeePot < ActiveRecord::Base
def ready?
has_coffee_grounds? && has_water?
end
endundefined method `has_coffee_grounds?`#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
end
end
#app/models/coffee_pot.rb
class CoffeePot < ActiveRecord::Base
def ready?
has_coffee_grounds? && has_water?
end
end#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
end
end
#app/models/coffee_pot.rb
class CoffeePot < ActiveRecord::Base
def has_coffee_grounds?
end
def ready?
has_coffee_grounds? && has_water?
end
end#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
end
end
#app/models/coffee_pot.rb
class CoffeePot < ActiveRecord::Base
def has_coffee_grounds?
false
end
def ready?
has_coffee_grounds? && has_water?
end
end#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
end
end
#app/models/coffee_pot.rb
class CoffeePot < ActiveRecord::Base
def has_coffee_grounds?
false
end
def has_water?
false
end
def ready?
has_coffee_grounds? && has_water?
end
end
1 example, 0 failures#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
end
end
#app/models/coffee_pot.rb
class CoffeePot < ActiveRecord::Base
def has_coffee_grounds?
false
end
def has_water?
false
end
def ready?
has_coffee_grounds? && has_water?
end
end#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
let(:full_pot) { create :coffee_pot }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
end
end
#app/models/coffee_pot.rb
class CoffeePot < ActiveRecord::Base
def has_coffee_grounds?
false
end
def has_water?
false
end
def ready?
has_coffee_grounds? && has_water?
end
end#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
let(:full_pot) { create :coffee_pot, coffee_grounds: 8.0 }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
end
end
#app/models/coffee_pot.rb
class CoffeePot < ActiveRecord::Base
def has_coffee_grounds?
false
end
def has_water?
false
end
def ready?
has_coffee_grounds? && has_water?
end
end#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
let(:full_pot) { create :coffee_pot, coffee_grounds: 8.0, water: 10.0 }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
end
end
#app/models/coffee_pot.rb
class CoffeePot < ActiveRecord::Base
def has_coffee_grounds?
false
end
def has_water?
false
end
def ready?
has_coffee_grounds? && has_water?
end
end#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
let(:full_pot) { create :coffee_pot, coffee_grounds: 8.0, water: 10.0 }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
expect(full_pot)
end
end
#app/models/coffee_pot.rb
class CoffeePot < ActiveRecord::Base
def has_coffee_grounds?
false
end
def has_water?
false
end
def ready?
has_coffee_grounds? && has_water?
end
end#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
let(:full_pot) { create :coffee_pot, coffee_grounds: 8.0, water: 10.0 }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
expect(full_pot).to be_ready
end
end
#app/models/coffee_pot.rb
class CoffeePot < ActiveRecord::Base
def has_coffee_grounds?
false
end
def has_water?
false
end
def ready?
has_coffee_grounds? && has_water?
end
endexpected `#<CoffeePot ...>.ready?` to return true, got false#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
let(:full_pot) { create :coffee_pot, coffee_grounds: 8.0, water: 10.0 }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
expect(full_pot).to be_ready
end
end
#app/models/coffee_pot.rb
class CoffeePot < ActiveRecord::Base
def has_coffee_grounds?
false
end
def has_water?
false
end
def ready?
has_coffee_grounds? && has_water?
end
end#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
let(:full_pot) { create :coffee_pot, coffee_grounds: 8.0, water: 10.0 }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
expect(full_pot).to be_ready
end
end
#app/models/coffee_pot.rb
class CoffeePot < ActiveRecord::Base
def has_coffee_grounds?
coffee_grounds > 0
end
def has_water?
false
end
def ready?
has_coffee_grounds? && has_water?
end
end#spec/models/coffee_pot_spec.rb
describe CoffeePot do
let(:empty_pot) { create :coffee_pot }
let(:full_pot) { create :coffee_pot, coffee_grounds: 8.0, water: 10.0 }
it 'needs coffee grounds and water to be ready' do
expect(empty_pot).not_to be_ready
expect(full_pot).to be_ready
end
end
#app/models/coffee_pot.rb
class CoffeePot < ActiveRecord::Base
def has_coffee_grounds?
coffee_grounds > 0
end
def has_water?
water > 0
end
def ready?
has_coffee_grounds? && has_water?
end
end
1 example, 0 failuresTest-driven development (TDD)
Define an expectation of your system
Minimally satisfy the expectation
Evaluate and introduce new expectations as needed




https://github.com/umts/jobapps
Travis CI
Continuous
Integration


Travis CI
Continuous
Integration




Simplecov
CodeClimate




CodeClimate
app/models/application_record.rb:88:4: C: Trailing whitespace detected.
end
^app/models/application_record.rb:63:6: C: Inconsistent indentation detected.
all_genders = GENDER_OPTIONS | gender_records.pluck(:gender)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^app/models/application_record.rb:6:25: C: Use the new Ruby 1.9 hash syntax.
delegate :department, :to => :position
^^^^^^app/models/application_record.rb:62:27: C: Use find_each instead of each.
ApplicationRecord.all.each(&:add_data_types)
^^^^Rubocop
Before TDD:
"My code seems to do what I want."
Now:
Before TDD:
"My code seems to do what I want."
Now:
It follows community-accepted Ruby and Rails style conventions.
My tests account for the conditional branches in my code.
All of the tools I used to develop my code are 100% free.
The expected behavior of my code is clearly outlined in my tests.
I can prove that my code does what I want.
Before TDD:
"My code seems to do what I want."
Now:
It follows community-accepted Ruby and Rails style conventions.
My tests account for the conditional branches in my code.
All of the tools I used to develop my code are 100% free.
The expected behavior of my code is clearly outlined in my tests.
I can prove that my code does what I want.
Unit testing, take 2
By David Faulkenberry
Unit testing, take 2
CS 320 Geek Talk, April 24th, 2017
- 1,037