196
16 mai 13 Test unitaire ? Mock ? TDD ? Kezako ? 1

Tests unitaires mock_kesako_20130516

  • Upload
    soat

  • View
    1.335

  • Download
    0

Embed Size (px)

DESCRIPTION

Vous subissez les régressions à chaque livraison ? Vous ne voyez pas l’intérêt des tests unitaires car ils ne servent qu’à tester des additions ? Les tests ne sont pas applicables à votre projet car il est trop complexe ? Si c’est le cas, suivez David dans la quête du Test Driven Development. Vous rencontrerez pléthore d’ennemies contre lesquels vous aurez à combattre : bugs, complexité, code statique, couplage fort. Ils essaieront de vous barrer la route, mais heureusement, vous pourrez compter sur vos alliés jUnit, Mockito, refactoring et injection/dépendance. David finira la soirée par une démonstration pratique sur un exercice de refactoring.

Citation preview

Page 2: Tests unitaires mock_kesako_20130516

Bienvenue !

Page 3: Tests unitaires mock_kesako_20130516

❤=+

Page 4: Tests unitaires mock_kesako_20130516

réseaux sociaux

Prochaines conférences : http://soat.fr

twitter : @soatgroup / @soatexpertsjava

slideshares : http://fr.slideshare.net/soatexpert

Aller plus loin : http://blog.soat.fr

Page 5: Tests unitaires mock_kesako_20130516

Test unitaire ? Mock ? TDD ? Kezako ?en finir avec les régressions par David Wursteisen

16 MAI 2013

Page 6: Tests unitaires mock_kesako_20130516
Page 7: Tests unitaires mock_kesako_20130516
Page 8: Tests unitaires mock_kesako_20130516

Nouveau client !

Page 9: Tests unitaires mock_kesako_20130516

Nouveau projet !

Page 10: Tests unitaires mock_kesako_20130516
Page 11: Tests unitaires mock_kesako_20130516
Page 13: Tests unitaires mock_kesako_20130516

La documentation explique le code /** * * @param xml : document xml représentant le swap * @return objet Swap */ public Swap parse(String xml) { Swap swap = new Swap(); String currency = getNodeValue("/swap/currency", xml); swap.setCurrency(currency); /* beaucoup de code... */ Date d = new Date(); if(test == 1) { if(d.after(spotDate)) { swap.setType("IRS"); } else { swap.setType("CURVE"); } } else if (test == 2) { if(d.after(spotDate)) { swap.setType("IRS"); } else { swap.setType("CURVE"); } } /* encore beaucoup de code... */ return swap; }

Page 14: Tests unitaires mock_kesako_20130516

La documentation explique le code 1 /** 2 * 3 * @param xml : document xml représentant le swap 4 * @return objet Swap 5 */ 6 public Swap parse(String xml) { 7 Swap swap = new Swap(); 8 String currency = getNodeValue("/swap/currency", xml); 9 swap.setCurrency(currency);[...] /* beaucoup de code... */ 530 Date d = new Date(); 531 if(test == 1) { 532 if(d.after(spotDate)) { 533 swap.setType("IRS"); 534 } else { 535 swap.setType("CURVE"); 536 } 537 } else if (test == 2) { 538 if(d.after(spotDate)) { 539 swap.setType("IRS"); 540 } else { 541 swap.setType("CURVE"); 542 } 543 }[...] /* encore beaucoup de code... */1135 return swap;1136 }

1000 LIGNES !

Page 15: Tests unitaires mock_kesako_20130516

La documentation a raison

1 /**2 * Always returns true.3 */4 public boolean isAvailable() {5 return false;6 }

Page 16: Tests unitaires mock_kesako_20130516

La documentation a raison

1 /**2 * Always returns true.3 */4 public boolean isAvailable() {5 return false;6 }

WTF ?!?

Page 17: Tests unitaires mock_kesako_20130516

La documentation n’est plusfiableune aideutile

Page 18: Tests unitaires mock_kesako_20130516

4 obj = networkService.getObject("product", id);

1 public Object getProduct(String id) {2 Object obj = null;3 try {4 obj = networkService.getObject("product", id);5 } catch (IOException e) {6 System.err.println("Error with obj : " + obj.toString());7 }8 return obj;9 }

Faire du code qui marche

Page 19: Tests unitaires mock_kesako_20130516

4 obj = networkService.getObject("product", id);

1 public Object getProduct(String id) {2 Object obj = null;3 try {4 obj = networkService.getObject("product", id);5 } catch (IOException e) {6 System.err.println("Error with obj : " + obj.toString());7 }8 return obj;9 }

Faire du code qui marche

Page 20: Tests unitaires mock_kesako_20130516

1 public Object getProduct(String id) {2 Object obj = null;3 try {4 obj = networkService.getObject("product", id);5 } catch (IOException e) {6 System.err.println("Error with obj : " + obj.toString());7 }8 return obj;9 }

2 Object obj = null; 5 } catch (IOException e) {6 System.err.println("Error with obj : " + obj.toString());7 }

Faire du code qui marche

NullPointerException !

Page 21: Tests unitaires mock_kesako_20130516

4 account = (BankAccount) service.getProduct(this.name);5 account.deposit();

1 public void affiche(BankAccount account, ProductService service) {2 System.out.println("Bank Account : "+this.name);3 System.out.println("Autres informations : ");4 account = (BankAccount) service.getProduct(this.name);5 account.deposit();6 System.out.println(account);7 System.out.println("=== FIN ===");8 9 }

Code simple

HTTP://EN.WIKIPEDIA.ORG/WIKI/FILE:JEU_DE_MIKADO.JPG

Page 22: Tests unitaires mock_kesako_20130516

4 account = (BankAccount) service.getProduct(this.name);5 account.deposit();

1 public void affiche(BankAccount account, ProductService service) {2 System.out.println("Bank Account : "+this.name);3 System.out.println("Autres informations : ");4 account = (BankAccount) service.getProduct(this.name);5 account.deposit();6 System.out.println(account);7 System.out.println("=== FIN ===");8 9 }

Code simple

HTTP://EN.WIKIPEDIA.ORG/WIKI/FILE:JEU_DE_MIKADO.JPG

Page 23: Tests unitaires mock_kesako_20130516

4 account = (BankAccount) service.getProduct(this.name);5 account.deposit();

1 public void affiche(BankAccount account, ProductService service) {2 System.out.println("Bank Account : "+this.name);3 System.out.println("Autres informations : ");4 account = (BankAccount) service.getProduct(this.name);5 account.deposit();6 System.out.println(account);7 System.out.println("=== FIN ===");8 9 }

Code simple

HTTP://EN.WIKIPEDIA.ORG/WIKI/FILE:JEU_DE_MIKADO.JPG

Page 24: Tests unitaires mock_kesako_20130516
Page 25: Tests unitaires mock_kesako_20130516
Page 26: Tests unitaires mock_kesako_20130516

C’est compliqué de fairesimpleun testune évolution

Page 27: Tests unitaires mock_kesako_20130516
Page 28: Tests unitaires mock_kesako_20130516
Page 29: Tests unitaires mock_kesako_20130516

Bonne nouvelle !

Page 30: Tests unitaires mock_kesako_20130516

Je vous prend dans mon équipe !

Page 31: Tests unitaires mock_kesako_20130516

HTTP://WWW.SXC.HU/PROFILE/HOTBLACK

COMMENT VA T’ON POUVOIR S’EN SORTIR ?

Page 33: Tests unitaires mock_kesako_20130516

PRINCIPE DE BASE

Page 34: Tests unitaires mock_kesako_20130516

Ecriture du test

Page 35: Tests unitaires mock_kesako_20130516

Lancementdu test

Ecriture du test

Page 36: Tests unitaires mock_kesako_20130516

Lancementdu test

Correction de l’implémentation

Ecriture du test

KO

Page 37: Tests unitaires mock_kesako_20130516

Lancementdu test

Correction de l’implémentation

Ecriture du test

Fin

KO

OK

Page 38: Tests unitaires mock_kesako_20130516

Lancementdu test

Correction de l’implémentation

Ecriture du test

Fin

KO

OK

REFACTOR

Page 39: Tests unitaires mock_kesako_20130516

Toujours faire le test cassant avant le test passant(pour tester le test)

Page 40: Tests unitaires mock_kesako_20130516

TEST UNITAIREtester la plus petite unité de code possible

Page 41: Tests unitaires mock_kesako_20130516

TEST UNITAIREtester la plus petite unité de code possible

SIMPLE

Page 42: Tests unitaires mock_kesako_20130516

TEST UNITAIREtester la plus petite unité de code possible

SIMPLEFEEDBACK

Page 43: Tests unitaires mock_kesako_20130516

TEST UNITAIREtester la plus petite unité de code possible

SIMPLEFEEDBACKCOÛT

Page 44: Tests unitaires mock_kesako_20130516
Page 45: Tests unitaires mock_kesako_20130516

$400 MILLIONS

Page 46: Tests unitaires mock_kesako_20130516

EXEMPLE

Page 47: Tests unitaires mock_kesako_20130516

1 @Test2 public void can_deposit() {3 bankAccount.setBalance(50);4 5 boolean result = bankAccount.deposit(1000);6 7 assertTrue(result);8 assertEquals(1050, bankAccount.getBalance());9 }

3 bankAccount.setBalance(50);

Test d’abord !

Page 48: Tests unitaires mock_kesako_20130516

1 @Test2 public void can_deposit() {3 bankAccount.setBalance(50);4 5 boolean result = bankAccount.deposit(1000);6 7 assertTrue(result);8 assertEquals(1050, bankAccount.getBalance());9 }

3 bankAccount.setBalance(50);

Test d’abord !

Page 49: Tests unitaires mock_kesako_20130516

5 boolean result = bankAccount.deposit(1000);

1 @Test2 public void can_deposit() {3 bankAccount.setBalance(50);4 5 boolean result = bankAccount.deposit(1000);6 7 assertTrue(result);8 assertEquals(1050, bankAccount.getBalance());9 }

Test d’abord !

Page 50: Tests unitaires mock_kesako_20130516

1 @Test2 public void can_deposit() {3 bankAccount.setBalance(50);4 5 boolean result = bankAccount.deposit(1000);6 7 assertTrue(result);8 assertEquals(1050, bankAccount.getBalance());9 }

Test d’abord !

7 assertTrue(result);8 assertEquals(1050, bankAccount.getBalance());

Page 51: Tests unitaires mock_kesako_20130516

Test d’abord !

1 boolean deposit(int amount) {2 return false;3 }

Page 52: Tests unitaires mock_kesako_20130516

Test d’abord !

1 boolean deposit(int amount) {2 return false;3 }

Page 53: Tests unitaires mock_kesako_20130516

Test d’abord !

1 boolean deposit(int amount) {2 bal = bal + amount;3 return true;4 }

Page 54: Tests unitaires mock_kesako_20130516

Test d’abord !

1 boolean deposit(int amount) {2 bal = bal + amount;3 return true;4 }

Page 55: Tests unitaires mock_kesako_20130516

Test d’abord !

1 @Test2 public void cant_deposit_with_negative_amount() {3 bankAccount.setBalance(100);4 5 boolean result = bankAccount.deposit(-20);6 7 assertFalse(result);8 assertEquals(100, bankAccount.getBalance());9 }

Page 56: Tests unitaires mock_kesako_20130516

Test d’abord !

1 @Test2 public void cant_deposit_with_negative_amount() {3 bankAccount.setBalance(100);4 5 boolean result = bankAccount.deposit(-20);6 7 assertFalse(result);8 assertEquals(100, bankAccount.getBalance());9 }

3 bankAccount.setBalance(100);

Page 57: Tests unitaires mock_kesako_20130516

Test d’abord !

1 @Test2 public void cant_deposit_with_negative_amount() {3 bankAccount.setBalance(100);4 5 boolean result = bankAccount.deposit(-20);6 7 assertFalse(result);8 assertEquals(100, bankAccount.getBalance());9 }

5 boolean result = bankAccount.deposit(-20);

Page 58: Tests unitaires mock_kesako_20130516

Test d’abord !

1 @Test2 public void cant_deposit_with_negative_amount() {3 bankAccount.setBalance(100);4 5 boolean result = bankAccount.deposit(-20);6 7 assertFalse(result);8 assertEquals(100, bankAccount.getBalance());9 }

7 assertFalse(result);8 assertEquals(100, bankAccount.getBalance());

Page 59: Tests unitaires mock_kesako_20130516

Test d’abord !

1 boolean deposit(int amount) {2 bal = bal + amount;3 return true;4 }

Page 60: Tests unitaires mock_kesako_20130516

Test d’abord !

1 boolean deposit(int amount) {2 bal = bal + amount;3 return true;4 }

Page 61: Tests unitaires mock_kesako_20130516

Test d’abord !

1 boolean deposit(int amount) {2 if(amount < 0) {3 return false;4 }5 bal = bal + amount;6 return true;7 }

Page 62: Tests unitaires mock_kesako_20130516

Test d’abord !

1 boolean deposit(int amount) {2 if(amount < 0) {3 return false;4 }5 bal = bal + amount;6 return true;7 }

Page 63: Tests unitaires mock_kesako_20130516

Acteur / Action / Assertion

Page 64: Tests unitaires mock_kesako_20130516

les «3 A» : Acteur/Action/Assertion

1 @Test2 public void cant_deposit_with_negative_amount() {3 bankAccount.setBalance(100);4 5 boolean result = bankAccount.deposit(-20);6 7 assertFalse(result);8 assertEquals(100, bankAccount.getBalance());9 }

Page 65: Tests unitaires mock_kesako_20130516

1 @Test2 public void cant_deposit_with_negative_amount() {3 bankAccount.setBalance(100);4 5 boolean result = bankAccount.deposit(-20);6 7 assertFalse(result);8 assertEquals(100, bankAccount.getBalance());9 }

les «3 A» : Acteur/Action/Assertion

3 bankAccount.setBalance(100);

Acteur

Page 66: Tests unitaires mock_kesako_20130516

1 @Test2 public void cant_deposit_with_negative_amount() {3 bankAccount.setBalance(100);4 5 boolean result = bankAccount.deposit(-20);6 7 assertFalse(result);8 assertEquals(100, bankAccount.getBalance());9 }

les «3 A» : Acteur/Action/Assertion

5 boolean result = bankAccount.deposit(-20);

Action

Page 67: Tests unitaires mock_kesako_20130516

1 @Test2 public void cant_deposit_with_negative_amount() {3 bankAccount.setBalance(100);4 5 boolean result = bankAccount.deposit(-20);6 7 assertFalse(result);8 assertEquals(100, bankAccount.getBalance());9 }

les «3 A» : Acteur/Action/Assertion

7 assertFalse(result);8 assertEquals(100, bankAccount.getBalance());

Assertions

Page 68: Tests unitaires mock_kesako_20130516

KISS

Page 69: Tests unitaires mock_kesako_20130516

KISSKEEP IT SIMPLE (AND STUPID)

Page 70: Tests unitaires mock_kesako_20130516

KISSKEEP IT SIMPLE (AND STUPID)

Page 71: Tests unitaires mock_kesako_20130516

7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99"); 8 9 // Vérifier.10 Assert.assertNotNull("Extra non trouvé.", targetDTO);11 Assert.assertEquals("Les accountId doivent être identiques.",12 "ABC99", targetDTO.getAccountId());

1 @Test 2 public void testGetCustomerOK() { 3 4 LOGGER.info("======= testGetCustomerOK starting..."); 5 6 try { 7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99"); 8 9 // Vérifier.10 Assert.assertNotNull("Extra non trouvé.", targetDTO);11 Assert.assertEquals("Les accountId doivent être identiques.",12 "ABC99", targetDTO.getAccountId());13 14 } catch (CustomerBusinessException exception) {15 LOGGER.error("CustomerBusinessException : {}",16 exception.getCause());17 Assert.fail(exception.getMessage());18 } catch (UnavailableResourceException exception) {19 LOGGER.error("UnavailableResourceException : {}",20 exception.getMessage());21 Assert.fail(exception.getMessage());22 } catch (UnexpectedException exception) {23 LOGGER.error("UnexpectedException : {}" +24 exception.getMessage());25 Assert.fail(exception.getMessage());26 } catch (Exception exception) {27 LOGGER.error("CRASH : " + exception.getMessage());28 Assert.fail(exception.getMessage());29 }30 31 LOGGER.info("======= testGetCustomerOK done.");32 }

Page 72: Tests unitaires mock_kesako_20130516

7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99"); 8 9 // Vérifier.10 Assert.assertNotNull("Extra non trouvé.", targetDTO);11 Assert.assertEquals("Les accountId doivent être identiques.",12 "ABC99", targetDTO.getAccountId());

1 @Test 2 public void testGetCustomerOK() { 3 4 LOGGER.info("======= testGetCustomerOK starting..."); 5 6 try { 7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99"); 8 9 // Vérifier.10 Assert.assertNotNull("Extra non trouvé.", targetDTO);11 Assert.assertEquals("Les accountId doivent être identiques.",12 "ABC99", targetDTO.getAccountId());13 14 } catch (CustomerBusinessException exception) {15 LOGGER.error("CustomerBusinessException : {}",16 exception.getCause());17 Assert.fail(exception.getMessage());18 } catch (UnavailableResourceException exception) {19 LOGGER.error("UnavailableResourceException : {}",20 exception.getMessage());21 Assert.fail(exception.getMessage());22 } catch (UnexpectedException exception) {23 LOGGER.error("UnexpectedException : {}" +24 exception.getMessage());25 Assert.fail(exception.getMessage());26 } catch (Exception exception) {27 LOGGER.error("CRASH : " + exception.getMessage());28 Assert.fail(exception.getMessage());29 }30 31 LOGGER.info("======= testGetCustomerOK done.");32 }

Page 73: Tests unitaires mock_kesako_20130516

1 @Test 2 public void testGetCustomerOK() { 3 4 LOGGER.info("======= testGetCustomerOK starting..."); 5 6 try { 7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99"); 8 9 // Vérifier.10 Assert.assertNotNull("Extra non trouvé.", targetDTO);11 Assert.assertEquals("Les accountId doivent être identiques.",12 "ABC99", targetDTO.getAccountId());13 14 } catch (CustomerBusinessException exception) {15 LOGGER.error("CustomerBusinessException : {}",16 exception.getCause());17 Assert.fail(exception.getMessage());18 } catch (UnavailableResourceException exception) {19 LOGGER.error("UnavailableResourceException : {}",20 exception.getMessage());21 Assert.fail(exception.getMessage());22 } catch (UnexpectedException exception) {23 LOGGER.error("UnexpectedException : {}" +24 exception.getMessage());25 Assert.fail(exception.getMessage());26 } catch (Exception exception) {27 LOGGER.error("CRASH : " + exception.getMessage());28 Assert.fail(exception.getMessage());29 }30 31 LOGGER.info("======= testGetCustomerOK done.");32 }

14 } catch (CustomerBusinessException exception) {15 LOGGER.error("CustomerBusinessException : {}",16 exception.getCause());17 Assert.fail(exception.getMessage());18 } catch (UnavailableResourceException exception) {19 LOGGER.error("UnavailableResourceException : {}",20 exception.getMessage());21 Assert.fail(exception.getMessage());22 } catch (UnexpectedException exception) {23 LOGGER.error("UnexpectedException : {}" +24 exception.getMessage());25 Assert.fail(exception.getMessage());26 } catch (Exception exception) {27 LOGGER.error("CRASH : " + exception.getMessage());28 Assert.fail(exception.getMessage());29 }30 31 LOGGER.info("======= testGetCustomerOK done.");

BRUIT

Page 74: Tests unitaires mock_kesako_20130516

KISS !

1 @Test2 public void can_get_customer() throws Exception {3 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99");4 Assert.assertEquals("Les accountId doivent être identiques.",5 "ABC99", targetDTO.getAccountId());6 }

Page 76: Tests unitaires mock_kesako_20130516

VENIR ARMÉ

Page 77: Tests unitaires mock_kesako_20130516

JUNIT + MOCKITO + ASSERTJ

Page 78: Tests unitaires mock_kesako_20130516

JUNIT + MOCKITO + ASSERTJ

Page 79: Tests unitaires mock_kesako_20130516

Mock ?

simulacre

se fait passer pour ce qu’il n’est pas

comportement paramétrable

Page 80: Tests unitaires mock_kesako_20130516

MOCKITO

Page 81: Tests unitaires mock_kesako_20130516

doReturn(new BankAccount()).when(daoService).getObject("product", "id");

Page 82: Tests unitaires mock_kesako_20130516

doReturn(new BankAccount()).when(daoService).getObject("product", "id");doReturn(new BankAccount())

Page 83: Tests unitaires mock_kesako_20130516

doReturn(new BankAccount()).when(daoService).getObject("product", "id");when(daoService)

Page 84: Tests unitaires mock_kesako_20130516

doReturn(new BankAccount()).when(daoService).getObject("product", "id"); getObject("product", "id");

Page 85: Tests unitaires mock_kesako_20130516

doThrow(IOException.class).when(daoService).getObject("product", "id");

Page 86: Tests unitaires mock_kesako_20130516

doThrow(IOException.class).when(daoService).getObject("product", "id");doThrow(IOException.class)

Page 87: Tests unitaires mock_kesako_20130516

doThrow(IOException.class).when(daoService).getObject("product", "id");when(daoService)

Page 88: Tests unitaires mock_kesako_20130516

doThrow(IOException.class).when(daoService).getObject("product", "id");getObject("product", "id");

Page 89: Tests unitaires mock_kesako_20130516

ASSERTJ

Page 90: Tests unitaires mock_kesako_20130516

assertThat(age).isGreaterThan(5);

Page 91: Tests unitaires mock_kesako_20130516

assertThat(myList).containsExactly("MONAD42", "META18")

Page 92: Tests unitaires mock_kesako_20130516

assertThat(negotation).isBooked();

Page 93: Tests unitaires mock_kesako_20130516

NOUVEAU CODE = NOUVEAU TEST

Page 94: Tests unitaires mock_kesako_20130516

NOUVEAU BUG = NOUVEAU TEST

Page 95: Tests unitaires mock_kesako_20130516

nouveau bug = nouveau test

1 public Object getProduct(String id) {2 Object obj = null;3 try {4 obj = networkService.getObject("product", id);5 } catch (IOException e) {6 System.err.println("Error with obj : " + obj.toString());7 }8 return obj;9 }

Page 96: Tests unitaires mock_kesako_20130516

1 public Object getProduct(String id) {2 Object obj = null;3 try {4 obj = networkService.getObject("product", id);5 } catch (IOException e) {6 System.err.println("Error with obj : " + obj.toString());7 }8 return obj;9 }

nouveau bug = nouveau test

6 System.err.println("Error with obj : " + obj.toString());

LE BUG EST ICI !

Page 97: Tests unitaires mock_kesako_20130516

nouveau bug = nouveau test

1 @Test2 public void can_return_null_when_ioexception() throws IOException {3 Mockito.doThrow(IOException.class)4 .when(networkService).getObject("product", "azerty");5 6 Object product = service.getProduct("azerty");7 8 assertThat(product).isNull();9 }

Page 98: Tests unitaires mock_kesako_20130516

3 Mockito.doThrow(IOException.class)4 .when(networkService).getObject("product", "azerty");

1 @Test2 public void can_return_null_when_ioexception() throws IOException {3 Mockito.doThrow(IOException.class)4 .when(networkService).getObject("product", "azerty");5 6 Object product = service.getProduct("azerty");7 8 assertThat(product).isNull();9 }

nouveau bug = nouveau test

Page 99: Tests unitaires mock_kesako_20130516

1 @Test2 public void can_return_null_when_ioexception() throws IOException {3 Mockito.doThrow(IOException.class)4 .when(networkService).getObject("product", "azerty");5 6 Object product = service.getProduct("azerty");7 8 assertThat(product).isNull();9 }

6 Object product = service.getProduct("azerty");

nouveau bug = nouveau test

Page 100: Tests unitaires mock_kesako_20130516

8 assertThat(product).isNull();

1 @Test2 public void can_return_null_when_ioexception() throws IOException {3 Mockito.doThrow(IOException.class)4 .when(networkService).getObject("product", "azerty");5 6 Object product = service.getProduct("azerty");7 8 assertThat(product).isNull();9 }

nouveau bug = nouveau test

Page 101: Tests unitaires mock_kesako_20130516

nouveau bug = nouveau test

1 public Object getProduct(String id) {2 Object obj = null;3 try {4 obj = networkService.getObject("product", id);5 } catch (IOException e) {6 System.err.println("Error with obj : " + obj.toString());7 }8 return obj;9 }

Page 102: Tests unitaires mock_kesako_20130516

nouveau bug = nouveau test

1 public Object getProduct(String id) {2 Object obj = null;3 try {4 obj = networkService.getObject("product", id);5 } catch (IOException e) {6 System.err.println("Error with obj : " + obj.toString());7 }8 return obj;9 }

Page 103: Tests unitaires mock_kesako_20130516

1 public Object getProduct(String id) {2 Object obj = null;3 try {4 obj = networkService.getObject("product", id);5 } catch (IOException e) {6 System.err.println("Error with obj : " + obj.toString());7 }8 return obj;9 }

nouveau bug = nouveau test

6 System.err.println("Error with obj : " + obj.toString());

LE BUG EST TOUJOURS ICI !

Page 104: Tests unitaires mock_kesako_20130516

1 public Object getProduct(String id) {2 Object obj = null;3 try {4 obj = networkService.getObject("product", id);5 } catch (IOException e) {6 System.err.println("Error with obj with id: " + id);7 }8 return obj;9 }

nouveau bug = nouveau test

6 System.err.println("Error with obj with id: " + id);

Page 105: Tests unitaires mock_kesako_20130516

nouveau bug = nouveau test

1 public Object getProduct(String id) {2 Object obj = null;3 try {4 obj = networkService.getObject("product", id);5 } catch (IOException e) {6 System.err.println("Error with obj with id: " + id);7 }8 return obj;9 }

6 System.err.println("Error with obj with id: " + id);

Page 106: Tests unitaires mock_kesako_20130516

Laissez votre câble tranquille

Page 107: Tests unitaires mock_kesako_20130516

TESTER DOIT ÊTRE SIMPLE

Page 108: Tests unitaires mock_kesako_20130516

code complexe 1 /** 2 * 3 * @param xml : document xml représentant le swap 4 * @return objet Swap 5 */ 6 public Swap parse(String xml) { 7 Swap swap = new Swap(); 8 String currency = getNodeValue("/swap/currency", xml); 9 swap.setCurrency(currency);[...] /* beaucoup de code... */ 530 Date d = new Date(); 531 if(test == 1) { 532 if(d.after(spotDate)) { 533 swap.setType("IRS"); 534 } else { 535 swap.setType("CURVE"); 536 } 537 } else if (test == 2) { 538 if(d.after(spotDate)) { 539 swap.setType("IRS"); 540 } else { 541 swap.setType("CURVE"); 542 } 543 }[...] /* encore beaucoup de code... */1135 return swap;1136 }

Page 109: Tests unitaires mock_kesako_20130516

1 @Test 2 public void can_parse_xml() throws Exception { 3 String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 4 "<!--\n" + 5 "\t== Copyright (c) 2002-2005. All rights reserved.\n" + 6 "\t== Financial Products Markup Language is subject to the FpML public license.\n" + 7 "\t== A copy of this license is available at http://www.fpml.org/documents/license\n" + 8 "-->\n" + 9 "<FpML version=\"4-2\" xmlns=\"http://www.fpml.org/2005/FpML-4-2\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.fpml.org/2005/FpML-4-2 fpml-main-4-2.xsd\" xsi:type=\"TradeCashflowsAsserted\">\n" +10 "\t<header>\n" +11 "\t\t<messageId messageIdScheme=\"http://www.example.com/messageId\">CEN/2004/01/05/15-38</messageId>\n" +12 "\t\t<sentBy>ABC</sentBy>\n" +13 "\t\t<sendTo>DEF</sendTo>\n" +14 "\t\t<creationTimestamp>2005-01-05T15:38:00-00:00</creationTimestamp>\n" +15 "\t</header>\n" +16 "\t<asOfDate>2005-01-05T15:00:00-00:00</asOfDate>\n" +17 "\t<tradeIdentifyingItems>\n" +18 "\t\t<partyTradeIdentifier>\n" +19 "\t\t\t<partyReference href=\"abc\"/>\n" +20 "\t\t\t<tradeId tradeIdScheme=\"http://www.abc.com/tradeId/\">trade1abcxxx</tradeId>\n" +21 "\t\t</partyTradeIdentifier>\n" +22 "\t\t<partyTradeIdentifier>\n" +23 "\t\t\t<partyReference href=\"def\"/>\n" +24 "\t\t\t<tradeId tradeIdScheme=\"http://www.def.com/tradeId/\">123cds</tradeId>\n" +25 "\t\t</partyTradeIdentifier>\n" +26 "\t</tradeIdentifyingItems>\n" +27 "\t<adjustedPaymentDate>2005-01-31</adjustedPaymentDate>\n" +28 "\t<netPayment>\n" +29 "\t\t<identifier netPaymentIdScheme=\"http://www.centralservice.com/netPaymentId\">netPaymentABCDEF001</identifier>\n" +30 "\t\t<payerPartyReference href=\"abc\"/>\n" +31 "\t\t<receiverPartyReference href=\"def\"/>\n" +32 "\t\t<paymentAmount>\n" +33 "\t\t\t<currency>EUR</currency>\n" +34 "\t\t\t<amount>200000</amount>\n" +35 "\t\t</paymentAmount>\n" +36 "\t</netPayment>\n" +

Page 110: Tests unitaires mock_kesako_20130516
Page 111: Tests unitaires mock_kesako_20130516

code complexe 1 /** 2 * 3 * @param xml : document xml représentant le swap 4 * @return objet Swap 5 */ 6 public Swap parse(String xml) { 7 Swap swap = new Swap(); 8 String currency = getNodeValue("/swap/currency", xml); 9 swap.setCurrency(currency);[...] /* beaucoup de code... */ 530 Date d = new Date(); 531 if(test == 1) { 532 if(d.after(spotDate)) { 533 swap.setType("IRS"); 534 } else { 535 swap.setType("CURVE"); 536 } 537 } else if (test == 2) { 538 if(d.after(spotDate)) { 539 swap.setType("IRS"); 540 } else { 541 swap.setType("CURVE"); 542 } 543 }[...] /* encore beaucoup de code... */1135 return swap;1136 }

Page 112: Tests unitaires mock_kesako_20130516

1 /** 2 * 3 * @param xml : document xml représentant le swap 4 * @return objet Swap 5 */ 6 public Swap parse(String xml) { 7 Swap swap = new Swap(); 8 String currency = getNodeValue("/swap/currency", xml); 9 swap.setCurrency(currency);[...] /* beaucoup de code... */ 530 Date d = new Date(); 531 if(test == 1) { 532 if(d.after(spotDate)) { 533 swap.setType("IRS"); 534 } else { 535 swap.setType("CURVE"); 536 } 537 } else if (test == 2) { 538 if(d.after(spotDate)) { 539 swap.setType("IRS"); 540 } else { 541 swap.setType("CURVE"); 542 } 543 }[...] /* encore beaucoup de code... */1135 return swap;1136 }

code complexe 531 if(test == 1) { 532 if(d.after(spotDate)) { 533 swap.setType("IRS"); 534 } else { 535 swap.setType("CURVE"); 536 } 537 } else if (test == 2) { 538 if(d.after(spotDate)) { 539 swap.setType("IRS"); 540 } else { 541 swap.setType("CURVE"); 542 } 543 }

EXTRACT METHOD !

Page 113: Tests unitaires mock_kesako_20130516

code complexe 1 public void updateSwapType(Swap swapToUpdate, Date now, Date spotDate, int test) { 2 if(test == 1) { 3 if(now.after(spotDate)) { 4 swapToUpdate.setType("IRS"); 5 } else { 6 swapToUpdate.setType("CURVE"); 7 } 8 } else if (test == 2) { 9 if(now.after(spotDate)) {10 swapToUpdate.setType("IRS");11 } else {12 swapToUpdate.setType("CURVE");13 }14 }15 }

Page 114: Tests unitaires mock_kesako_20130516

code complexe

1 @Test2 public void can_update_swap_type() throws Exception {3 Swap swap = new Swap();4 Date now = simpleDateFormat.parse("2012-06-15");5 Date before = simpleDateFormat.parse("2012-05-05");6 service.updateSwapType(swap, now, before, 1);7 assertEquals("IRS", swap.getType());8 }

Page 115: Tests unitaires mock_kesako_20130516

LE CODE DOIT ÊTRE MODULAIRE

Page 116: Tests unitaires mock_kesako_20130516

Singleton 1 public class ProductService { 2 3 private static ProductService instance = new ProductService(); 4 5 private DAOService daoService; 6 7 private ProductService() { 8 System.out.println("ProductService constructor"); 9 daoService = DAOService.getInstance();10 }11 12 public static ProductService getInstance() {13 return instance;14 }15 16 17 18 public Object getProduct(String id) {19 return daoService.getObject("product", id);20 }21 }

Page 117: Tests unitaires mock_kesako_20130516

1 public class ProductService { 2 3 private static ProductService instance = new ProductService(); 4 5 private DAOService daoService; 6 7 private ProductService() { 8 System.out.println("ProductService constructor"); 9 daoService = DAOService.getInstance();10 }11 12 public static ProductService getInstance() {13 return instance;14 }15 16 17 18 public Object getProduct(String id) {19 return daoService.getObject("product", id);20 }21 }

Singleton 3 private static ProductService instance = new ProductService();

Page 118: Tests unitaires mock_kesako_20130516

1 public class ProductService { 2 3 private static ProductService instance = new ProductService(); 4 5 private DAOService daoService; 6 7 private ProductService() { 8 System.out.println("ProductService constructor"); 9 daoService = DAOService.getInstance();10 }11 12 public static ProductService getInstance() {13 return instance;14 }15 16 17 18 public Object getProduct(String id) {19 return daoService.getObject("product", id);20 }21 }

Singleton 7 private ProductService() { 9 daoService = DAOService.getInstance();10 }

Page 119: Tests unitaires mock_kesako_20130516

Singleton 1 public class ProductService { 2 3 private static ProductService instance = new ProductService(); 4 5 private DAOService daoService; 6 7 private ProductService() { 8 System.out.println("ProductService constructor"); 9 daoService = DAOService.getInstance();10 }11 12 public static ProductService getInstance() {13 return instance;14 }15 16 17 18 public Object getProduct(String id) {19 return daoService.getObject("product", id);20 }21 }

Page 120: Tests unitaires mock_kesako_20130516

Singleton

Code

Page 121: Tests unitaires mock_kesako_20130516

Singleton

Code ProductService

Page 122: Tests unitaires mock_kesako_20130516

Singleton

Code ProductService DAOService

Page 123: Tests unitaires mock_kesako_20130516

Singleton

Code ProductService DAOService

Page 124: Tests unitaires mock_kesako_20130516

Singleton

Code ProductService DAOService

Page 125: Tests unitaires mock_kesako_20130516

Singleton

Code ProductService DAOService

MockProductService

Page 126: Tests unitaires mock_kesako_20130516

Singleton

1 public void validateSwap(String id) {2 Swap swap = (Swap) ProductService.getInstance().getProduct(id);3 swap.updateState("VALIDATE");4 ProductService.getInstance().save(swap);5 }

Page 127: Tests unitaires mock_kesako_20130516

1 public void validateSwap(String id) {2 Swap swap = (Swap) ProductService.getInstance().getProduct(id);3 swap.updateState("VALIDATE");4 ProductService.getInstance().save(swap);5 }

Singleton

ProductService.getInstance() 4 ProductService.getInstance()

COUPLAGE FORT

Page 128: Tests unitaires mock_kesako_20130516

Injection

1 private ProductService productService; 2 3 public void setProductService(ProductService injectedService) { 4 this.productService = injectedService; 5 } 6 7 public void validateSwap(String id) { 8 Swap swap = (Swap) productService.getProduct(id); 9 swap.updateState("VALIDATE");10 productService.save(swap);11 }

Page 129: Tests unitaires mock_kesako_20130516

1 private ProductService productService; 2 3 public void setProductService(ProductService injectedService) { 4 this.productService = injectedService; 5 } 6 7 public void validateSwap(String id) { 8 Swap swap = (Swap) productService.getProduct(id); 9 swap.updateState("VALIDATE");10 productService.save(swap);11 }

Injection

3 public void setProductService(ProductService injectedService) { 4 this.productService = injectedService; 5 }

INJECTION

Page 130: Tests unitaires mock_kesako_20130516

1 private ProductService productService; 2 3 public void setProductService(ProductService injectedService) { 4 this.productService = injectedService; 5 } 6 7 public void validateSwap(String id) { 8 Swap swap = (Swap) productService.getProduct(id); 9 swap.updateState("VALIDATE");10 productService.save(swap);11 }

Injection

8 Swap swap = (Swap) productService.getProduct(id);

UTILISATION

Page 131: Tests unitaires mock_kesako_20130516

Injection 1 @InjectMocks 2 private BankAccount bankAccount; 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap();10 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId");12 Mockito.doNothing().when(productService).save(swap);13 14 bankAccount.validateSwap("fakeId");15 16 assertEquals("VALIDATE", swap.getState());17 }

Page 132: Tests unitaires mock_kesako_20130516

1 @InjectMocks 2 private BankAccount bankAccount; 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap();10 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId");12 Mockito.doNothing().when(productService).save(swap);13 14 bankAccount.validateSwap("fakeId");15 16 assertEquals("VALIDATE", swap.getState());17 }

Injection 4 @Mock 5 private ProductService productService;

MOCK

Page 133: Tests unitaires mock_kesako_20130516

1 @InjectMocks 2 private BankAccount bankAccount; 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap();10 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId");12 Mockito.doNothing().when(productService).save(swap);13 14 bankAccount.validateSwap("fakeId");15 16 assertEquals("VALIDATE", swap.getState());17 }

Injection 1 @InjectMocks 2 private BankAccount bankAccount;

INJECTION AUTOMATIQUE DES MOCKS

Page 134: Tests unitaires mock_kesako_20130516

1 @InjectMocks 2 private BankAccount bankAccount; 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap();10 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId");12 Mockito.doNothing().when(productService).save(swap);13 14 bankAccount.validateSwap("fakeId");15 16 assertEquals("VALIDATE", swap.getState());17 }

Injection 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId");12 Mockito.doNothing().when(productService).save(swap);

Page 135: Tests unitaires mock_kesako_20130516

1 @InjectMocks 2 private BankAccount bankAccount; 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap();10 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId");12 Mockito.doNothing().when(productService).save(swap);13 14 bankAccount.validateSwap("fakeId");15 16 assertEquals("VALIDATE", swap.getState());17 }

14 bankAccount.validateSwap("fakeId");

Injection

Page 136: Tests unitaires mock_kesako_20130516

Injection 1 @InjectMocks 2 private BankAccount bankAccount; 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap();10 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId");12 Mockito.doNothing().when(productService).save(swap);13 14 bankAccount.validateSwap("fakeId");15 16 assertEquals("VALIDATE", swap.getState());17 }

16 assertEquals("VALIDATE", swap.getState());

Page 137: Tests unitaires mock_kesako_20130516

YODA (C) DISNEY

Page 138: Tests unitaires mock_kesako_20130516

UTILISE L’INJECTION, LUKE

YODA (C) DISNEY

Page 139: Tests unitaires mock_kesako_20130516

Sans injecteur ?

1 public void validateSwap(String id) {2 Swap swap = (Swap) ProductService.getInstance().getProduct(id);3 swap.updateState("VALIDATE");4 ProductService.getInstance().save(swap);5 }

Page 140: Tests unitaires mock_kesako_20130516

1 public void validateSwap(String id) {2 Swap swap = (Swap) ProductService.getInstance().getProduct(id);3 swap.updateState("VALIDATE");4 ProductService.getInstance().save(swap);5 }

Sans injecteur ?

ProductService.getInstance() 4 ProductService.getInstance()

EXTRACT METHOD !

Page 141: Tests unitaires mock_kesako_20130516

1 public ProductService getProductService() {2 return ProductService.getInstance();3 }4 5 public void validateSwap(String id) {6 Swap swap = (Swap) getProductService().getProduct(id);7 swap.updateState("VALIDATE");8 getProductService().save(swap);9 }

Sans injecteur ?

1 public ProductService getProductService() {2 return ProductService.getInstance();3 } getProductService() 8 getProductService()

Page 142: Tests unitaires mock_kesako_20130516

Sans injecteur ? 1 @Spy 2 private BankAccount bankAccount = new BankAccount("", 23, "", 3); 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap();10 11 Mockito.doReturn(productService).when(bankAccount).getProductService();12 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId");14 Mockito.doNothing().when(productService).save(swap);15 16 bankAccount.validateSwap("fakeId");17 18 assertEquals("VALIDATE", swap.getState());19 }

Page 143: Tests unitaires mock_kesako_20130516

1 @Spy 2 private BankAccount bankAccount = new BankAccount("", 23, "", 3); 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap();10 11 Mockito.doReturn(productService).when(bankAccount).getProductService();12 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId");14 Mockito.doNothing().when(productService).save(swap);15 16 bankAccount.validateSwap("fakeId");17 18 assertEquals("VALIDATE", swap.getState());19 }

Sans injecteur ? 1 @Spy 2 private BankAccount bankAccount = new BankAccount("", 23, "", 3);

REDÉFINITION DES MÉTHODESPOSSIBLE

Page 144: Tests unitaires mock_kesako_20130516

1 @Spy 2 private BankAccount bankAccount = new BankAccount("", 23, "", 3); 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap();10 11 Mockito.doReturn(productService).when(bankAccount).getProductService();12 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId");14 Mockito.doNothing().when(productService).save(swap);15 16 bankAccount.validateSwap("fakeId");17 18 assertEquals("VALIDATE", swap.getState());19 }

Sans injecteur ? 11 Mockito.doReturn(productService).when(bankAccount).getProductService();

Page 145: Tests unitaires mock_kesako_20130516

1 @Spy 2 private BankAccount bankAccount = new BankAccount("", 23, "", 3); 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap();10 11 Mockito.doReturn(productService).when(bankAccount).getProductService();12 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId");14 Mockito.doNothing().when(productService).save(swap);15 16 bankAccount.validateSwap("fakeId");17 18 assertEquals("VALIDATE", swap.getState());19 }

Sans injecteur ? 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId");14 Mockito.doNothing().when(productService).save(swap);

Page 146: Tests unitaires mock_kesako_20130516

Sans injecteur ? 1 @Spy 2 private BankAccount bankAccount = new BankAccount("", 23, "", 3); 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap();10 11 Mockito.doReturn(productService).when(bankAccount).getProductService();12 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId");14 Mockito.doNothing().when(productService).save(swap);15 16 bankAccount.validateSwap("fakeId");17 18 assertEquals("VALIDATE", swap.getState());19 }

16 bankAccount.validateSwap("fakeId");

Page 147: Tests unitaires mock_kesako_20130516

Sans injecteur ? 1 @Spy 2 private BankAccount bankAccount = new BankAccount("", 23, "", 3); 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap();10 11 Mockito.doReturn(productService).when(bankAccount).getProductService();12 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId");14 Mockito.doNothing().when(productService).save(swap);15 16 bankAccount.validateSwap("fakeId");17 18 assertEquals("VALIDATE", swap.getState());19 }

18 assertEquals("VALIDATE", swap.getState());

Page 148: Tests unitaires mock_kesako_20130516

Avertissement

Page 149: Tests unitaires mock_kesako_20130516

LANCER UN TEST DOIT ÊTRE FACILE

Page 150: Tests unitaires mock_kesako_20130516

Tests dans son IDEECLIPSE

NETBEANS

INTELLIJ

Page 151: Tests unitaires mock_kesako_20130516

LE CODE DOIT TOUJOURS ÊTRE DÉPLOYABLE

Page 152: Tests unitaires mock_kesako_20130516

Intégration continue

mvn install

Page 153: Tests unitaires mock_kesako_20130516

Intégration continue

[INFO] ---------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ---------------------------------------------

Page 154: Tests unitaires mock_kesako_20130516

Intégration continue

mvn install

Page 155: Tests unitaires mock_kesako_20130516

Intégration continue

[INFO] ---------------------------------------------

[INFO] BUILD FAILURE

[INFO] ---------------------------------------------

Page 156: Tests unitaires mock_kesako_20130516

Intégration continue

[INFO] ---------------------------------------------

[INFO] BUILD FAILURE

[INFO] ---------------------------------------------

WORKS ON

MY

MACHINE

Page 157: Tests unitaires mock_kesako_20130516

Intégration continue

Déclenchement d’un build

Page 158: Tests unitaires mock_kesako_20130516

Intégration continue

Déclenchement d’un build Compilation

Page 159: Tests unitaires mock_kesako_20130516

Intégration continue

Déclenchement d’un build Compilation Test

Page 160: Tests unitaires mock_kesako_20130516

Intégration continue

Déclenchement d’un build Compilation Test

Déploiement

Analyse de code

Page 161: Tests unitaires mock_kesako_20130516
Page 162: Tests unitaires mock_kesako_20130516

AVOIR LA BONNE COUVERTURE

Page 163: Tests unitaires mock_kesako_20130516

80%DE COUVERTURE DE CODE

Page 164: Tests unitaires mock_kesako_20130516

80%DE COUVERTURE DE GETTER/SETTER

Page 165: Tests unitaires mock_kesako_20130516

TRAVAILLER EN BINÔME

Page 166: Tests unitaires mock_kesako_20130516

binomage (pair hero)

philosophie différente pour code identique

HTTP://WWW.SXC.HU/PHOTO/959091

Page 167: Tests unitaires mock_kesako_20130516

binomage (pair hero)

philosophie différente pour code identiqueLES COMMANDES

Page 168: Tests unitaires mock_kesako_20130516

binomage (pair hero)

philosophie différente pour code identique

LE PLAN DE VOL

Page 169: Tests unitaires mock_kesako_20130516

Ping Pong

Page 170: Tests unitaires mock_kesako_20130516

J’écris le test

Page 171: Tests unitaires mock_kesako_20130516

Il écrit l’implémentation

Page 172: Tests unitaires mock_kesako_20130516

J’écris le test

Page 173: Tests unitaires mock_kesako_20130516

Il écrit l’implémentation

Page 174: Tests unitaires mock_kesako_20130516

bref

Page 175: Tests unitaires mock_kesako_20130516

j’ai binômé

Page 176: Tests unitaires mock_kesako_20130516

6 mois plus tard...

Page 177: Tests unitaires mock_kesako_20130516

Bugs

0

22,5

45

67,5

90

Janvier Février Mars Avril Mai Juin

Bugs Satisfaction

Page 178: Tests unitaires mock_kesako_20130516

Bugs

0

22,5

45

67,5

90

Janvier Février Mars Avril Mai Juin

Bugs Satisfaction

Page 179: Tests unitaires mock_kesako_20130516

Bugs

0

22,5

45

67,5

90

Janvier Février Mars Avril Mai Juin

Bugs Satisfaction

Page 180: Tests unitaires mock_kesako_20130516

Bugs

0

22,5

45

67,5

90

Janvier Février Mars Avril Mai Juin

Bugs Satisfaction

Page 181: Tests unitaires mock_kesako_20130516

Bugs

0

22,5

45

67,5

90

Janvier Février Mars Avril Mai Juin

Bugs Satisfaction

Page 182: Tests unitaires mock_kesako_20130516

Bugs

0

22,5

45

67,5

90

Janvier Février Mars Avril Mai Juin

Bugs Satisfaction

Page 183: Tests unitaires mock_kesako_20130516

BRAVO À NOTRE ÉQUIPE DE CHOC !

Page 184: Tests unitaires mock_kesako_20130516

(POUR RÉSUMER)

Page 185: Tests unitaires mock_kesako_20130516

Installez Jenkins

Page 186: Tests unitaires mock_kesako_20130516

Automatisez votre build

Page 187: Tests unitaires mock_kesako_20130516

Écrivez votre 1er test

Page 188: Tests unitaires mock_kesako_20130516

(même si il est «trop» simple)

Page 189: Tests unitaires mock_kesako_20130516

HTTP://WWW.SXC.HU/PHOTO/664214

IL FAUT APPRENDRE À NAGER...

Page 190: Tests unitaires mock_kesako_20130516

...AVANT DE GAGNER DES COMPÉTITIONS

HTTP://WWW.SXC.HU/PHOTO/1008962

Page 191: Tests unitaires mock_kesako_20130516

( DEMO )

Page 193: Tests unitaires mock_kesako_20130516

Merci !

Page 194: Tests unitaires mock_kesako_20130516

It’s Pizza Time !Drink

Page 195: Tests unitaires mock_kesako_20130516

@DWURSTEISEN

Page 196: Tests unitaires mock_kesako_20130516

référence

jenkins : http://jenkins-ci.org/

assertj : https://github.com/joel-costigliola/assertj

mockito : https://code.google.com/p/mockito/

démo : http://parleys.com/play/5148922a0364bc17fc56c85a/about