Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Conf soat tests_unitaires_Mockito_jUnit_170113

0 views

Published on

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 ? Si c’est le cas, suivez David dans la quête du Test Driven Development. Nous rencontrerons pléthore d'ennemies contre lesquels nous aurons à combattre : bugs, complexité, code statique, couplage fort. Ils essaieront de nous barrer la route, mais heureusement, nous pourrons compter sur nos alliés jUnit, Mockito, refactoring et injection/dépendance

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Conf soat tests_unitaires_Mockito_jUnit_170113

  1. 1. Test unitaire ? Mock ? TDD ? Kezako ?01/26/13 1
  2. 2. Nouveau client !
  3. 3. Nouveau projet !
  4. 4. LEGACY CODEHTTP://UPLOAD.WIKIMEDIA.ORG/WIKIPEDIA/COMMONS/THUMB/6/69/HUMAN_EVOLUTION.SVG/1000PX-HUMAN_EVOLUTION.SVG.PNG
  5. 5. 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; }
  6. 6. 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"); 1000 534 535 } else { swap.setType("CURVE"); LIGNES ! 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 }
  7. 7. La documentation a raison1 /**2 * Always returns true.3 */4 public boolean isAvailable() {5 return false;6 }
  8. 8. La documentation a raison1 /**2 * Always returns true.3 */4 public boolean isAvailable() { WTF ?!?5 return false;6 }
  9. 9. fiableLa documentation n’est plus une aide utile
  10. 10. Faire du code qui marche1 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 }
  11. 11. Faire du code qui marche1 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 }
  12. 12. Faire du code qui marche1 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 } NullPointerException !
  13. 13. Code simple 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 }HTTP://EN.WIKIPEDIA.ORG/WIKI/FILE:JEU_DE_MIKADO.JPG
  14. 14. Code simple 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 }HTTP://EN.WIKIPEDIA.ORG/WIKI/FILE:JEU_DE_MIKADO.JPG
  15. 15. Code simple 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 }HTTP://EN.WIKIPEDIA.ORG/WIKI/FILE:JEU_DE_MIKADO.JPG
  16. 16. simpleC’est compliqué de faire un test une évolution
  17. 17. Bonne nouvelle !
  18. 18. Je vous prend dans mon équipe !
  19. 19. COMMENT VAT’ON POUVOIRS’EN SORTIR ? HTTP://WWW.SXC.HU/PROFILE/HOTBLACK
  20. 20. TEST DRIVEN DEVELOPMENTHTTP://UPLOAD.WIKIMEDIA.ORG/WIKIPEDIA/COMMONS/THUMB/6/69/HUMAN_EVOLUTION.SVG/1000PX-HUMAN_EVOLUTION.SVG.PNG
  21. 21. PRINCIPE DE BASE
  22. 22. Ecrituredu test
  23. 23. Ecriture Lancementdu test du test
  24. 24. Correction de l’implémentation KOEcriture Lancementdu test du test
  25. 25. Correction de l’implémentation KOEcriture Lancementdu test du test OK Fin
  26. 26. Correction de l’implémentation KOEcriture Lancementdu test du test OK Fin REFACTOR
  27. 27. Toujours faire le test cassant avantle test passant(pour tester le test)
  28. 28. TEST UNITAIREtester la plus petite unité de code possible
  29. 29. SIM PLETEST UNITAIREtester la plus petite unité de code possible
  30. 30. SIM FEE PLE DBATEST UNITAIRE CKtester la plus petite unité de code possible
  31. 31. SIM FEE PLE DBA COÛTEST UNITAIRE CKtester la plus petite unité de code possible T
  32. 32. $40MIL 0 LIO NS
  33. 33. EXEMPLE
  34. 34. Test d’abord !1 @Test2 public void can_deposit() {3 bankAccount.setBalance(50);45 boolean result = bankAccount.deposit(1000);67 assertTrue(result);8 assertEquals(1050, bankAccount.getBalance());9 }
  35. 35. Test d’abord !1 @Test2 public void can_deposit() {3 bankAccount.setBalance(50);45 boolean result = bankAccount.deposit(1000);67 assertTrue(result);8 assertEquals(1050, bankAccount.getBalance());9 }
  36. 36. Test d’abord !1 @Test2 public void can_deposit() {3 bankAccount.setBalance(50);45 boolean result = bankAccount.deposit(1000);67 assertTrue(result);8 assertEquals(1050, bankAccount.getBalance());9 }
  37. 37. Test d’abord !1 @Test2 public void can_deposit() {3 bankAccount.setBalance(50);45 boolean result = bankAccount.deposit(1000);67 assertTrue(result);8 assertEquals(1050, bankAccount.getBalance());9 }
  38. 38. Test d’abord !1 boolean deposit(int amount) {2 return false;3 }
  39. 39. Test d’abord !1 boolean deposit(int amount) {2 return false;3 }
  40. 40. Test d’abord !1 boolean deposit(int amount) {2 bal = bal + amount;3 return true;4 }
  41. 41. Test d’abord !1 boolean deposit(int amount) {2 bal = bal + amount;3 return true;4 }
  42. 42. Test d’abord !1 @Test2 public void cant_deposit_with_negative_amount() {3 bankAccount.setBalance(100);45 boolean result = bankAccount.deposit(-20);67 assertFalse(result);8 assertEquals(100, bankAccount.getBalance());9 }
  43. 43. Test d’abord !1 @Test2 public void cant_deposit_with_negative_amount() {3 bankAccount.setBalance(100);45 boolean result = bankAccount.deposit(-20);67 assertFalse(result);8 assertEquals(100, bankAccount.getBalance());9 }
  44. 44. Test d’abord !1 @Test2 public void cant_deposit_with_negative_amount() {3 bankAccount.setBalance(100);45 boolean result = bankAccount.deposit(-20);67 assertFalse(result);8 assertEquals(100, bankAccount.getBalance());9 }
  45. 45. Test d’abord !1 @Test2 public void cant_deposit_with_negative_amount() {3 bankAccount.setBalance(100);45 boolean result = bankAccount.deposit(-20);67 assertFalse(result);8 assertEquals(100, bankAccount.getBalance());9 }
  46. 46. Test d’abord !1 boolean deposit(int amount) {2 bal = bal + amount;3 return true;4 }
  47. 47. Test d’abord !1 boolean deposit(int amount) {2 bal = bal + amount;3 return true;4 }
  48. 48. Test d’abord !1 boolean deposit(int amount) {2 if(amount < 0) {3 return false;4 }5 bal = bal + amount;6 return true;7 }
  49. 49. Test d’abord !1 boolean deposit(int amount) {2 if(amount < 0) {3 return false;4 }5 bal = bal + amount;6 return true;7 }
  50. 50. Acteur / Action / Assertion
  51. 51. les «3 A» : Acteur/Action/Assertion1 @Test2 public void cant_deposit_with_negative_amount() {3 bankAccount.setBalance(100);45 boolean result = bankAccount.deposit(-20);67 assertFalse(result);8 assertEquals(100, bankAccount.getBalance());9 }
  52. 52. les «3 A» : Acteur/Action/Assertion1 @Test2 public void cant_deposit_with_negative_amount() {3 bankAccount.setBalance(100);45 boolean result = bankAccount.deposit(-20);6 Acteur7 assertFalse(result);8 assertEquals(100, bankAccount.getBalance());9 }
  53. 53. les «3 A» : Acteur/Action/Assertion1 @Test2 public void cant_deposit_with_negative_amount() {3 bankAccount.setBalance(100);45 boolean result = bankAccount.deposit(-20);6 Action7 assertFalse(result);8 assertEquals(100, bankAccount.getBalance());9 }
  54. 54. les «3 A» : Acteur/Action/Assertion1 @Test2 public void cant_deposit_with_negative_amount() {3 bankAccount.setBalance(100);45 boolean result = bankAccount.deposit(-20);6 Assertions7 assertFalse(result);8 assertEquals(100, bankAccount.getBalance());9 }
  55. 55. KISS
  56. 56. KISSKEEP IT SIMPLE (AND STUPID)
  57. 57. KISSKEEP IT SIMPLE (AND STUPID)
  58. 58. 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());1314 } 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 }3031 LOGGER.info("======= testGetCustomerOK done.");32 }
  59. 59. 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());1314 } 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 }3031 LOGGER.info("======= testGetCustomerOK done.");32 }
  60. 60. 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());1314 } catch (CustomerBusinessException exception) {15 LOGGER.error("CustomerBusinessException : {}",16 exception.getCause());17 Assert.fail(exception.getMessage());18 } catch (UnavailableResourceException exception) {19 LOGGER.error("UnavailableResourceException : {}", BRUIT20 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 }3031 LOGGER.info("======= testGetCustomerOK done.");32 }
  61. 61. 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 }
  62. 62. EN PRATIQUEHTTP://UPLOAD.WIKIMEDIA.ORG/WIKIPEDIA/COMMONS/THUMB/6/69/HUMAN_EVOLUTION.SVG/1000PX-HUMAN_EVOLUTION.SVG.PNG
  63. 63. VENIR ARMÉ
  64. 64. JUNIT + MOCKITO + FEST-ASSERT
  65. 65. JUNIT + MOCKITO + FEST-ASSERT
  66. 66. Mock ?simulacrese fait passer pour ce qu’iln’est pascomportementparamétrable
  67. 67. MOCKITO
  68. 68. doReturn(new BankAccount()).when(daoService).getObject("product", "id");
  69. 69. doReturn(new BankAccount()) BankAccount()).when(daoService).getObject("product", "id");
  70. 70. doReturn(new BankAccount()).when(daoService).getObject("product", "id"); when(daoService)
  71. 71. doReturn(new BankAccount()).when(daoService).getObject("product", "id"); getObject("product",
  72. 72. doThrow(IOException.class).when(daoService).getObject("product", "id");
  73. 73. doThrow(IOException.class).when(daoService).getObject("product", "id");doThrow(IOException.class)
  74. 74. doThrow(IOException.class).when(daoService).getObject("product", "id"); when(daoService)
  75. 75. doThrow(IOException.class).when(daoService).getObject("product", "id"); getObject("product",
  76. 76. FEST-ASSERT
  77. 77. assertThat(age).isGreaterThan(5);
  78. 78. assertThat(myList).containsExactly("MONAD42", "META18")
  79. 79. NOUVEAU CODE = NOUVEAU TEST
  80. 80. NOUVEAU BUG = NOUVEAU TEST
  81. 81. nouveau bug = nouveau test1 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 }
  82. 82. nouveau bug = nouveau test1 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 } LE BUG EST ICI !
  83. 83. nouveau bug = nouveau test1 @Test2 public void can_return_null_when_ioexception() throws IOException {3 Mockito.doThrow(IOException.class)4 .when(daoService).getObject("product", "azerty");56 Object product = service.getProduct("azerty");78 assertThat(product).isNull();9 }
  84. 84. nouveau bug = nouveau test1 @Test2 public void can_return_null_when_ioexception() throws IOException {3 Mockito.doThrow(IOException.class)4 .when(daoService).getObject("product", "azerty");56 Object product = service.getProduct("azerty");78 assertThat(product).isNull();9 }
  85. 85. nouveau bug = nouveau test1 @Test2 public void can_return_null_when_ioexception() throws IOException {3 Mockito.doThrow(IOException.class)4 .when(daoService).getObject("product", "azerty");56 Object product = service.getProduct("azerty");78 assertThat(product).isNull();9 }
  86. 86. nouveau bug = nouveau test1 @Test2 public void can_return_null_when_ioexception() throws IOException {3 Mockito.doThrow(IOException.class)4 .when(daoService).getObject("product", "azerty");56 Object product = service.getProduct("azerty");78 assertThat(product).isNull();9 }
  87. 87. nouveau bug = nouveau test1 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 }
  88. 88. nouveau bug = nouveau test1 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 }
  89. 89. nouveau bug = nouveau test1 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 } LE BUG EST TOUJOURS ICI !
  90. 90. nouveau bug = nouveau test1 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 }
  91. 91. nouveau bug = nouveau test1 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 }
  92. 92. Laissez votre câble tranquille
  93. 93. TESTER DOIT ÊTRE SIMPLE
  94. 94. 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 }
  95. 95. 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/licensen" + 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 "tt<messageId messageIdScheme="http://www.example.com/messageId">CEN/2004/01/05/15-38</messageId>n"+12 "tt<sentBy>ABC</sentBy>n" +13 "tt<sendTo>DEF</sendTo>n" +14 "tt<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 "tt<partyTradeIdentifier>n" +19 "ttt<partyReference href="abc"/>n" +20 "ttt<tradeId tradeIdScheme="http://www.abc.com/tradeId/">trade1abcxxx</tradeId>n" +21 "tt</partyTradeIdentifier>n" +22 "tt<partyTradeIdentifier>n" +23 "ttt<partyReference href="def"/>n" +24 "ttt<tradeId tradeIdScheme="http://www.def.com/tradeId/">123cds</tradeId>n" +25 "tt</partyTradeIdentifier>n" +26 "t</tradeIdentifyingItems>n" +27 "t<adjustedPaymentDate>2005-01-31</adjustedPaymentDate>n" +28 "t<netPayment>n" +29 "tt<identifier netPaymentIdScheme="http://www.centralservice.com/netPaymentId">netPaymentABCDEF001</identifier>n" +30 "tt<payerPartyReference href="abc"/>n" +31 "tt<receiverPartyReference href="def"/>n" +32 "tt<paymentAmount>n" +
  96. 96. 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 }
  97. 97. 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 { EXTRACT METHOD ! 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 }
  98. 98. 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 }
  99. 99. code complexe1 @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 }
  100. 100. LE CODE DOIT ÊTRE MODULAIRE
  101. 101. 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 }
  102. 102. 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 }
  103. 103. 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 }
  104. 104. 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 }
  105. 105. Singleton Code
  106. 106. Singleton Code ProductService
  107. 107. Singleton Code ProductService DAOService
  108. 108. Singleton Code ProductService DAOService
  109. 109. Singleton Code ProductService DAOService
  110. 110. Singleton Mock ProductService Code ProductService DAOService
  111. 111. Singleton1 public void validateSwap(String id) {2 Swap swap = (Swap) ProductService.getInstance().getProduct(id);3 swap.updateState("VALIDATE");4 ProductService.getInstance().save(swap);5 }
  112. 112. Singleton1 public void validateSwap(String id) {2 Swap swap = (Swap) ProductService.getInstance() ProductService.getInstance().getProduct(id);3 swap.updateState("VALIDATE");4 ProductService.getInstance() ProductService.getInstance().save(swap);5 } COUPLAGE FORT
  113. 113. 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 }
  114. 114. Injection 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 }
  115. 115. 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 } UTILISATION
  116. 116. 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();1011 Mockito.doReturn(swap).when(productService).getProduct("fakeId");12 Mockito.doNothing().when(productService).save(swap);1314 bankAccount.validateSwap("fakeId");1516 assertEquals("VALIDATE", swap.getState());17 }
  117. 117. Injection 1 @InjectMocks 2 private BankAccount bankAccount; 3 4 5 @Mock private ProductService productService; MOCK 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap();1011 Mockito.doReturn(swap).when(productService).getProduct("fakeId");12 Mockito.doNothing().when(productService).save(swap);1314 bankAccount.validateSwap("fakeId");1516 assertEquals("VALIDATE", swap.getState());17 }
  118. 118. Injection 1 @InjectMocks INJECTION AUTOMATIQUE 2 private BankAccount bankAccount; 3 DES MOCKS 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap();1011 Mockito.doReturn(swap).when(productService).getProduct("fakeId");12 Mockito.doNothing().when(productService).save(swap);1314 bankAccount.validateSwap("fakeId");1516 assertEquals("VALIDATE", swap.getState());17 }
  119. 119. 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();1011 Mockito.doReturn(swap).when(productService).getProduct("fakeId");12 Mockito.doNothing().when(productService).save(swap);1314 bankAccount.validateSwap("fakeId");1516 assertEquals("VALIDATE", swap.getState());17 }
  120. 120. 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();1011 Mockito.doReturn(swap).when(productService).getProduct("fakeId");12 Mockito.doNothing().when(productService).save(swap);1314 bankAccount.validateSwap("fakeId");1516 assertEquals("VALIDATE", swap.getState());17 }
  121. 121. 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();1011 Mockito.doReturn(swap).when(productService).getProduct("fakeId");12 Mockito.doNothing().when(productService).save(swap);1314 bankAccount.validateSwap("fakeId");1516 assertEquals("VALIDATE", swap.getState());17 }
  122. 122. YODA (C) DISNEY
  123. 123. UTILISE L’INJECTION, LUKEYODA (C) DISNEY
  124. 124. 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 }
  125. 125. Sans injecteur ? EXTRACT METHOD !1 public void validateSwap(String id) {2 Swap swap = (Swap) ProductService.getInstance() ProductService.getInstance().getProduct(id);3 swap.updateState("VALIDATE");4 ProductService.getInstance() ProductService.getInstance().save(swap);5 }
  126. 126. Sans injecteur ?1 public ProductService getProductService() {2 return ProductService.getInstance();3 }45 public void validateSwap(String id) {6 Swap swap = (Swap) getProductService() getProductService().getProduct(id);7 swap.updateState("VALIDATE");8 getProductService() getProductService().save(swap);9 }
  127. 127. 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();1011 Mockito.doReturn(productService).when(bankAccount).getProductService();1213 Mockito.doReturn(swap).when(productService).getProduct("fakeId");14 Mockito.doNothing().when(productService).save(swap);1516 bankAccount.validateSwap("fakeId");1718 assertEquals("VALIDATE", swap.getState());19 }
  128. 128. Sans injecteur ? 1 @Spy 2 private BankAccount bankAccount = new BankAccount("", 23, "", 3); 3 4 @Mock 5 private ProductService productService; 6 7 @Test REDÉFINITION DES MÉTHODES 8 9 public void can_validate_swap() { Swap swap = new Swap(); POSSIBLE1011 Mockito.doReturn(productService).when(bankAccount).getProductService();1213 Mockito.doReturn(swap).when(productService).getProduct("fakeId");14 Mockito.doNothing().when(productService).save(swap);1516 bankAccount.validateSwap("fakeId");1718 assertEquals("VALIDATE", swap.getState());19 }
  129. 129. 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();1011 Mockito.doReturn(productService).when(bankAccount).getProductService();1213 Mockito.doReturn(swap).when(productService).getProduct("fakeId");14 Mockito.doNothing().when(productService).save(swap);1516 bankAccount.validateSwap("fakeId");1718 assertEquals("VALIDATE", swap.getState());19 }
  130. 130. 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();1011 Mockito.doReturn(productService).when(bankAccount).getProductService();1213 Mockito.doReturn(swap).when(productService).getProduct("fakeId");14 Mockito.doNothing().when(productService).save(swap);1516 bankAccount.validateSwap("fakeId");1718 assertEquals("VALIDATE", swap.getState());19 }
  131. 131. 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();1011 Mockito.doReturn(productService).when(bankAccount).getProductService();1213 Mockito.doReturn(swap).when(productService).getProduct("fakeId");14 Mockito.doNothing().when(productService).save(swap);1516 bankAccount.validateSwap("fakeId");1718 assertEquals("VALIDATE", swap.getState());19 }
  132. 132. 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();1011 Mockito.doReturn(productService).when(bankAccount).getProductService();1213 Mockito.doReturn(swap).when(productService).getProduct("fakeId");14 Mockito.doNothing().when(productService).save(swap);1516 bankAccount.validateSwap("fakeId");1718 assertEquals("VALIDATE", swap.getState());19 }
  133. 133. m e n t rt is s eA v e
  134. 134. Singleton ? 1 public class ProductService { 2 3 private static ProductService instance = new ProductService(); 4 5 private ProductService() { 6 7 } 8 9 public static ProductService getInstance() {10 return instance;11 }12 }
  135. 135. Singleton ? 1 public class ProductService { 2 3 private static ProductService instance = new ProductService(); 4 5 private ProductService() { 6 CRÉATION DE L’INSTANCE 7 } 8 AU CHARGEMENT DE LA CLASS 9 public static ProductService getInstance() {10 return instance;11 }12 }
  136. 136. Singleton ? 1 public class ProductService { 2 3 private static ProductService instance = new ProductService(); 4 5 private ProductService() { INSTANCIATION IMPOSSIBLE 6 7 } 8 9 public static ProductService getInstance() {10 return instance;11 }12 }
  137. 137. Singleton ? 1 public class ProductService { 2 3 private static ProductService instance = null; 4 5 public ProductService() { CONSTRUCTEUR PUBLIC 6 7 } 8 9 public static ProductService getInstance() {10 if(instance == null) {11 instance = new ProductService();12 }13 return instance;14 }15 }
  138. 138. Singleton ? 1 public class ProductService { 2 3 private static ProductService instance = null; 4 5 public ProductService() { 6 7 } 8 9 public static ProductService getInstance() {10 if(instance == null) {11 instance = new ProductService();12 } CHARGEMENT TARDIF13 return instance;14 }15 }
  139. 139. Singleton ? 1 public class ProductService { 2 3 private static ProductService instance = new ProductService(); 4 5 private ProductService() { 6 7 } 8 9 public static ProductService getInstance() {10 return instance;11 }12 }
  140. 140. Singleton ? 1 public class ProductService implements IProductService { 2 3 private static IProductService instance = new ProductService(); 4 5 private ProductService() { 6 7 } 8 9 public static IProductService getInstance() {10 return instance;11 }12 } NIVEAU SUPPLÉMENTAIRE VIA UNE INTERFACE
  141. 141. LANCER UN TEST DOIT ÊTRE FACILE
  142. 142. Tests dans son IDE INT ELL ECL IJ IPS E NET BEA NS
  143. 143. LE CODE DOIT TOUJOURS ÊTRE DÉPLOYABLE
  144. 144. Intégration continuemvn install
  145. 145. Intégration continue[INFO] ---------------------------------------------[INFO] BUILD SUCCESS[INFO] ---------------------------------------------
  146. 146. Intégration continuemvn install
  147. 147. Intégration continue[INFO] ---------------------------------------------[INFO] BUILD FAILURE[INFO] ---------------------------------------------
  148. 148. Intégration continue O N K S R O Y W M[INFO] --------------------------------------------- E IN[INFO] BUILD FAILURE CH[INFO] --------------------------------------------- MA
  149. 149. Intégration continueDéclenchement d’un build
  150. 150. Intégration continueDéclenchement Compilation d’un build
  151. 151. Intégration continueDéclenchement Compilation Test d’un build
  152. 152. Intégration continue DéploiementDéclenchement Compilation Test d’un build Analyse de code
  153. 153. AVOIR LA BONNE COUVERTURE
  154. 154. 80%DE COUVERTURE DE CODE
  155. 155. 80%DE COUVERTURE DE GETTER/SETTER
  156. 156. TRAVAILLER EN BINÔME
  157. 157. binomage (pair hero) philosophie différente pour code identiqueHTTP://WWW.SXC.HU/PHOTO/959091
  158. 158. binomage (pair hero) D E S MA N C O M LE Sphilosophie différente pour code identique
  159. 159. binomage (pair hero) LE PLA ND EVphilosophie différente pour code identique OL
  160. 160. Ping Pong
  161. 161. J’écris le test
  162. 162. Il écrit l’implémentation
  163. 163. J’écris le test
  164. 164. Il écrit l’implémentation
  165. 165. bref
  166. 166. j’ai binômé
  167. 167. 6 mois plus tard...
  168. 168. Bugs Bugs Satisfaction 90 67,5 45 22,5 0 Janvier Février Mars Avril Mai Juin
  169. 169. Bugs Bugs Satisfaction 90 67,5 45 22,5 0 Janvier Février Mars Avril Mai Juin
  170. 170. Bugs Bugs Satisfaction 90 67,5 45 22,5 0 Janvier Février Mars Avril Mai Juin
  171. 171. Bugs Bugs Satisfaction 90 67,5 45 22,5 0 Janvier Février Mars Avril Mai Juin
  172. 172. Bugs Bugs Satisfaction 90 67,5 45 22,5 0 Janvier Février Mars Avril Mai Juin
  173. 173. Bugs Bugs Satisfaction 90 67,5 45 22,5 0 Janvier Février Mars Avril Mai Juin
  174. 174. BRAVO À NOTRE ÉQUIPE DE CHOC !
  175. 175. (POUR RÉSUMER)
  176. 176. Installez Jenkins
  177. 177. Automatisez votre build
  178. 178. Écrivez votre 1er test
  179. 179. (même si il est «trop» simple)
  180. 180. HTTP://WWW.SXC.HU/PHOTO/664214IL FAUT APPRENDRE À NAGER...
  181. 181. HTTP://WWW.SXC.HU/PHOTO/1008962...AVANT DE GAGNER DES COMPÉTITIONS
  182. 182. ( DEMO )
  183. 183. QUESTIONS ?HTTP://UPLOAD.WIKIMEDIA.ORG/WIKIPEDIA/COMMONS/THUMB/6/69/HUMAN_EVOLUTION.SVG/1000PX-HUMAN_EVOLUTION.SVG.PNG
  184. 184. @DWURSTEISEN

×