refactoring unit-tests - clean code days · 2016. 7. 6. · refactoring unit-tests @marcoemrich...

91
Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16

Upload: others

Post on 26-Mar-2021

4 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

Refactoring Unit-Tests@MarcoEmrich Juni 2016 #CCD16

Page 2: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

TDDTDDStoneageStoneage

Page 3: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Birth ofBirth ofTTest est DDriven riven DDevelopmentevelopment

??

Page 4: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

https://arialdomartini.wordpress.com/2012/07/20/you-wont-believe-how-old-tdd-is

John von Neuman

Anno Anno 19571957

Page 5: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

https://arialdomartini.wordpress.com/2012/07/20/you-wont-believe-how-old-tdd-is

Kent Beck

Anno Anno 19891989

Page 6: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

TDD???

Anno Anno 20052005

Page 7: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6def test_validate_password @user.password = '' @user.password_confirmation = '' assert [email protected] assert_equal ["is too short (minimum is 5 characters)", "has invalid characters", "can't be blank"], @user.errors.on(:password)

@user.password = 'testest' @user.password_confirmation = 'testtest' assert [email protected] assert_equal "doesn't match confirmation" , @user.errors.on(:password)

@user.password = '' @user.password_confirmation = 'testtest' assert [email protected] assert_equal ["is too short (minimum is 5 characters)", "has invalid characters", "doesn't match confirmation", "can't be blank"], @user.errors.on(:password)

@user.password = 'testtest' @user.password_confirmation = '' assert [email protected] assert_equal "doesn't match confirmation", @user.errors.on(:password)

@user.password = 'test' @user.password_confirmation = 'test' assert [email protected] assert_equal "is too short (minimum is 5 characters)", @user.errors.on(:password)

@user.password = 'testet' @user.password_confirmation = 'testet' assert @user.saveend

webmasters.dewebmasters.de 20052005

Page 8: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6def test_validate_password @user.password = '' @user.password_confirmation = '' assert [email protected] assert_equal ["is too short (minimum is 5 characters)", "has invalid characters", "can't be blank"], @user.errors.on(:password)

@user.password = 'testest' @user.password_confirmation = 'testtest' assert [email protected] assert_equal "doesn't match confirmation" , @user.errors.on(:password)

@user.password = '' @user.password_confirmation = 'testtest' assert [email protected] assert_equal ["is too short (minimum is 5 characters)", "has invalid characters", "doesn't match confirmation", "can't be blank"], @user.errors.on(:password)

@user.password = 'testtest' @user.password_confirmation = '' assert [email protected] assert_equal "doesn't match confirmation", @user.errors.on(:password)

@user.password = 'test' @user.password_confirmation = 'test' assert [email protected] assert_equal "is too short (minimum is 5 characters)", @user.errors.on(:password)

@user.password = 'testet' @user.password_confirmation = 'testet' assert @user.saveend

Embarrass

ing

Page 9: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

There is still hopeThere is still hope......

Page 10: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Test Test RefactoringRefactoring

Page 11: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

ExampleExample

Page 12: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

(CC) https://www.flickr.com/photos/shannxn/14129007573 Shannon O'Toole

Page 13: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

(CC) https://www.flickr.com/photos/rockandrollfreak/16773279381

Page 14: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

ONLINEONLINESeminar-ShopSeminar-Shop

Page 15: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

ONLINEONLINESeminar-ShopSeminar-Shop

Page 16: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Page 17: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

(CC) https://www.flickr.com/photos/shannxn/14129007573 Shannon O'Toole

Page 18: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

SpecsSpecs

Page 19: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

● Seminare haben Name und Nettopreis

Ruby Java

SpecsSpecs

Page 20: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

● Seminare haben Name und Nettopreis

● Seminare berechnen Ihren Bruttopreis - außer, sie sind steuerbefreit

Ruby Java/JS

SpecsSpecs

Page 21: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

MarketingMarketingDepartmentDepartment

Page 22: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

3-Buchstaben Rabatt3-Buchstaben Rabatt

(CC) https://www.flickr.com/photos/hey__paul/5851687664 Hey Paul Studios

Page 23: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

● Seminare haben Name und Nettopreis

● Seminare berechnen Ihren Bruttopreis - außer, sie sind steuerbefreit

● 3-Buchstaben-Seminare* bekommen 5% Rabatt

Ruby Java/JS

SpecsSpecs

Page 24: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class Seminar TAX_RATE = 1.19 THREE_LETTER_DISCOUNT_RATE = 5

attr_writer :net_price, :tax_free, :name

def initialize(name, net_price, tax_free) @name, @net_price, @tax_free = name, net_price, tax_free end

def gross_price net_price * tax_rate end

def net_price @net_price - discount end

def tax_rate @tax_free ? 1 : TAX_RATE / 100 end

def discount @net_price * discount_rate / 100 end

def discount_rate discount_granted? ? THREE_LETTER_DISCOUNT_RATE : 0 end

def discount_granted? @name.size < 3 end

end

Page 25: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class Seminar TAX_RATE = 1.19 THREE_LETTER_DISCOUNT_RATE = 5

attr_writer :net_price, :tax_free, :name

def initialize(name, net_price, tax_free) @name, @net_price, @tax_free = name, net_price, tax_free end

def gross_price net_price * tax_rate end

def net_price @net_price - discount end

def tax_rate @tax_free ? 1 : TAX_RATE / 100 end

def discount @net_price * discount_rate / 100 end

def discount_rate discount_granted? ? THREE_LETTER_DISCOUNT_RATE : 0 end

def discount_granted? @name.size < 3 end

end

Page 26: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Tests?Tests?

Page 27: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class SeminarTest < Test::Unit::TestCase

def test_seminar_should_calculate_correct_gross_prices seminar = Seminar.new('OOP', 500, false) assert_equal 565.25, seminar.gross_price

seminar.net_price = 300 assert_equal 339.15, seminar.gross_price

seminar.tax_free = true assert_equal 285, seminar.gross_price

seminar.name = 'Objekt-Orientierte Programmierung' assert_equal 300, seminar.gross_price end

end

Page 28: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class SeminarTest < Test::Unit::TestCase

def test_seminar_should_calculate_correct_gross_prices seminar = Seminar.new('OOP', 500, false) assert_equal 565.25, seminar.gross_price

seminar.net_price = 300 assert_equal 339.15, seminar.gross_price

seminar.tax_free = true assert_equal 285, seminar.gross_price

seminar.name = 'Objekt-Orientierte Programmierung' assert_equal 300, seminar.gross_price end

end

Failure:<565.25> expected but was<5.95>.

Page 29: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

3 minutes3 minutes

Page 30: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Bug?Bug?

Page 31: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

2 Bugs?2 Bugs?

Page 32: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

alternativealternativetest suittest suit

Page 33: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

9 test cases9 test cases

Page 34: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

2 failing tests2 failing tests

Page 35: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6def test_seminar_should_have_the_german_mwst_tax_rate_if_it_is_not_tax_free seminar = create_seminar(tax_free: false) assert_equal Seminar::TAX_RATE, seminar.tax_rateend

def test_discount_granted_should_return_true_if_name_consists_of_3_letters seminar = create_seminar(name: 'OOP') # 3 Letters assert seminar.discount_granted?end

Failure:<1.19> expected but was<0.0119>.

Failure:<false> is not true.

Page 36: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

3 minutes3 minutes

Page 37: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Bug?Bug?

Page 38: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

2 Bugs?2 Bugs?

Page 39: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

3 Bugs?3 Bugs?

Page 40: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Page 41: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class Seminar TAX_RATE = 1.19 THREE_LETTER_DISCOUNT_RATE = 5

attr_writer :net_price, :tax_free, :name

def initialize(name, net_price, tax_free) @name, @net_price, @tax_free = name, net_price, tax_free end

def gross_price net_price * tax_rate end

def net_price @net_price - discount end

def tax_rate @tax_free ? 1 : TAX_RATE / 100 end

def discount @net_price * discount_rate / 100 end

def discount_rate discount_granted? ? THREE_LETTER_DISCOUNT_RATE : 0 end

def discount_granted? @name.size < 3 end

end

Page 42: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class Seminar TAX_RATE = 1.19 THREE_LETTER_DISCOUNT_RATE = 5

attr_writer :net_price, :tax_free, :name

def initialize(name, net_price, tax_free) @name, @net_price, @tax_free = name, net_price, tax_free end

def gross_price net_price * tax_rate end

def net_price @net_price - discount end

def tax_rate @tax_free ? 1 : TAX_RATE end

def discount @net_price * discount_rate / 100 end

def discount_rate discount_granted? ? THREE_LETTER_DISCOUNT_RATE : 0 end

def discount_granted? @name.size <= 3 end

end

Page 43: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

comparingcomparingtest suitestest suites

Page 44: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Quality CriteriaQuality Criteriaforfor

test casestest cases

Page 45: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

ReadableReadable

(CC) https://www.flickr.com/photos/camera_is_a_mirror_with_memory/6628934195

Page 46: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Living Living Documentation!Documentation!

Page 47: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

TestingTestingthethe

Tests?Tests?

Page 48: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

FastFast

Page 49: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

MaintainableMaintainable

Page 50: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Defect Defect LocalizationLocalization

Page 51: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

IsolationIsolation(CC) https://www.flickr.com/photos/loufi/3500076/

Page 52: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

FocusFocus

(CC) https://www.flickr.com/photos/rogersg/3814863064

Page 53: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

"Jeder Test-Case prüft genau eine interessante Verhaltensweise"

J.B. Rainsberger

Page 54: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Quality CriteriaQuality CriteriaReadable

Fast

Maintainable

Defect Localization

Page 55: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

(CC) http://www.flickr.com/photos/a_ninjamonkey/3565672226/sizes/o/in/photostream/

Conflicts?Conflicts?

Page 56: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Optimaler Kompromiss?

Page 57: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

TDD

Kent Beck

Page 58: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Meet BDD(Dan North oder King Image)

http://dannorth.net/bio/

BDD

Dan North

Page 59: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

TDD/BDD führen zu guten Tests!

Page 60: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

TDD/BDD führen zu guten Tests!

(nicht unbedingtautomatisch)

Page 61: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Verbesserungen möglich!

Page 62: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Legacy Test Suites

Page 63: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

??

Page 64: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

Testcode muss gewartet werdenTestcode muss gewartet werden

Page 65: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Test RefactoringTest RefactoringExampleExample

Page 66: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class SeminarTest < Test::Unit::TestCase

def test_seminar_should_calculate_correct_gross_prices seminar = Seminar.new('OOP', 500, false) assert_equal 565.25, seminar.gross_price

seminar.net_price = 300 assert_equal 339.15, seminar.gross_price

seminar.tax_free = true assert_equal 285, seminar.gross_price

seminar.name = 'Objekt-Orientierte Programmierung' assert_equal 300, seminar.gross_price end

end

Page 67: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class SeminarTest < Test::Unit::TestCase

def test_seminar_should_calculate_correct_gross_prices seminar = Seminar.new('OOP', 500, false) assert_equal 565.25, seminar.gross_price

seminar.net_price = 300 assert_equal 339.15, seminar.gross_price

seminar.tax_free = true assert_equal 285, seminar.gross_price

seminar.name = 'Objekt-Orientierte Programmierung' assert_equal 300, seminar.gross_price end

end

Remove Redudant Tests(gleiche Äquivalenzklasse)

Page 68: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class SeminarTest < Test::Unit::TestCase

def test_seminar_should_calculate_correct_gross_prices seminar = Seminar.new('OOP', 500, false) assert_equal 565.25, seminar.gross_price

seminar.net_price = 300 assert_equal 339.15, seminar.gross_price

seminar.tax_free = true assert_equal 475, seminar.gross_price

seminar.name = 'Objekt-Orientierte Programmierung' assert_equal 500, seminar.gross_price end

end

Remove Redudant Tests

Page 69: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class SeminarTest < Test::Unit::TestCase

def test_seminar_should_calculate_correct_gross_prices seminar = Seminar.new('OOP', 500, false) assert_equal 565.25, seminar.gross_price

seminar.tax_free = true assert_equal 475, seminar.gross_price

seminar.name = 'Objekt-Orientierte Programmierung' assert_equal 500, seminar.gross_price end

end

Page 70: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class SeminarTest < Test::Unit::TestCase

def test_seminar_should_calculate_correct_gross_prices seminar = Seminar.new('Objekt-Orientierte Programmierung', 500, true) assert_equal 500, seminar.gross_price

seminar.name = 'OOP' assert_equal 475, seminar.gross_price

seminar.tax_free = false assert_equal 565.25, seminar.gross_price end

end

Use neutral fixture(Build up!)

Page 71: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class SeminarTest < Test::Unit::TestCase

def test_a_tax_free_seminar_should_return_a_gross_price_without_tax seminar = Seminar.new('Objekt-Orientierte Programmierung', 500, true) assert_equal 500, seminar.gross_price end

def test_a_not_tax_free_seminar_should_return_gross_price_with_correct_tax seminar = Seminar.new('Objekt-Orientierte Programmierung', 500, false) assert_equal 595, seminar.gross_price end

def test_a_3letter_seminar_should_return_a_gross_price_with_discount seminar = Seminar.new('OOP', 500, true) assert_equal 475, seminar.gross_price end

end

Split test methodsFresh fixtureArrange Act Assert: AAA-Pattern

Page 72: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class SeminarTest < Test::Unit::TestCase

def test_a_tax_free_seminar_should_return_a_gross_price_without_tax seminar = Seminar.new('Objekt-Orientierte Programmierung', 500, true) assert_equal 500, seminar.gross_price end

def test_a_not_tax_free_seminar_should_return_gross_price_with_correct_tax seminar = Seminar.new('Objekt-Orientierte Programmierung', 500, false) assert_equal 595, seminar.gross_price end

def test_a_3letter_seminar_should_return_a_gross_price_with_discount seminar = Seminar.new('OOP', 500, true) assert_equal 475, seminar.gross_price end

end

Use test data factories

Page 73: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Test data factories● Ruby-Frameworks

Factory-Girl Machinist

● Java-Frameworks Usurper PojoBuilder

● Patterns Object Mothers Test Data Builders/Factories Example Factories

Page 74: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class SeminarTest < Test::Unit::TestCase

def create_seminar(args = {}) new_args = { :name => 'Object Oriented Programming', :net_price => 500, :tax_free => true }.merge(args)

Seminar.new(new_args[:name], new_args[:net_price], new_args[:tax_free]) end

end

Use factories

Defaults(neutral Fixture)

Page 75: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class SeminarTest < Test::Unit::TestCase def test_a_tax_free_seminar_should_return_a_gross_price_without_tax seminar = Seminar.new('Objekt-Orientierte Programmierung', 500, true) seminar = create_seminar(tax_free: true) assert_equal 500, seminar.gross_price end

def test_a_not_tax_free_seminar_should_return_gross_price_with_correct_tax seminar = Seminar.new('Objekt-Orientierte Programmierung', 500, false) seminar = create_seminar(tax_free: false) assert_equal 595, seminar.gross_price end

def test_a_3letter_seminar_should_return_a_gross_price_with_discount seminar = Seminar.new('OOP', 500, true) seminar = create_seminar(name: 'OOP') assert_equal 475, seminar.gross_price end

end

Use factories

Page 76: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class SeminarTest < Test::Unit::TestCase def test_a_tax_free_seminar_should_return_a_gross_price_without_tax seminar = create_seminar(tax_free: true) assert_equal 500, seminar.gross_price end

def test_a_not_tax_free_seminar_should_return_gross_price_with_correct_tax seminar = create_seminar(tax_free: false) assert_equal 595, seminar.gross_price end

def test_a_3letter_seminar_should_return_a_gross_price_with_discount seminar = create_seminar(name: 'OOP') assert_equal 475, seminar.gross_price end

end

Use factories

Page 77: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class SeminarTest < Test::Unit::TestCase def test_a_tax_free_seminar_should_return_a_gross_price_without_tax seminar = create_seminar(tax_free: true) assert_equal seminar.net_price, seminar.gross_price end

def test_a_not_tax_free_seminar_should_return_gross_price_with_correct_tax seminar = create_seminar(tax_free: false) assert_equal seminar.net_price * Seminar::TAX_RATE, seminar.gross_price end

def test_a_3letter_seminar_should_return_a_gross_price_with_discount seminar = create_seminar(name: 'OOP', net_price: 500) assert_equal 500 * 0.95, seminar.gross_price end

end

Use factories

500

500

Page 78: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class SeminarTest < Test::Unit::TestCase def test_a_tax_free_seminar_should_return_a_gross_price_without_tax seminar = create_seminar(tax_free: true) assert_equal seminar.net_price, seminar.gross_price end

def test_a_not_tax_free_seminar_should_return_gross_price_with_correct_tax seminar = create_seminar(tax_free: false) assert_equal seminar.net_price * Seminar::TAX_RATE, seminar.gross_price end

def test_a_3letter_seminar_should_return_a_gross_price_with_discount seminar = create_seminar(name: 'OOP', net_price: 500) assert_equal 500 * 0.95, seminar.gross_price end

end

add missing test

Page 79: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6class SeminarTest < Test::Unit::TestCase def test_a_tax_free_seminar_should_return_a_gross_price_without_tax seminar = create_seminar(tax_free: true) assert_equal seminar.net_price, seminar.gross_price end

def test_a_not_tax_free_seminar_should_return_gross_price_with_correct_tax seminar = create_seminar(tax_free: false) assert_equal seminar.net_price * Seminar::TAX_RATE, seminar.gross_price end

def test_a_3letter_seminar_should_return_a_gross_price_with_discount seminar = create_seminar(name: 'OOP', net_price: 500) assert_equal 500 * 0.95, seminar.gross_price end

def test_a_more_letters_seminar_should_return_a_net_price_without_discount seminar = create_seminar(name: 'Object O. Programming', net_price: 500) assert_equal 500, seminar.gross_price end

end

add missing test

Page 80: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

def test_a_3letter_seminar_should_return_a_gross_price_with_discount seminar = create_seminar(name: 'OOP') assert_equal 500 * 0.95, seminar.gross_price end

def test_a_more_letters_seminar_should_return_a_net_price_without_discount seminar = create_seminar(name: 'Object Oriented Programming') assert_equal 500, seminar.gross_price end

Isolate

class Seminar def gross_price net_price * tax_rate end

def net_price @net_price - discount end

def discount @net_price * discount_rate / 100 endend

Discount

Page 81: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

def test_a_3letter_seminar_should_return_a_gross_price_with_discount seminar = create_seminar(name: 'OOP') assert_equal 500 * 0.95, seminar.net_price .gross_price end

def test_a_more_letters_seminar_should_return_a_net_price_without_discount seminar = create_seminar(name: 'Object Oriented Programming') assert_equal 500, seminar.net_price .gross_price end

Isolate

class Seminar def gross_price net_price * tax_rate end

def net_price @net_price - discount end

def discount @net_price * discount_rate / 100 endend

Discount

Page 82: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

def test_a_tax_free_seminar_should_return_a_gross_price_without_tax seminar = create_seminar(tax_free: true) assert_equal seminar.net_price, seminar.gross_price end

def test_a_not_tax_free_seminar_should_return_gross_price_with_correct_tax seminar = create_seminar(tax_free: false) assert_equal seminar.net_price * Seminar::TAX_RATE, seminar.gross_price end

Isolate

class Seminar def gross_price net_price * tax_rate end

def tax_rate @tax_free ? 1 : TAX_RATE / 100 endend

Tax

Page 83: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

def test_a_tax_free_seminar_should_have_a_tax_rate_of_1 seminar = create_seminar(tax_free: true) assert_equal seminar.net_price, seminar.gross_price assert_equal 1, seminar.tax_rate end

def test_a_not_tax_free_seminar_should_have_the_correct_tax_rate seminar = create_seminar(tax_free: false) assert_equal seminar.net_price * Seminar::TAX_RATE, seminar.gross_price assert_equal Seminar::TAX_RATE, seminar.tax_rate end

Isolate

class Seminar def gross_price net_price * tax_rate end

def tax_rate @tax_free ? 1 : TAX_RATE / 100 endend

Tax

Page 84: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

def test_a_tax_free_seminar_should_have_a_tax_rate_of_1 seminar = create_seminar(tax_free: true) assert_equal 1, seminar.tax_rate end

def test_a_not_tax_free_seminar_should_have_the_correct_tax_rate seminar = create_seminar(tax_free: false) assert_equal Seminar::TAX_RATE, seminar.tax_rate end

Isolate

class Seminar def gross_price net_price * tax_rate end

def tax_rate @tax_free ? 1 : TAX_RATE / 100 endend

Tax

Page 85: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

def test_a_tax_free_seminar_should_have_a_tax_rate_of_1 seminar = create_seminar(tax_free: true) assert_equal 1, seminar.tax_rate end

def test_a_not_tax_free_seminar_should_have_the_correct_tax_rate seminar = create_seminar(tax_free: false) assert_equal Seminar::TAX_RATE, seminar.tax_rate end

Lost Coverage

class Seminar def gross_price net_price * tax_rate end

def tax_rate @tax_free ? 1 : TAX_RATE / 100 endend

Tax

Page 86: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

def test_a_tax_free_seminar_should_have_a_tax_rate_of_1 seminar = create_seminar(tax_free: true) assert_equal 1, seminar.tax_rate end

def test_a_not_tax_free_seminar_should_have_the_correct_tax_rate seminar = create_seminar(tax_free: false) assert_equal Seminar::TAX_RATE, seminar.tax_rate end

def test_seminar_should_use_tax_rate_to_calculate_gross_price

endclass Seminar def gross_price net_price * tax_rate end

def tax_rate @tax_free ? 1 : TAX_RATE / 100 end def net_price @net_price - discount end

Tax

Lost Coverage

Page 87: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

def test_a_tax_free_seminar_should_have_a_tax_rate_of_1 seminar = create_seminar(tax_free: true) assert_equal 1, seminar.tax_rate end

def test_a_not_tax_free_seminar_should_have_the_correct_tax_rate seminar = create_seminar(tax_free: false) assert_equal Seminar::TAX_RATE, seminar.tax_rate end

def test_seminar_should_use_tax_rate_to_calculate_gross_priceseminar = create_seminar(tax_free: false)

assert_equal ?, seminar.gross_price end

class Seminar def gross_price net_price * tax_rate end

def tax_rate @tax_free ? 1 : TAX_RATE / 100 end def net_price @net_price - discount end

Tax

IsolateUse Stubs

Page 88: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

def test_a_tax_free_seminar_should_have_a_tax_rate_of_1 seminar = create_seminar(tax_free: true) assert_equal 1, seminar.tax_rate end

def test_a_not_tax_free_seminar_should_have_the_correct_tax_rate seminar = create_seminar(tax_free: false) assert_equal Seminar::TAX_RATE, seminar.tax_rate end

def test_seminar_should_use_tax_rate_to_calculate_gross_price seminar = create_seminar(tax_free: false) seminar.stubs(net_price: 100) seminar.stubs(tax_rate: 1.5) assert_equal 150, seminar.gross_price end

IsolateUse Stubs

class Seminar def gross_price net_price * tax_rate end

def tax_rate @tax_free ? 1 : TAX_RATE / 100 end def net_price @net_price - discount end

Tax

Page 89: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Mocks & Stubs● Ruby

Rspec-Mocks Mocha FlexMock

● Java Mockito EasyMock Jmockit

● JavaScript SinonJS Jasmine Spies

Page 90: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

Page 91: Refactoring Unit-Tests - Clean Code Days · 2016. 7. 6. · Refactoring Unit-Tests @MarcoEmrich Juni 2016 #CCD16 @ m a r c o e m r i c h # C C D 1 6 TDD Stoneage @ m a r c o e m r

@m

ar co

em

rich #

CC

D1

6

@marcoemrich

https://github.com/marcoemrich