introduzione al tdd
DESCRIPTION
Introduzione al TDD con esempi e consigli.TRANSCRIPT
![Page 1: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/1.jpg)
Introduzione al
Test Driven Development
Andrea Francia
http://www.andreafrancia.it
![Page 2: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/2.jpg)
ContentsConceptsDefinitionExample1: ParserExample2: Text To Speech
![Page 3: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/3.jpg)
Concepts
Test FirstAutomate tests
![Page 4: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/4.jpg)
What is a Automated Test?
![Page 5: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/5.jpg)
Automated Test Lifecycle
Giordano Scalzo: http://www.slideshare.net/giordano/tdd-iphonefordummies
![Page 6: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/6.jpg)
Automated Test Lifecycle
Giordano Scalzo: http://www.slideshare.net/giordano/tdd-iphonefordummies
![Page 7: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/7.jpg)
Automated Test Lifecycle
SUT: System Under TestGiordano Scalzo: http://www.slideshare.net/giordano/tdd-iphonefordummies
![Page 8: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/8.jpg)
Automated Test Lifecycle
SUT: System Under TestGiordano Scalzo: http://www.slideshare.net/giordano/tdd-iphonefordummies
![Page 9: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/9.jpg)
Automated Test Lifecycle
SUT: System Under TestGiordano Scalzo: http://www.slideshare.net/giordano/tdd-iphonefordummies
![Page 10: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/10.jpg)
Example of a Manual Test: nextLine()
public static void main(String[] args) {String text = "first line\nsecond line";
Scanner scanner = new Scanner(text);
System.out.println(scanner.nextLine()); // prints "first line"System.out.println(scanner.nextLine()); // prints "second line”
}
Code:
![Page 11: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/11.jpg)
assertEquals(expected, actual);
PASS FAIL
expected == actual
yes no
![Page 12: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/12.jpg)
Using JUnit@Test public void howNextLineWorks() throws IOException {
String text = "first line\nsecond line";
Scanner scanner = new Scanner(text);
assertEquals(”first line", scanner.nextLine()); assertEquals(”second line", scanner.nextLine()); }
Code:
Output:
![Page 13: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/13.jpg)
What is Test Driven Development?
![Page 14: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/14.jpg)
What is TDD?Test-driven development (TDD) is a software
development process that relies on the repetition of a very short development cycle:
Giordano Scalzo: http://www.slideshare.net/giordano/tdd-iphonefordummiesTim Ottinger:http://agileinaflash.blogspot.com/2009/02/red-green-refactor.html
![Page 15: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/15.jpg)
RED
first the developer writes a failing automated test case that defines a desired new behaviour (of the software),
![Page 16: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/16.jpg)
GREEN
then produces code to pass that test …
![Page 17: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/17.jpg)
Refactor
and finally refactors the new code to acceptable standards.
![Page 18: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/18.jpg)
![Page 19: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/19.jpg)
Example:Writing “df” Parser
![Page 20: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/20.jpg)
The df output[andreafrancia@deneb Dropbox]$ dfFilesystem 1K-blocks Used Available Use% Mounted on/dev/disk0s2 243862672 135971832 107634840 56% //dev/disk0s1 243862672 135971832 107634840 56% /tmp/dev/disk1s2 243862672 135971832 107634840 56% /optdevfs 109 109 0 100% /dev
Mount Points
![Page 21: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/21.jpg)
The problemList all mount points
![Page 22: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/22.jpg)
The ProblemWrite a method that extract the list of the mount
points from the output of df.
![Page 23: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/23.jpg)
First of all decompose the
problem!
![Page 24: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/24.jpg)
DecompositionParse the output of “df” process …
When there are no mounted volumes When there is only one volume mountedWhen there are many volumes When the a volume contains whitespaces
![Page 25: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/25.jpg)
First CycleParse the output of “df” process
When there are no volumes When there is only one volumeWhen there are many volumesWhen the a volume contains whitespaces
![Page 26: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/26.jpg)
@Test public void whenNoVolumes() { String input = "Filesystem 1024-blocks Used Available
Capacity Mounted on”; List<String> result = parseDfOutput(input);
assertEquals(emptyList(), result); }
![Page 27: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/27.jpg)
![Page 28: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/28.jpg)
@Test public void whenNoVolumes() { String input = "Filesystem 1024-blocks Used Available
Capacity Mounted on”; List<String> result = parseDfOutput(input);
assertEquals(emptyList(), result); }
private List<String> parseDfOutput(String string) { return null; }
![Page 29: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/29.jpg)
@Test public void whenNoVolumes() { String input = "Filesystem 1024-blocks Used Available
Capacity Mounted on”; List<String> result = parseDfOutput(input);
assertEquals(emptyList(), result); }
private List<String> parseDfOutput(String string) { return emptyList(); }
![Page 30: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/30.jpg)
No need for refactoring
![Page 31: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/31.jpg)
Second CycleParse the output of “df” process
When there are no volumes When there is only one volumeWhen there are many volumesWhen the a volume contains whitespaces
![Page 32: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/32.jpg)
@Test public void whenOneVolume() { List<String> result = parseDfOutput("" + "Filesystem 1024-blocks Used Available Capacity
Mounted on\n" + "/dev/disk0s2 243862672 135479924 108126748
56% /");
assertEquals(asList("/"), result); }
![Page 33: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/33.jpg)
private List<String> parseDfOutput(String string) { return emptyList(); }
![Page 34: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/34.jpg)
private List<String> parseDfOutput(String string) { List<String> result = new ArrayList<String>();
return result;}
![Page 35: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/35.jpg)
private List<String> parseDfOutput(String input) { List<String> result = new ArrayList<String>();
Scanner scanner = new Scanner(input); scanner.nextLine(); // skip header if(scanner.hasNextLine()) { String line = scanner.nextLine(); Scanner scanner1 = new Scanner(line); scanner1.next(); // skip Filesystem scanner1.next(); // skip 1024-blocks scanner1.next(); // skip Used scanner1.next(); // skip Available scanner1.next(); // skip Capacity String mountPoint = scanner1.next(); result.add(mountPoint); }
return result; }
![Page 36: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/36.jpg)
private List<String> parseDfOutput(String input) { List<String> result = new ArrayList<String>();
Scanner lines = new Scanner(input); lines.nextLine(); // skip header if(lines.hasNextLine()) { String line = lines.nextLine(); Scanner values = new Scanner(line); values.next(); // skip Filesystem values.next(); // skip 1024-blocks values.next(); // skip Used values.next(); // skip Available values.next(); // skip Capacity String mountPoint = values.next(); result.add(mountPoint); }
return result; }
![Page 37: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/37.jpg)
private List<String> parseDfOutput(String input) { List<String> result = new ArrayList<String>();
Scanner lines = new Scanner(input); lines.nextLine(); // skip header if(lines.hasNextLine()) { result.add(parseMountPoint(lines.nextLine())); }
return result; }
private String parseMountPoint(String line) { Scanner values = new Scanner(line); values.next(); // skip Filesystem values.next(); // skip 1024-blocks values.next(); // skip Used values.next(); // skip Available values.next(); // skip Capacity String mountPoint = values.next(); return mountPoint; }
![Page 38: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/38.jpg)
Third CycleParse the output of “df” process
When there are no volumes When there is only one volumeWhen there are many volumesWhen the a volume contains whitespaces
![Page 39: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/39.jpg)
@Test public void whenMultipleVolume() { List<String> result = parseDfOutput("" + "Filesystem 1024-blocks Used Available Capacity
Mounted on\n" + "/dev/disk0s2 243862672 135479924 108126748 56% /\
n" + "/dev/disk0s2 243862672 135479924 108126748
56% /media/disk\n" + "/dev/disk0s2 243862672 135479924 108126748 56%
/tmp\n");
assertEquals(asList("/", "/media/disk", "/tmp"), result); }
![Page 40: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/40.jpg)
@Test public void whenMultipleVolume() { List<String> result = parseDfOutput("" + "Filesystem 1024-blocks Used Available Capacity
Mounted on\n" + "/dev/disk0s2 243862672 135479924 108126748 56% /\
n" + "/dev/disk0s2 243862672 135479924 108126748
56% /media/disk\n" + "/dev/disk0s2 243862672 135479924 108126748 56%
/tmp\n");
assertEquals(asList("/", "/media/disk", "/tmp"), result); }
![Page 41: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/41.jpg)
private List<String> parseDfOutput(String input) { List<String> result = new ArrayList<String>();
Scanner lines = new Scanner(input); lines.nextLine(); // skip header if(lines.hasNextLine()) { String line = lines.nextLine(); String mountPoint = parseMountPoint(line); result.add(mountPoint); }
return result; }
![Page 42: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/42.jpg)
private List<String> parseDfOutput(String input) { List<String> result = new ArrayList<String>();
Scanner lines = new Scanner(input); lines.nextLine(); // skip header while(lines.hasNextLine()) { String line = lines.nextLine(); String mountPoint = parseMountPoint(line); result.add(mountPoint); }
return result; }
![Page 43: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/43.jpg)
TDD Rules
![Page 44: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/44.jpg)
TDD RulesTest FirstTest for All FeaturesRemove all duplication (always)
![Page 45: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/45.jpg)
Some hintsKeep tests running and passingKeeps test smallDon’t mix phases (Red, Green,
Refactor)Don’t mix unit tests with
integration testsTest only one feature per test
![Page 46: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/46.jpg)
Examples from my last work
![Page 47: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/47.jpg)
Regole applicateOgni feature deve essere sviluppata
secondo il TDDPartire dai test di accettazioneRitardare le decisioni di design all’ultimo
momento responsabileApplicare un principio di design solo dopo
aver avuto la prova che sia utile in quel specifico caso
![Page 48: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/48.jpg)
Prima feature: produrre testo pronunciabile
![Page 49: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/49.jpg)
Test di accettazionepublic class HoroscopeTest {
@Test public void userListenOroscope() {
Horoscope horoscope = new Horoscope();
horoscope.saveDivination("22-GIU-10", "Ariete", "Sarai molto fortunato."); String result =
horoscope.GET("/horoscope/ariete.txt");
assertEquals("22 giugno 2010: Ariete, Sarai molto fortunato.”, result);
}
![Page 50: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/50.jpg)
No test No codeQuando scrivo il codice di produzione
scrivo il minimo necessario a far passare il test
Se il minimo non mi convince (è troppo stupido), vuol dire che manca una specifica funzionale cioè manca un test.
Prima di scrivere una qualsiasi riga di codice in più aggiungo un test che la richieda.
![Page 51: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/51.jpg)
@Test public void shouldStoreDivinationsForMultipleSigns() {
Horoscope horoscope = new Horoscope();horoscope.saveDivination("22-GIU-10", "Ariete", "for ariete");horoscope.saveDivination("22-GIU-10", "Toro", "for toro");
assertEquals("22 giugno 2010: Ariete, for ariete", horoscope.GET("/horoscope/ariete.txt"));assertEquals("22 giugno 2010: Toro, for toro", horoscope.GET("/horoscope/toro.txt"));}
![Page 52: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/52.jpg)
Cerco di non anticipare il design
Prima di affrontare lo sviluppo faccio una veloce sessione di design
Non implemento nessuna decisione fino a che non si rende necessaria
E.g. anche servirà un DAO per adesso salvo tutto in RAM
![Page 53: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/53.jpg)
Seconda Feature: oroscopo ascoltabile
![Page 54: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/54.jpg)
@Test public void howToCreateMp3() {
Horoscope horoscope = new Horoscope( aFakeSyntetizerWhichReturns( aMp3Stream()));
horoscope.saveDivination("22-GIU-10", "Ariete", "divination");
assertThat(horoscope.GET( "/horoscope/ariete.mp3").asByteArray(), is(equalTo(aMp3Stream())));}
![Page 55: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/55.jpg)
ResourceOra il GET restituisce una Resource
public Resource GET(String path) {...}
Il client decide quale rappresentazione usare:
horoscope.GET("/horoscope/ariete/divination.txt").asString());
horoscope.GET("/horoscope/ariete/divination.mp3").asByteArray();
![Page 56: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/56.jpg)
Terza feature: la persistenza
![Page 57: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/57.jpg)
Stato delle coseAl momento tutto viene persistito in memoria (in
una HashMap)Non esiste ancora un oggetto DAO, tutto viene
fatto dall’unica class Horoscope
![Page 58: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/58.jpg)
Estrazione del comportamento
public class MemoryDivinationRepo {
Divination lastDivinationForSign(String sign); void saveDivinationFromPronounce(String sign, String pronounce);
};
public interface Divination { String asText(); byte[] asMp3();};
![Page 59: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/59.jpg)
Estrazione dell’interfacciapublic class MemoryDivinationRepo implements DivinationRepo {...}
public interface DivinationRepo { Divination lastDivinationForSign(String sign); void saveDivinationFromPronounce(String sign, String pronounce);};
![Page 60: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/60.jpg)
Caratterizzazione del comportamento
L’interfaccia è una minima parte del contratto, la parte più importante è il comportamento che l’oggetto dovrebbe avere.
Il comportamento lo estraggo con dei test di caratterizzazione
![Page 61: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/61.jpg)
Caratterizzazione di MemoryDivinationRepo
public class MemoryDivinationRepoTest { @Test public void shouldStoreDivinationPronounceForASign() {...}
@Test public void shouldReplyWithAPronouncedMp3() {...}
@Test public void shouldStoreDivinationPronounceForMultipleSigns() {...}
@Test public void shouldOverrideDivinationPronounce() {...}}
![Page 63: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/63.jpg)
Extra slides
![Page 64: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/64.jpg)
Example of an Automated Test
@Test public void shouldParsePath() {
String content = "[Trash Info]\n" + "Path=/home/andrea/foo.txt\n" + "DeletionDate=2010-08-23T12:59:14\n";
String path = Parser.parsePath(content);
assertEquals("/home/andrea/foo.txt”, path);}
![Page 65: Introduzione al TDD](https://reader033.vdocuments.site/reader033/viewer/2022061202/547c188ab4af9f16628b458b/html5/thumbnails/65.jpg)
Testing Frameworks
http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks
•PHPUnit•SimpleTest
•Google C++ Testing Framework•CppUnitLite•CppUnit
•JUnit•TestNG
•PyUnit•Nose