Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Test Driven Development - The Right Way

guasek
April 11, 2014

Test Driven Development - The Right Way

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".

guasek

April 11, 2014
Tweet

Other Decks in Programming

Transcript

  1. 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
  2. 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
  3. 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
  4. 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.
  5. Prime factorization – TDD style class TestPrimeFactors(unittest.TestCase): """ Prime factors

    test suite. """ def test_prime_factors(self): self.assertListEqual([], prime_factors(1))
  6. 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)
  7. Prime factorization – TDD style def prime_factors(number): """ Performs prime

    factorization. :param number: Number to be factorized. :type number: int :rtype: list """ return []
  8. 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))
  9. 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)
  10. Prime factorization – TDD style def prime_factors(number): return [] def

    prime_factors(number): factors = [] if number > 1: factors.append(2) return factors
  11. 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))
  12. 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)
  13. 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
  14. 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))
  15. 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)
  16. 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
  17. 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)
  18. 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
  19. 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
  20. 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))
  21. 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))
  22. 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))
  23. 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))
  24. 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)
  25. 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
  26. 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))
  27. 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)
  28. 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
  29. 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
  30. 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
  31. 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))
  32. Zalety TDD • Prostota iteracji designu • Pokrycie testami •

    Możliwość refactoringu • Zdecouplowany, testowalny kod • Nietrywialny design • Ograniczenie wykorzystania debugera • Brak strachu przez zmianami w kodzie
  33. Problemy z TDD • Konieczność zmiany stylu myślenia • Początkowo

    mało intuicyjna technika • Pokusa pisania kodu produkcyjnego bez testów