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".
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
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
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
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.
test_prime_factors (test.prime_factors.TestPrimeFactors) ---------------------------------------------------------------------- NameError: global name 'prime_factors' is not defined ---------------------------------------------------------------------- Ran 1 test in 0.000s FAILED (errors=1)
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
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
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
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
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
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
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
Możliwość refactoringu • Zdecouplowany, testowalny kod • Nietrywialny design • Ograniczenie wykorzystania debugera • Brak strachu przez zmianami w kodzie