test driven development - the right way

64
Test driven development The right way Paweł Głasek @PawelGlasek

Upload: pawel-glasek

Post on 27-Jun-2015

181 views

Category:

Software


3 download

DESCRIPTION

I've encountered many people having misunderstood Test Driven Development. I'm going to present TDD and the main prinicples standing behind as it was described by it's originator Kent Beck in his book "Test driven development by example".

TRANSCRIPT

Page 1: Test driven development - the right way

Test driven development

The right way

Paweł Głasek

@PawelGlasek

Page 2: Test driven development - the right way
Page 3: Test driven development - the right way
Page 4: Test driven development - the right way

The right way?

Page 5: Test driven development - the right way

Czym TDD nie jest

Napisaniem testów wszystkich obiektów, przed implementacją funkcjonalności.

Page 6: Test driven development - the right way

Czym TDD nie jest

Wszystkie testy przed implementacją

● Ciężko zaprojektować odpowiedni design oraz zmieniać go w trakcie kodowania

● Ciężko przewidzieć zmiany w obiektach klas już obecnych w systemie

● Ciężko przewidzieć współdziałanie komponentów

● Niektóre warunki brzegowe nigdy nie występują – zbyt duża ilość niepotrzebnych testów

● Często niepełne pokrycie

Page 7: Test driven development - the right way

Czym TDD nie jest

Sztuką pisania unit testów

Page 8: Test driven development - the right way

Czym TDD nie jest

Just Unit tests

● Błyskawicznie prowadzi do „przemockowania”

● Nie testuje współdziałania poszczególnych obiektów

● Pomimo zmian w powiązanych, ale zmockowanych klasach testy przechodzą

● Niektóre warunki brzegowe nigdy nie występują – zbyt duża ilość niepotrzebnych testów

● Brak motywacji do pisania testów

Page 9: Test driven development - the right way

Czym TDD nie jest

Napisaniem testów po zakończeniu pisania kodu produkcyjnego.

Page 10: Test driven development - the right way

Czym TDD nie jest

Testy po napisaniu kodu produkcyjnego

● Brak motywacji do pisania testów po fakcie

● Wiele przypadków pozostaje nieprzetestowanych

● Niektóre warunki brzegowe nigdy nie występują

● Brak poczucia sensu pisania testów w ten sposób

● Częste problemy z testowalnością napisanego kodu

● Nuda

Page 11: Test driven development - the right way

The right way

Page 12: Test driven development - the right way

TDD

Agile'owa technika wytwarzania programowania

Page 13: Test driven development - the right way

Kent Beck

Page 14: Test driven development - the right way

Test Driven Development By Example

Page 15: Test driven development - the right way
Page 16: Test driven development - the right way

Red – green – refactor

Zasady wujka Boba:

1. Nie wolno pisać kodu produkcyjnego, dopóki nie istnieje failujący test.

2. Nie wolno napisać więcej testów, niż jest to niezbędne do faila (niekompilujący się kod również uznajemy jako fail).

3. Nie wolno pisać więcej kodu produkcyjnego niż jest to niezbędne, by testy przechodziły.

Page 17: Test driven development - the right way

Po wiedz mi, a za pomnę. Po każ mi, a za pamiętam.

Page 18: Test driven development - the right way

Rozkład liczby na czynniki pierwsze

Page 19: Test driven development - the right way

TDD style

Page 20: Test driven development - the right way

Prime factorization – TDD style

class TestPrimeFactors(unittest.TestCase):

"""

Prime factors test suite.

"""

def test_prime_factors(self):

self.assertListEqual([], prime_factors(1))

Page 21: Test driven development - the right way

Prime factorization – TDD style

>> nose2 test.prime_factors

==================================================

ERROR: test_prime_factors (test.prime_factors.TestPrimeFactors)

----------------------------------------------------------------------

NameError: global name 'prime_factors' is not defined

----------------------------------------------------------------------

Ran 1 test in 0.000s

FAILED (errors=1)

Page 22: Test driven development - the right way

Prime factorization – TDD style

def prime_factors(number):

"""

Performs prime factorization.

:param number: Number to be factorized.

:type number: int

:rtype: list

"""

return []

Page 23: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

.

----------------------------------------------------------------------

Ran 1 test in 0.001s

OK

Page 24: Test driven development - the right way

Prime factorization – TDD style

class TestPrimeFactors(unittest.TestCase):

"""

Prime factors test suite.

"""

def test_prime_factors(self):

self.assertListEqual([], prime_factors(1))

self.assertListEqual([2], prime_factors(2))

Page 25: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

F

================================================

FAIL: test_prime_factors (test.prime_factors.TestPrimeFactors)

----------------------------------------------------------------------

AssertionError: Lists differ: [2] != []

----------------------------------------------------------------------

Ran 1 test in 0.001s

FAILED (failures=1)

Page 26: Test driven development - the right way

Prime factorization – TDD style

def prime_factors(number):

return []

def prime_factors(number):

factors = []

if number > 1:

factors.append(2)

return factors

Page 27: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

.

----------------------------------------------------------------------

Ran 1 test in 0.001s

OK

Page 28: Test driven development - the right way

Prime factorization – TDD style

class TestPrimeFactors(unittest.TestCase):

"""

Prime factors test suite.

"""

def test_prime_factors(self):

self.assertListEqual([], prime_factors(1))

self.assertListEqual([2], prime_factors(2))

self.assertListEqual([3], prime_factors(3))

Page 29: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

F

================================================

FAIL: test_prime_factors (test.prime_factors.TestPrimeFactors)

----------------------------------------------------------------------

AssertionError: Lists differ: [3] != [2]

----------------------------------------------------------------------

Ran 1 test in 0.001s

FAILED (failures=1)

Page 30: Test driven development - the right way

Prime factorization – TDD style

def prime_factors(number):

factors = []

if number > 1:

factors.append(2)

return factors

def prime_factors(number):

factors = []

if number > 1:

factors.append(number)

return factors

Page 31: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

.

----------------------------------------------------------------------

Ran 1 test in 0.001s

OK

Page 32: Test driven development - the right way

Prime factorization – TDD style

class TestPrimeFactors(unittest.TestCase):

"""

Prime factors test suite.

"""

def test_prime_factors(self):

self.assertListEqual([], prime_factors(1))

self.assertListEqual([2], prime_factors(2))

self.assertListEqual([3], prime_factors(3))

self.assertListEqual([2, 2], prime_factors(4))

Page 33: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

F

================================================

FAIL: test_prime_factors (test.prime_factors.TestPrimeFactors)

----------------------------------------------------------------------

AssertionError: Lists differ: [2, 2] != [4]

----------------------------------------------------------------------

Ran 1 test in 0.001s

FAILED (failures=1)

Page 34: Test driven development - the right way

Prime factorization – TDD style

def prime_factors(number):

factors = []

if number > 1:

factors.append(number)

return factors

def prime_factors(number):

factors = []

if number > 1:

if number % 2 == 0:

factors.append(2)

number /= 2

factors.append(number)

return factors

Page 35: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

F

================================================

FAIL: test_prime_factors (test.prime_factors.TestPrimeFactors)

----------------------------------------------------------------------

AssertionError: Lists differ: [2] != [2, 1]

----------------------------------------------------------------------

Ran 1 test in 0.001s

FAILED (failures=1)

Page 36: Test driven development - the right way

Prime factorization – TDD style

def prime_factors(number):

factors = []

if number > 1:

if number % 2 == 0:

factors.append(2)

number /= 2

factors.append(number)

return factors

def prime_factors(number):

factors = []

if number > 1:

if number % 2 == 0:

factors.append(2)

number /= 2

if number > 1:

factors.append(number)

return factors

Page 37: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

.

----------------------------------------------------------------------

Ran 1 test in 0.001s

OK

Page 38: Test driven development - the right way

Prime factorization – TDD style

def prime_factors(number):

factors = []

if number > 1:

if number % 2 == 0:

factors.append(2)

number /= 2

if number > 1:

factors.append(number)

return factors

def prime_factors(number):

factors = []

if number > 1:

if number % 2 == 0:

factors.append(2)

number /= 2

if number > 1:

factors.append(number)

return factors

Page 39: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

.

----------------------------------------------------------------------

Ran 1 test in 0.001s

OK

Page 40: Test driven development - the right way

Prime factorization – TDD style

class TestPrimeFactors(unittest.TestCase):

"""

Prime factors test suite.

"""

def test_prime_factors(self):

self.assertListEqual([], prime_factors(1))

self.assertListEqual([2], prime_factors(2))

self.assertListEqual([3], prime_factors(3))

self.assertListEqual([2, 2], prime_factors(4))

self.assertListEqual([5], prime_factors(5))

Page 41: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

.

----------------------------------------------------------------------

Ran 1 test in 0.001s

OK

Page 42: Test driven development - the right way

Prime factorization – TDD style

class TestPrimeFactors(unittest.TestCase):

"""

Prime factors test suite.

"""

def test_prime_factors(self):

self.assertListEqual([], prime_factors(1))

self.assertListEqual([2], prime_factors(2))

self.assertListEqual([3], prime_factors(3))

self.assertListEqual([2, 2], prime_factors(4))

self.assertListEqual([5], prime_factors(5))

self.assertListEqual([2, 3], prime_factors(6))

Page 43: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

.

----------------------------------------------------------------------

Ran 1 test in 0.001s

OK

Page 44: Test driven development - the right way

Prime factorization – TDD style

class TestPrimeFactors(unittest.TestCase):

"""

Prime factors test suite.

"""

def test_prime_factors(self):

self.assertListEqual([], prime_factors(1))

self.assertListEqual([2], prime_factors(2))

self.assertListEqual([3], prime_factors(3))

self.assertListEqual([2, 2], prime_factors(4))

self.assertListEqual([5], prime_factors(5))

self.assertListEqual([2, 3], prime_factors(6))

self.assertListEqual([7], prime_factors(7))

Page 45: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

.

----------------------------------------------------------------------

Ran 1 test in 0.001s

OK

Page 46: Test driven development - the right way

Prime factorization – TDD style

class TestPrimeFactors(unittest.TestCase):

"""

Prime factors test suite.

"""

def test_prime_factors(self):

self.assertListEqual([], prime_factors(1))

self.assertListEqual([2], prime_factors(2))

self.assertListEqual([3], prime_factors(3))

self.assertListEqual([2, 2], prime_factors(4))

self.assertListEqual([5], prime_factors(5))

self.assertListEqual([2, 3], prime_factors(6))

self.assertListEqual([7], prime_factors(7))

self.assertListEqual([2, 2, 2], prime_factors(8))

Page 47: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

F

================================================

FAIL: test_prime_factors (test.prime_factors.TestPrimeFactors)

----------------------------------------------------------------------

AssertionError: Lists differ: [2, 2, 2] != [2, 4]

----------------------------------------------------------------------

Ran 1 test in 0.001s

FAILED (failures=1)

Page 48: Test driven development - the right way

Prime factorization – TDD style

def prime_factors(number):

factors = []

if number > 1:

if number % 2 == 0:

factors.append(2)

number /= 2

if number > 1:

factors.append(number)

return factors

def prime_factors(number):

factors = []

if number > 1:

while number % 2 == 0:

factors.append(2)

number /= 2

if number > 1:

factors.append(number)

return factors

Page 49: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

.

----------------------------------------------------------------------

Ran 1 test in 0.001s

OK

Page 50: Test driven development - the right way

Prime factorization – TDD style

class TestPrimeFactors(unittest.TestCase):

def test_prime_factors(self):

self.assertListEqual([], prime_factors(1))

self.assertListEqual([2], prime_factors(2))

self.assertListEqual([3], prime_factors(3))

self.assertListEqual([2, 2], prime_factors(4))

self.assertListEqual([5], prime_factors(5))

self.assertListEqual([2, 3], prime_factors(6))

self.assertListEqual([7], prime_factors(7))

self.assertListEqual([2, 2, 2], prime_factors(8))

self.assertListEqual([3, 3], prime_factors(9))

Page 51: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

F

================================================

FAIL: test_prime_factors (test.prime_factors.TestPrimeFactors)

----------------------------------------------------------------------

AssertionError: Lists differ: [3, 3] != [9]

----------------------------------------------------------------------

Ran 1 test in 0.001s

FAILED (failures=1)

Page 52: Test driven development - the right way

Prime factorization – TDD style

def prime_factors(number):

factors = []

if number > 1:

while number % 2 == 0:

factors.append(2)

number /= 2

if number > 1:

factors.append(number)

return factors

def prime_factors(number):

factors = []

if number > 1:

while number % 2 == 0:

factors.append(2)

number /= 2

while number % 3 == 0:

factors.append(3)

number /= 3

if number > 1:

factors.append(number)

return factors

Page 53: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

.

----------------------------------------------------------------------

Ran 1 test in 0.001s

OK

Page 54: Test driven development - the right way

Prime factorization – TDD style

def prime_factors(number):

factors = []

if number > 1:

while number % 2 == 0:

factors.append(2)

number /= 2

while number % 3 == 0:

factors.append(3)

number /= 3

if number > 1:

factors.append(number)

return factors

def prime_factors(number):

factors = []

divisor = 2

while number > 1:

while number % divisor == 0:

factors.append(divisor)

number /= divisor

divisor += 1

if number > 1:

factors.append(number)

return factors

Page 55: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

.

----------------------------------------------------------------------

Ran 1 test in 0.001s

OK

Page 56: Test driven development - the right way

Prime factorization – TDD style

def prime_factors(number):

factors = []

divisor = 2

while number > 1:

while number % divisor == 0:

factors.append(divisor)

number /= divisor

divisor += 1

if number > 1:

factors.append(number)

return factors

def prime_factors(number):

factors = []

divisor = 2

while number > 1:

while number % divisor == 0:

factors.append(divisor)

number /= divisor

divisor += 1

return factors

Page 57: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

.

----------------------------------------------------------------------

Ran 1 test in 0.001s

OK

Page 58: Test driven development - the right way

Prime factorization – TDD style

class TestPrimeFactors(unittest.TestCase):

"""

Prime factors test suite.

"""

def test_prime_factors(self):

self.assertListEqual([], prime_factors(1))

self.assertListEqual([2], prime_factors(2))

self.assertListEqual([3], prime_factors(3))

self.assertListEqual([2, 2], prime_factors(4))

self.assertListEqual([5], prime_factors(5))

self.assertListEqual([2, 3], prime_factors(6))

self.assertListEqual([7], prime_factors(7))

self.assertListEqual([2, 2, 2], prime_factors(8))

self.assertListEqual([3, 3], prime_factors(9))

self.assertListEqual([2, 2, 3, 3, 5, 7 , 11, 13], prime_factors(2*2*3*3*5*7*11*13))

Page 59: Test driven development - the right way

Prime factorization – TDD style

>>nose2 test.prime_factors

.

----------------------------------------------------------------------

Ran 1 test in 0.001s

OK

Page 60: Test driven development - the right way

Clean code that works

Page 61: Test driven development - the right way

Zalety TDD

● Prostota iteracji designu● Pokrycie testami● Możliwość refactoringu● Zdecouplowany, testowalny kod● Nietrywialny design● Ograniczenie wykorzystania debugera● Brak strachu przez zmianami w kodzie

Page 62: Test driven development - the right way

Problemy z TDD

● Konieczność zmiany stylu myślenia● Początkowo mało intuicyjna technika● Pokusa pisania kodu produkcyjnego bez testów

Page 63: Test driven development - the right way

Pytania

Page 64: Test driven development - the right way

Dziękuję