Test unitaire ?           Mock ? TDD ?             Kezako ?01/26/13                             1
Nouveau client !
Nouveau projet !
LEGACY CODEHTTP://UPLOAD.WIKIMEDIA.ORG/WIKIPEDIA/COMMONS/THUMB/6/69/HUMAN_EVOLUTION.SVG/1000PX-HUMAN_EVOLUTION.SVG.PNG
La documentation explique le code        /**          *          * @param xml : document xml représentant le swap         ...
La documentation explique le code               1    /**               2      *               3      * @param xml : docume...
La documentation a raison1        /**2        * Always returns true.3        */4      public boolean isAvailable() {5     ...
La documentation a raison1        /**2        * Always returns true.3        */4      public boolean isAvailable() {      ...
fiableLa documentation n’est plus une aide                            utile
Faire du code qui marche1    public Object getProduct(String id) {2        Object obj = null;3        try {4            ob...
Faire du code qui marche1    public Object getProduct(String id) {2        Object obj = null;3        try {4            ob...
Faire du code qui marche1    public Object getProduct(String id) {2        Object obj = null;3        try {4            ob...
Code simple      1         public void affiche(BankAccount account, ProductService service) {      2             System.ou...
Code simple      1         public void affiche(BankAccount account, ProductService service) {      2             System.ou...
Code simple      1         public void affiche(BankAccount account, ProductService service) {      2             System.ou...
simpleC’est compliqué de faire un test                         une évolution
Bonne nouvelle !
Je vous prend dans mon équipe !
COMMENT VAT’ON POUVOIRS’EN SORTIR ?       HTTP://WWW.SXC.HU/PROFILE/HOTBLACK
TEST DRIVEN DEVELOPMENTHTTP://UPLOAD.WIKIMEDIA.ORG/WIKIPEDIA/COMMONS/THUMB/6/69/HUMAN_EVOLUTION.SVG/1000PX-HUMAN_EVOLUTION...
PRINCIPE DE BASE
Ecrituredu test
Ecriture   Lancementdu test      du test
Correction de                            l’implémentation                       KOEcriture   Lancementdu test      du test
Correction de                             l’implémentation                        KOEcriture   Lancementdu test      du te...
Correction de                                       l’implémentation                                  KOEcriture   Lanceme...
Toujours faire le test cassant avantle test passant(pour tester le test)
TEST UNITAIREtester la plus petite unité de code possible
SIM                                               PLETEST UNITAIREtester la plus petite unité de code possible
SIM              FEE                              PLE              DBATEST UNITAIRE                          CKtester la p...
SIM              FEE                              PLE              DBA  COÛTEST UNITAIRE     CKtester la plus petite unité...
$40MIL 0   LIO       NS
EXEMPLE
Test d’abord !1    @Test2    public void can_deposit() {3        bankAccount.setBalance(50);45        boolean result = ban...
Test d’abord !1    @Test2    public void can_deposit() {3        bankAccount.setBalance(50);45        boolean result = ban...
Test d’abord !1    @Test2    public void can_deposit() {3        bankAccount.setBalance(50);45        boolean result = ban...
Test d’abord !1    @Test2    public void can_deposit() {3        bankAccount.setBalance(50);45        boolean result = ban...
Test d’abord !1    boolean deposit(int amount) {2        return false;3    }
Test d’abord !1    boolean deposit(int amount) {2        return false;3    }
Test d’abord !1    boolean deposit(int amount) {2        bal = bal + amount;3        return true;4    }
Test d’abord !1    boolean deposit(int amount) {2        bal = bal + amount;3        return true;4    }
Test d’abord !1    @Test2    public void cant_deposit_with_negative_amount() {3        bankAccount.setBalance(100);45     ...
Test d’abord !1    @Test2    public void cant_deposit_with_negative_amount() {3        bankAccount.setBalance(100);45     ...
Test d’abord !1    @Test2    public void cant_deposit_with_negative_amount() {3        bankAccount.setBalance(100);45     ...
Test d’abord !1    @Test2    public void cant_deposit_with_negative_amount() {3        bankAccount.setBalance(100);45     ...
Test d’abord !1    boolean deposit(int amount) {2        bal = bal + amount;3        return true;4    }
Test d’abord !1    boolean deposit(int amount) {2        bal = bal + amount;3        return true;4    }
Test d’abord !1    boolean deposit(int amount) {2        if(amount < 0) {3            return false;4        }5        bal ...
Test d’abord !1    boolean deposit(int amount) {2        if(amount < 0) {3            return false;4        }5        bal ...
Acteur / Action / Assertion
les «3 A» : Acteur/Action/Assertion1    @Test2    public void cant_deposit_with_negative_amount() {3        bankAccount.se...
les «3 A» : Acteur/Action/Assertion1    @Test2    public void cant_deposit_with_negative_amount() {3        bankAccount.se...
les «3 A» : Acteur/Action/Assertion1    @Test2    public void cant_deposit_with_negative_amount() {3        bankAccount.se...
les «3 A» : Acteur/Action/Assertion1    @Test2    public void cant_deposit_with_negative_amount() {3        bankAccount.se...
KISS
KISSKEEP IT SIMPLE (AND STUPID)
KISSKEEP IT SIMPLE (AND STUPID)
1   @Test 2   public void testGetCustomerOK() { 3 4       LOGGER.info("======= testGetCustomerOK starting..."); 5 6       ...
1   @Test 2   public void testGetCustomerOK() { 3 4       LOGGER.info("======= testGetCustomerOK starting..."); 5 6       ...
1   @Test 2   public void testGetCustomerOK() { 3 4       LOGGER.info("======= testGetCustomerOK starting..."); 5 6       ...
KISS !1    @Test2    public void can_get_customer() throws Exception {3        CustomerDTO targetDTO = this.serviceImpl.ge...
EN PRATIQUEHTTP://UPLOAD.WIKIMEDIA.ORG/WIKIPEDIA/COMMONS/THUMB/6/69/HUMAN_EVOLUTION.SVG/1000PX-HUMAN_EVOLUTION.SVG.PNG
VENIR ARMÉ
JUNIT + MOCKITO + FEST-ASSERT
JUNIT + MOCKITO + FEST-ASSERT
Mock ?simulacrese fait passer pour ce qu’iln’est pascomportementparamétrable
MOCKITO
doReturn(new BankAccount()).when(daoService).getObject("product", "id");
doReturn(new BankAccount())             BankAccount()).when(daoService).getObject("product", "id");
doReturn(new BankAccount()).when(daoService).getObject("product", "id");                            when(daoService)
doReturn(new BankAccount()).when(daoService).getObject("product", "id");                                             getOb...
doThrow(IOException.class).when(daoService).getObject("product", "id");
doThrow(IOException.class).when(daoService).getObject("product", "id");doThrow(IOException.class)
doThrow(IOException.class).when(daoService).getObject("product", "id");                           when(daoService)
doThrow(IOException.class).when(daoService).getObject("product", "id");                                            getObje...
FEST-ASSERT
assertThat(age).isGreaterThan(5);
assertThat(myList).containsExactly("MONAD42", "META18")
NOUVEAU CODE = NOUVEAU TEST
NOUVEAU BUG = NOUVEAU TEST
nouveau bug = nouveau test1    public Object getProduct(String id) {2        Object obj = null;3        try {4            ...
nouveau bug = nouveau test1    public Object getProduct(String id) {2        Object obj = null;3        try {4            ...
nouveau bug = nouveau test1    @Test2    public void can_return_null_when_ioexception() throws IOException {3        Mocki...
nouveau bug = nouveau test1    @Test2    public void can_return_null_when_ioexception() throws IOException {3        Mocki...
nouveau bug = nouveau test1    @Test2    public void can_return_null_when_ioexception() throws IOException {3        Mocki...
nouveau bug = nouveau test1    @Test2    public void can_return_null_when_ioexception() throws IOException {3        Mocki...
nouveau bug = nouveau test1    public Object getProduct(String id) {2        Object obj = null;3        try {4            ...
nouveau bug = nouveau test1    public Object getProduct(String id) {2        Object obj = null;3        try {4            ...
nouveau bug = nouveau test1    public Object getProduct(String id) {2        Object obj = null;3        try {4            ...
nouveau bug = nouveau test1    public Object getProduct(String id) {2        Object obj = null;3        try {4            ...
nouveau bug = nouveau test1    public Object getProduct(String id) {2        Object obj = null;3        try {4            ...
Laissez votre câble tranquille
TESTER DOIT ÊTRE SIMPLE
code complexe   1    /**   2      *   3      * @param xml : document xml représentant le swap   4      * @return objet Swa...
1      @Test  2    public void can_parse_xml() throws Exception {  3        String xml = "<?xml version="1.0" encoding="UT...
code complexe   1    /**   2      *   3      * @param xml : document xml représentant le swap   4      * @return objet Swa...
code complexe   1    /**   2      *   3      * @param xml : document xml représentant le swap   4      * @return objet Swa...
code complexe 1 public void updateSwapType(Swap swapToUpdate, Date now, Date spotDate, int test) { 2         if(test == 1)...
code complexe1    @Test2    public void can_update_swap_type() throws Exception {3        Swap swap = new Swap();4        ...
LE CODE DOIT ÊTRE MODULAIRE
Singleton     1 public class ProductService {     2     3     private static ProductService instance = new ProductService(...
Singleton     1 public class ProductService {     2     3     private static ProductService instance = new ProductService(...
Singleton     1 public class ProductService {     2     3     private static ProductService instance = new ProductService(...
Singleton     1 public class ProductService {     2     3     private static ProductService instance = new ProductService(...
Singleton   Code
Singleton   Code     ProductService
Singleton   Code     ProductService   DAOService
Singleton   Code     ProductService   DAOService
Singleton   Code     ProductService   DAOService
Singleton       Mock            ProductService   Code     ProductService   DAOService
Singleton1    public void validateSwap(String id) {2        Swap swap = (Swap) ProductService.getInstance().getProduct(id)...
Singleton1    public void validateSwap(String id) {2        Swap swap = (Swap) ProductService.getInstance()               ...
Injection 1     private ProductService productService; 2 3     public void setProductService(ProductService injectedServic...
Injection                                                   INJECTION 1     private ProductService productService; 2 3    ...
Injection 1     private ProductService productService; 2 3     public void setProductService(ProductService injectedServic...
Injection 1     @InjectMocks 2     private BankAccount bankAccount; 3 4     @Mock 5     private ProductService productServ...
Injection 1     @InjectMocks 2     private BankAccount bankAccount; 3 4 5       @Mock       private ProductService product...
Injection 1     @InjectMocks                                     INJECTION AUTOMATIQUE 2     private BankAccount bankAccou...
Injection 1     @InjectMocks 2     private BankAccount bankAccount; 3 4     @Mock 5     private ProductService productServ...
Injection 1     @InjectMocks 2     private BankAccount bankAccount; 3 4     @Mock 5     private ProductService productServ...
Injection 1     @InjectMocks 2     private BankAccount bankAccount; 3 4     @Mock 5     private ProductService productServ...
YODA (C) DISNEY
UTILISE L’INJECTION,        LUKEYODA (C) DISNEY
Sans injecteur ?1    public void validateSwap(String id) {2        Swap swap = (Swap) ProductService.getInstance().getProd...
Sans injecteur ?                                      EXTRACT METHOD !1    public void validateSwap(String id) {2        S...
Sans injecteur ?1    public ProductService getProductService() {2        return ProductService.getInstance();3    }45    p...
Sans injecteur ? 1    @Spy 2    private BankAccount bankAccount = new BankAccount("", 23, "", 3); 3 4    @Mock 5    privat...
Sans injecteur ? 1    @Spy 2    private BankAccount bankAccount = new BankAccount("", 23, "", 3); 3 4    @Mock 5    privat...
Sans injecteur ? 1    @Spy 2    private BankAccount bankAccount = new BankAccount("", 23, "", 3); 3 4    @Mock 5    privat...
Sans injecteur ? 1    @Spy 2    private BankAccount bankAccount = new BankAccount("", 23, "", 3); 3 4    @Mock 5    privat...
Sans injecteur ? 1    @Spy 2    private BankAccount bankAccount = new BankAccount("", 23, "", 3); 3 4    @Mock 5    privat...
Sans injecteur ? 1    @Spy 2    private BankAccount bankAccount = new BankAccount("", 23, "", 3); 3 4    @Mock 5    privat...
m e n t     rt is s eA v e
Singleton ? 1 public class ProductService { 2 3     private static ProductService instance = new ProductService(); 4 5    ...
Singleton ? 1 public class ProductService { 2 3     private static ProductService instance = new ProductService(); 4 5    ...
Singleton ? 1 public class ProductService { 2 3     private static ProductService instance = new ProductService(); 4 5    ...
Singleton ? 1 public class ProductService { 2 3     private static ProductService instance = null; 4 5     public ProductS...
Singleton ? 1 public class ProductService { 2 3     private static ProductService instance = null; 4 5     public ProductS...
Singleton ? 1 public class ProductService { 2 3     private static ProductService instance = new ProductService(); 4 5    ...
Singleton ? 1 public class ProductService implements IProductService { 2 3     private static IProductService instance = n...
LANCER UN TEST DOIT ÊTRE FACILE
Tests dans son IDE     INT                           ELL      ECL                     IJ         IPS               E      ...
LE CODE DOIT TOUJOURS   ÊTRE DÉPLOYABLE
Intégration continuemvn install
Intégration continue[INFO] ---------------------------------------------[INFO] BUILD SUCCESS[INFO] -----------------------...
Intégration continuemvn install
Intégration continue[INFO] ---------------------------------------------[INFO] BUILD FAILURE[INFO] -----------------------...
Intégration continue                              O N              K S             R            O Y           W M[INFO] --...
Intégration continueDéclenchement  d’un build
Intégration continueDéclenchement                Compilation  d’un build
Intégration continueDéclenchement                Compilation   Test  d’un build
Intégration continue                                      DéploiementDéclenchement                Compilation   Test  d’un...
AVOIR LA BONNE COUVERTURE
80%DE COUVERTURE DE CODE
80%DE COUVERTURE DE GETTER/SETTER
TRAVAILLER EN BINÔME
binomage (pair hero)             philosophie différente pour code identiqueHTTP://WWW.SXC.HU/PHOTO/959091
binomage (pair hero)                                 D E S                MA N           C O M LE Sphilosophie différente p...
binomage (pair hero)                       LE                             PLA                                     ND      ...
Ping Pong
J’écris le test
Il écrit l’implémentation
J’écris le test
Il écrit l’implémentation
bref
j’ai binômé
6 mois plus tard...
Bugs                Bugs                   Satisfaction   90  67,5   45  22,5    0    Janvier   Février   Mars   Avril    ...
Bugs                Bugs                   Satisfaction   90  67,5   45  22,5    0    Janvier   Février   Mars   Avril    ...
Bugs                Bugs                   Satisfaction   90  67,5   45  22,5    0    Janvier   Février   Mars   Avril    ...
Bugs                Bugs                   Satisfaction   90  67,5   45  22,5    0    Janvier   Février   Mars   Avril    ...
Bugs                Bugs                   Satisfaction   90  67,5   45  22,5    0    Janvier   Février   Mars   Avril    ...
Bugs                Bugs                   Satisfaction   90  67,5   45  22,5    0    Janvier   Février   Mars   Avril    ...
BRAVO À NOTRE ÉQUIPE DE CHOC !
(POUR RÉSUMER)
Installez Jenkins
Automatisez votre build
Écrivez votre 1er test
(même si il est «trop» simple)
HTTP://WWW.SXC.HU/PHOTO/664214IL FAUT APPRENDRE     À NAGER...
HTTP://WWW.SXC.HU/PHOTO/1008962...AVANT DE GAGNER DES COMPÉTITIONS
( DEMO )
QUESTIONS ?HTTP://UPLOAD.WIKIMEDIA.ORG/WIKIPEDIA/COMMONS/THUMB/6/69/HUMAN_EVOLUTION.SVG/1000PX-HUMAN_EVOLUTION.SVG.PNG
@DWURSTEISEN
Conf soat tests_unitaires_Mockito_jUnit_170113
Conf soat tests_unitaires_Mockito_jUnit_170113
Conf soat tests_unitaires_Mockito_jUnit_170113
Conf soat tests_unitaires_Mockito_jUnit_170113
Conf soat tests_unitaires_Mockito_jUnit_170113
Conf soat tests_unitaires_Mockito_jUnit_170113
Conf soat tests_unitaires_Mockito_jUnit_170113
Conf soat tests_unitaires_Mockito_jUnit_170113
Conf soat tests_unitaires_Mockito_jUnit_170113
Conf soat tests_unitaires_Mockito_jUnit_170113
Conf soat tests_unitaires_Mockito_jUnit_170113
Upcoming SlideShare
Loading in...5
×

Conf soat tests_unitaires_Mockito_jUnit_170113

976

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
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
976
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
6
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

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
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×