Plan na dziś
1.Powtórzenie
2.Red
3.Green
4.Refactor
3 PRAWA TDD wg UNCLE BOBA
1.Nie pisz żadnego kodu produkcyjnego jeśli nie
ma nieprzechodzącego testu
2.Pisz tylko tyle testu, aby zademonstrować, że
nie przechodzi
3.Pisz tylko tyle kodu produkcyjnego, aby test
przeszedł
CYKL TDD
RED
GREEN
REFACTOR
spraw aby
test
przechodził
napisz
nieprzechodzący
test
refaktoryzuj
RED
Clock clock = new Clock();
clock.set(6, 15);
wait.minutes(5);
assertClockAt(6, 20);
RED
Clock clock = new Clock();
clock.set(6, 15);
wait.minutes(5);
assertClockAt(6, 20);
✔MYŚLENIE
✔PROJEKTOWANIE
FEEDBACK
✔JAKOŚĆ PROJEKTU
✔TESTOWALNOŚĆ
✔JAKOŚĆ TESTU
LISTA TESTÓW
● sprzedaż jednego produktu
● brak kodu kreskowego
● pusty kod kreskowy
● ...
● zła nazwa „Storage”
● duplikacja w CatalogItem
DOSTOSUJ SZYBKOŚĆ
CO SIĘ STANIE?
WIELKOŚĆ KROKU
BIEGŁOŚĆ W TDD
ZŁOŻONOŚĆ PROBLEMU
ZNAJOMOŚĆ DZIEDZINY
TESTY JEDNOSTKOWE
● Muszą uruchamiać się szybko
● Test nie jest testem jednostkowym jeśli:
● komunikuje się z bazą danych
● korzysta z sieci
● dotyka systemu plików
● musisz coś zmienić w środowisku aby go
uruchomić
Michael C. Feathers, Working Effectively with Legacy Code
DOBRE TESTY JEDNOSTKOWE
● F ast
● I solated
● R epeatable
● S elf-validating
● T imely
● tysiące / sekundę
● wskazuje błąd
● nieważna kolejność ani czas
● brak ręcznego sprawdzania
● napisane przed kodem
GREEN
Clock clock = new Clock();
clock.set(6, 15);
wait.minutes(5);
assertClockAt(6, 20);
class Clock
{
…
}
?
?
?
class Clock
{
…
}
class Clock
{
…
}
GREEN
Clock clock = new Clock();
clock.set(6, 15);
wait.minutes(5);
assertClockAt(6, 20);
class Clock
{
…
}
?
?
?
class Clock
{
…
}
class Clock
{
…
}
FEEDBACK
✔ POPRAWNOŚĆ
✔ REGRESJA
✔ WIELKOŚĆ KROKU
FAKE IT
OBVIOUS
IMPLEMENT
ATION
TRIANGULATE
FAKE IT
public int getSize {
return 12;
}
OBVIOUS
IMPLEMENT
ATION
public static int[] generatePrimes(int maxValue) {
if (maxValue >= 2) // the only valid case
{
// declarations
int s = maxValue + 1; // size of array
boolean[] f = new boolean[s];
int i;
// initialize array to true.
for (i = 0; i < s; i++)
f[i] = true;
// get rid of known non-primes
f[0] = f[1] = false;
// sieve
int j;
for (i = 2; i < Math.sqrt(s) + 1; i++) {
if (f[i]) // if i is uncrossed, cross its multiples.
{
for (j = 2 * i; j < s; j += i)
f[j] = false; // multiple is not prime
}
}
// how many primes are there?
int count = 0;
for (i = 0; i < s; i++) {
if (f[i])
count++; // bump count.
}
int[] primes = new int[count];
// move the primes into the result
for (i = 0, j = 0; i < s; i++) {
if (f[i]) // if prime
primes[j++] = i;
}
return primes; // return the primes
} else
// maxValue < 2
return new int[0]; // return null array if bad input.
}
TRIANGULATE
integer7ShouldNotBeDivisibleBy3
public boolean isDivisible(int dividend, int divisor {
return dividend % divisor == 0;
}
integer6ShouldBeDivisibleBy3
public boolean isDivisible(int dividend, int divisor {
return true;
}
REFACTOR
Clock clock = new Clock();
clock.set(6, 15);
wait.minutes(5);
assertClockAt(6, 20);
?
?
?
REFACTOR
Clock clock = new Clock();
clock.set(6, 15);
wait.minutes(5);
assertClockAt(6, 20);
?
?
?
✔ PROJEKT (ŁATWOŚĆ)
✔ TESTY (BEZPIECZEŃSTWO)
FEEDBACK
REFAKTORYZACJA
ZMIANA
WEWNĘTRZNEJ STRUKTURY
KODU BEZ ZMIANY
ZEWNĘTRZNEGO
ZACHOWANIA
POZIOMY REFAKTORYZACJI
double
basePrice
=
anOrder.basePrice();
return
(basePrice
>
1000);
return (anOrder.basePrice() > 1000);
2 NAJWAŻNIEJSZE ZASADY
REMOVE
DUPLICATION
(DRY)
IMPROVE
NAMES
GREEN
REFACTOR
UTRZYMUJ
TESTY
ZIELONE
[7,8,9] http://www.flickr.com/photos/thofik/3920097812
[14,16] http://www.flickr.com/photos/29225114@N08/2778223048/
[14] http://www.flickr.com/photos/j-pocztarski/4226650088/
[22] http://www.flickr.com/photos/macca/204553997
[22] http://www.courier-journal.com/blogs/vel05/uploaded_images/baby-names-720609.jpg
DZIĘKUJĘ
Zdjęcia:

02 - Mechanika TDD