SlideShare una empresa de Scribd logo
1 de 195
Descargar para leer sin conexión
Test unitaire ?
           Mock ? TDD ?
             Kezako ?




01/26/13
                             1
Nouveau client !
Nouveau projet !
LEGACY CODE




HTTP://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
          * @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;
        }
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    }
La documentation a raison

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

1        /**
2        * Always returns true.
3        */
4      public boolean isAvailable() {
                                        WTF ?!?
5            return false;
6      }
fiable
La documentation n’est plus une aide
                            utile
Faire du code qui marche

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

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

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    }

                            NullPointerException !
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
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
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
simple
C’est compliqué de faire un test
                         une évolution
Bonne nouvelle !
Je vous prend dans mon équipe !
COMMENT VA
T’ON POUVOIR
S’EN SORTIR ?

       HTTP://WWW.SXC.HU/PROFILE/HOTBLACK
TEST DRIVEN DEVELOPMENT




HTTP://UPLOAD.WIKIMEDIA.ORG/WIKIPEDIA/COMMONS/THUMB/6/69/HUMAN_EVOLUTION.SVG/1000PX-HUMAN_EVOLUTION.SVG.PNG
PRINCIPE DE BASE
Ecriture
du test
Ecriture   Lancement
du test      du test
Correction de
                            l’implémentation
                       KO

Ecriture   Lancement
du test      du test
Correction de
                             l’implémentation
                        KO

Ecriture   Lancement
du test      du test


                       OK

                                   Fin
Correction de
                                       l’implémentation
                                  KO

Ecriture   Lancement
du test      du test


                              OK

                                             Fin

                       REFACTOR
Toujours faire le test cassant avant
le test passant
(pour tester le test)
TEST UNITAIRE
tester la plus petite unité de code possible
SIM
                                               PLE
TEST UNITAIRE
tester la plus petite unité de code possible
SIM
              FEE                              PLE
              DBA
TEST UNITAIRE                          CK
tester la plus petite unité de code possible
SIM
              FEE                              PLE
              DBA
  COÛ
TEST UNITAIRE     CK
tester la plus petite unité de code possible

         T
$40
MIL 0
   LIO
       NS
EXEMPLE
Test d’abord !

1    @Test
2    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 !

1    @Test
2    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 !

1    @Test
2    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 !

1    @Test
2    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 !


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    @Test
2    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    }
Test d’abord !

1    @Test
2    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    }
Test d’abord !

1    @Test
2    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    }
Test d’abord !

1    @Test
2    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    }
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 = bal + amount;
6        return true;
7    }
Test d’abord !

1    boolean deposit(int amount) {
2        if(amount < 0) {
3            return false;
4        }
5        bal = bal + amount;
6        return true;
7    }
Acteur / Action / Assertion
les «3 A» : Acteur/Action/Assertion

1    @Test
2    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

1    @Test
2    public void cant_deposit_with_negative_amount() {
3        bankAccount.setBalance(100);
4
5        boolean result = bankAccount.deposit(-20);
6
                                                         Acteur
7        assertFalse(result);
8        assertEquals(100, bankAccount.getBalance());
9    }
les «3 A» : Acteur/Action/Assertion

1    @Test
2    public void cant_deposit_with_negative_amount() {
3        bankAccount.setBalance(100);
4
5        boolean result = bankAccount.deposit(-20);
6
                                                         Action
7        assertFalse(result);
8        assertEquals(100, bankAccount.getBalance());
9    }
les «3 A» : Acteur/Action/Assertion

1    @Test
2    public void cant_deposit_with_negative_amount() {
3        bankAccount.setBalance(100);
4
5        boolean result = bankAccount.deposit(-20);
6
                                                         Assertions
7        assertFalse(result);
8        assertEquals(100, bankAccount.getBalance());
9    }
KISS
KISS
KEEP IT SIMPLE (AND STUPID)
KISS
KEEP IT SIMPLE (AND STUPID)
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   }
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   }
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 : {}",



                                                                              BRUIT
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   }
KISS !

1    @Test
2    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    }
EN PRATIQUE




HTTP://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 ?

simulacre

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

comportement
paramé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");
                                             getObject("product",
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");
                                            getObject("product",
FEST-ASSERT
assertThat(age).isGreaterThan(5);
assertThat(myList).containsExactly("MONAD42", "META18")
NOUVEAU CODE = NOUVEAU TEST
NOUVEAU BUG = NOUVEAU TEST
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    }
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    }


                                   LE BUG EST ICI !
nouveau bug = nouveau test

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

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

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

1    @Test
2    public void can_return_null_when_ioexception() throws IOException {
3        Mockito.doThrow(IOException.class)
4                .when(daoService).getObject("product", "azerty");
5
6        Object product = service.getProduct("azerty");
7
8        assertThat(product).isNull();
9    }
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    }
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    }
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    }


                           LE BUG EST TOUJOURS ICI !
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    }
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    }
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 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    }
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" +
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    }
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    }
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     }
code complexe

1    @Test
2    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    }
LE CODE DOIT ÊTRE MODULAIRE
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 }
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 }
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 }
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 }
Singleton


   Code
Singleton


   Code     ProductService
Singleton


   Code     ProductService   DAOService
Singleton


   Code     ProductService   DAOService
Singleton


   Code     ProductService   DAOService
Singleton       Mock
            ProductService




   Code     ProductService   DAOService
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    }
Singleton


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    }




                                            COUPLAGE FORT
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     }
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     }
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
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     }
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();
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                                     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();
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;
 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;
 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;
 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     }
YODA (C) DISNEY
UTILISE L’INJECTION,
        LUKE
YODA (C) DISNEY
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    }
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    }
Sans injecteur ?

1    public ProductService getProductService() {
2        return ProductService.getInstance();
3    }
4
5    public void validateSwap(String id) {
6        Swap swap = (Swap) getProductService()
                             getProductService().getProduct(id);
7        swap.updateState("VALIDATE");
8        getProductService()
         getProductService().save(swap);
9    }
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    }
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();                                         POSSIBLE
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);
 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);
 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);
 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);
 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    }
m e n t
     rt is s e
A v e
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 }
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 }
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 }
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 }
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 TARDIF
13         return instance;
14     }
15 }
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 }
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
LANCER UN TEST DOIT ÊTRE FACILE
Tests dans son IDE     INT
                           ELL
      ECL                     IJ
         IPS
               E

                     NET
                        BEA
                            NS
LE CODE DOIT TOUJOURS
   ÊTRE DÉPLOYABLE
Intégration continue



mvn install
Intégration continue


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

[INFO] BUILD SUCCESS

[INFO] ---------------------------------------------
Intégration continue



mvn install
Intégration continue


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

[INFO] BUILD FAILURE

[INFO] ---------------------------------------------
Intégration continue
                              O N
              K S
             R
            O Y
           W M
[INFO] ---------------------------------------------


                     E
                   IN
[INFO] BUILD FAILURE




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




              MA
Intégration continue


Déclenchement
  d’un build
Intégration continue


Déclenchement
                Compilation
  d’un build
Intégration continue


Déclenchement
                Compilation   Test
  d’un build
Intégration continue
                                      Déploiement




Déclenchement
                Compilation   Test
  d’un build



                                     Analyse de code
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 identique




HTTP://WWW.SXC.HU/PHOTO/959091
binomage (pair hero)
                                 D E S
                MA N
           C O M
 LE S
philosophie différente pour code identique
binomage (pair hero)
                       LE
                             PLA
                                     ND
                                            EV
philosophie différente pour code identique
                                              OL
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           Mai    Juin
Bugs
                Bugs                   Satisfaction


   90


  67,5


   45


  22,5


    0
    Janvier   Février   Mars   Avril           Mai    Juin
Bugs
                Bugs                   Satisfaction


   90


  67,5


   45


  22,5


    0
    Janvier   Février   Mars   Avril           Mai    Juin
Bugs
                Bugs                   Satisfaction


   90


  67,5


   45


  22,5


    0
    Janvier   Février   Mars   Avril           Mai    Juin
Bugs
                Bugs                   Satisfaction


   90


  67,5


   45


  22,5


    0
    Janvier   Février   Mars   Avril           Mai    Juin
Bugs
                Bugs                   Satisfaction


   90


  67,5


   45


  22,5


    0
    Janvier   Février   Mars   Avril           Mai    Juin
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/664214




IL 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

Más contenido relacionado

La actualidad más candente

The uniform interface is 42
The uniform interface is 42The uniform interface is 42
The uniform interface is 42Yevhen Bobrov
 
PVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error ExamplesPVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error ExamplesAndrey Karpov
 
201913001 khairunnisa progres_harian
201913001 khairunnisa progres_harian201913001 khairunnisa progres_harian
201913001 khairunnisa progres_harianKhairunnisaPekanbaru
 
Jdk(java) 7 - 6 기타기능
Jdk(java) 7 - 6 기타기능Jdk(java) 7 - 6 기타기능
Jdk(java) 7 - 6 기타기능knight1128
 
How Data Flow analysis works in a static code analyzer
How Data Flow analysis works in a static code analyzerHow Data Flow analysis works in a static code analyzer
How Data Flow analysis works in a static code analyzerAndrey Karpov
 
Spock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestSpock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestHoward Lewis Ship
 
Deterministic simulation testing
Deterministic simulation testingDeterministic simulation testing
Deterministic simulation testingFoundationDB
 
Silicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM MechanicsSilicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM MechanicsAzul Systems, Inc.
 
Making Java more dynamic: runtime code generation for the JVM
Making Java more dynamic: runtime code generation for the JVMMaking Java more dynamic: runtime code generation for the JVM
Making Java more dynamic: runtime code generation for the JVMRafael Winterhalter
 
201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programingwahyuseptiansyah
 
модели акторов в с++ миф или реальность
модели акторов в с++ миф или реальностьмодели акторов в с++ миф или реальность
модели акторов в с++ миф или реальностьcorehard_by
 
BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
BDD - Behavior Driven Development Webapps mit Groovy Spock und GebBDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
BDD - Behavior Driven Development Webapps mit Groovy Spock und GebChristian Baranowski
 

La actualidad más candente (20)

Server1
Server1Server1
Server1
 
Tugas 2
Tugas 2Tugas 2
Tugas 2
 
分散式系統
分散式系統分散式系統
分散式系統
 
The uniform interface is 42
The uniform interface is 42The uniform interface is 42
The uniform interface is 42
 
PVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error ExamplesPVS-Studio in 2021 - Error Examples
PVS-Studio in 2021 - Error Examples
 
201913001 khairunnisa progres_harian
201913001 khairunnisa progres_harian201913001 khairunnisa progres_harian
201913001 khairunnisa progres_harian
 
Fia fabila
Fia fabilaFia fabila
Fia fabila
 
Jdk(java) 7 - 6 기타기능
Jdk(java) 7 - 6 기타기능Jdk(java) 7 - 6 기타기능
Jdk(java) 7 - 6 기타기능
 
How Data Flow analysis works in a static code analyzer
How Data Flow analysis works in a static code analyzerHow Data Flow analysis works in a static code analyzer
How Data Flow analysis works in a static code analyzer
 
Vaadin7
Vaadin7Vaadin7
Vaadin7
 
Spock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestSpock: A Highly Logical Way To Test
Spock: A Highly Logical Way To Test
 
Deterministic simulation testing
Deterministic simulation testingDeterministic simulation testing
Deterministic simulation testing
 
Core java
Core javaCore java
Core java
 
Silicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM MechanicsSilicon Valley JUG: JVM Mechanics
Silicon Valley JUG: JVM Mechanics
 
Making Java more dynamic: runtime code generation for the JVM
Making Java more dynamic: runtime code generation for the JVMMaking Java more dynamic: runtime code generation for the JVM
Making Java more dynamic: runtime code generation for the JVM
 
201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing
 
Spock and Geb in Action
Spock and Geb in ActionSpock and Geb in Action
Spock and Geb in Action
 
модели акторов в с++ миф или реальность
модели акторов в с++ миф или реальностьмодели акторов в с++ миф или реальность
модели акторов в с++ миф или реальность
 
Java
JavaJava
Java
 
BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
BDD - Behavior Driven Development Webapps mit Groovy Spock und GebBDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
BDD - Behavior Driven Development Webapps mit Groovy Spock und Geb
 

Destacado

Mathieu parisot spring profiles
Mathieu parisot spring profilesMathieu parisot spring profiles
Mathieu parisot spring profilesSOAT
 
Le renouveau du web - Mathieu Parisot
Le renouveau du web - Mathieu ParisotLe renouveau du web - Mathieu Parisot
Le renouveau du web - Mathieu ParisotSOAT
 
Integration continue: TFS Preview
Integration continue: TFS PreviewIntegration continue: TFS Preview
Integration continue: TFS PreviewSOAT
 
Patterns Agiles avec Visual Studio 2012 et TFS 2012 (ALM201)
Patterns Agiles avec Visual Studio 2012 et TFS 2012 (ALM201)Patterns Agiles avec Visual Studio 2012 et TFS 2012 (ALM201)
Patterns Agiles avec Visual Studio 2012 et TFS 2012 (ALM201)Olivier Conq
 
Présentation spring data Matthieu Briend
Présentation spring data  Matthieu BriendPrésentation spring data  Matthieu Briend
Présentation spring data Matthieu BriendSOAT
 
Je démarre avec TFS 2012
Je démarre avec TFS 2012Je démarre avec TFS 2012
Je démarre avec TFS 2012Cédric Leblond
 
L'entreprise libérée
L'entreprise libéréeL'entreprise libérée
L'entreprise libéréeSOAT
 

Destacado (9)

Mathieu parisot spring profiles
Mathieu parisot spring profilesMathieu parisot spring profiles
Mathieu parisot spring profiles
 
Le renouveau du web - Mathieu Parisot
Le renouveau du web - Mathieu ParisotLe renouveau du web - Mathieu Parisot
Le renouveau du web - Mathieu Parisot
 
Integration continue: TFS Preview
Integration continue: TFS PreviewIntegration continue: TFS Preview
Integration continue: TFS Preview
 
TFS Source Control Management
TFS Source Control ManagementTFS Source Control Management
TFS Source Control Management
 
TFS
TFSTFS
TFS
 
Patterns Agiles avec Visual Studio 2012 et TFS 2012 (ALM201)
Patterns Agiles avec Visual Studio 2012 et TFS 2012 (ALM201)Patterns Agiles avec Visual Studio 2012 et TFS 2012 (ALM201)
Patterns Agiles avec Visual Studio 2012 et TFS 2012 (ALM201)
 
Présentation spring data Matthieu Briend
Présentation spring data  Matthieu BriendPrésentation spring data  Matthieu Briend
Présentation spring data Matthieu Briend
 
Je démarre avec TFS 2012
Je démarre avec TFS 2012Je démarre avec TFS 2012
Je démarre avec TFS 2012
 
L'entreprise libérée
L'entreprise libéréeL'entreprise libérée
L'entreprise libérée
 

Similar a Conf soat tests_unitaires_Mockito_jUnit_170113

Tests unitaires mock_kesako_20130516
Tests unitaires mock_kesako_20130516Tests unitaires mock_kesako_20130516
Tests unitaires mock_kesako_20130516SOAT
 
2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good TestsTomek Kaczanowski
 
Como NÃO testar o seu projeto de Software. DevDay 2014
Como NÃO testar o seu projeto de Software. DevDay 2014Como NÃO testar o seu projeto de Software. DevDay 2014
Como NÃO testar o seu projeto de Software. DevDay 2014alexandre freire
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleThierry Wasylczenko
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good TestsTomek Kaczanowski
 
ESCMAScript 6: Get Ready For The Future. Now
ESCMAScript 6: Get Ready For The Future. NowESCMAScript 6: Get Ready For The Future. Now
ESCMAScript 6: Get Ready For The Future. NowKrzysztof Szafranek
 
Cool JVM Tools to Help You Test
Cool JVM Tools to Help You TestCool JVM Tools to Help You Test
Cool JVM Tools to Help You TestSchalk Cronjé
 
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMockUnit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMockRobot Media
 
Node.js System: The Landing
Node.js System: The LandingNode.js System: The Landing
Node.js System: The LandingHaci Murat Yaman
 
Javascript Everywhere
Javascript EverywhereJavascript Everywhere
Javascript EverywherePascal Rettig
 
Atlassian Groovy Plugins
Atlassian Groovy PluginsAtlassian Groovy Plugins
Atlassian Groovy PluginsPaul King
 
Developer Test - Things to Know
Developer Test - Things to KnowDeveloper Test - Things to Know
Developer Test - Things to Knowvilniusjug
 
Intravert Server side processing for Cassandra
Intravert Server side processing for CassandraIntravert Server side processing for Cassandra
Intravert Server side processing for CassandraEdward Capriolo
 
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"DataStax Academy
 
Cool Jvm Tools to Help you Test - Aylesbury Testers Version
Cool Jvm Tools to Help you Test - Aylesbury Testers VersionCool Jvm Tools to Help you Test - Aylesbury Testers Version
Cool Jvm Tools to Help you Test - Aylesbury Testers VersionSchalk Cronjé
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?Doug Hawkins
 
Node Boot Camp
Node Boot CampNode Boot Camp
Node Boot CampTroy Miles
 
Don't Be Afraid of Abstract Syntax Trees
Don't Be Afraid of Abstract Syntax TreesDon't Be Afraid of Abstract Syntax Trees
Don't Be Afraid of Abstract Syntax TreesJamund Ferguson
 
Programming with ZooKeeper - A basic tutorial
Programming with ZooKeeper - A basic tutorialProgramming with ZooKeeper - A basic tutorial
Programming with ZooKeeper - A basic tutorialJeff Smith
 

Similar a Conf soat tests_unitaires_Mockito_jUnit_170113 (20)

Tests unitaires mock_kesako_20130516
Tests unitaires mock_kesako_20130516Tests unitaires mock_kesako_20130516
Tests unitaires mock_kesako_20130516
 
2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests2012 JDays Bad Tests Good Tests
2012 JDays Bad Tests Good Tests
 
Como NÃO testar o seu projeto de Software. DevDay 2014
Como NÃO testar o seu projeto de Software. DevDay 2014Como NÃO testar o seu projeto de Software. DevDay 2014
Como NÃO testar o seu projeto de Software. DevDay 2014
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradle
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests
 
ESCMAScript 6: Get Ready For The Future. Now
ESCMAScript 6: Get Ready For The Future. NowESCMAScript 6: Get Ready For The Future. Now
ESCMAScript 6: Get Ready For The Future. Now
 
Cool JVM Tools to Help You Test
Cool JVM Tools to Help You TestCool JVM Tools to Help You Test
Cool JVM Tools to Help You Test
 
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMockUnit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
 
Node.js System: The Landing
Node.js System: The LandingNode.js System: The Landing
Node.js System: The Landing
 
Javascript Everywhere
Javascript EverywhereJavascript Everywhere
Javascript Everywhere
 
Atlassian Groovy Plugins
Atlassian Groovy PluginsAtlassian Groovy Plugins
Atlassian Groovy Plugins
 
Developer Test - Things to Know
Developer Test - Things to KnowDeveloper Test - Things to Know
Developer Test - Things to Know
 
Intravert Server side processing for Cassandra
Intravert Server side processing for CassandraIntravert Server side processing for Cassandra
Intravert Server side processing for Cassandra
 
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
NYC* 2013 - "Advanced Data Processing: Beyond Queries and Slices"
 
A Test of Strength
A Test of StrengthA Test of Strength
A Test of Strength
 
Cool Jvm Tools to Help you Test - Aylesbury Testers Version
Cool Jvm Tools to Help you Test - Aylesbury Testers VersionCool Jvm Tools to Help you Test - Aylesbury Testers Version
Cool Jvm Tools to Help you Test - Aylesbury Testers Version
 
JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?JVM Mechanics: When Does the JVM JIT & Deoptimize?
JVM Mechanics: When Does the JVM JIT & Deoptimize?
 
Node Boot Camp
Node Boot CampNode Boot Camp
Node Boot Camp
 
Don't Be Afraid of Abstract Syntax Trees
Don't Be Afraid of Abstract Syntax TreesDon't Be Afraid of Abstract Syntax Trees
Don't Be Afraid of Abstract Syntax Trees
 
Programming with ZooKeeper - A basic tutorial
Programming with ZooKeeper - A basic tutorialProgramming with ZooKeeper - A basic tutorial
Programming with ZooKeeper - A basic tutorial
 

Más de SOAT

Back from Microsoft //Build 2018
Back from Microsoft //Build 2018Back from Microsoft //Build 2018
Back from Microsoft //Build 2018SOAT
 
Amélioration continue, c'est l'affaire de tous !
Amélioration continue, c'est l'affaire de tous !Amélioration continue, c'est l'affaire de tous !
Amélioration continue, c'est l'affaire de tous !SOAT
 
JAVA 8 : Migration et enjeux stratégiques en entreprise
JAVA 8 : Migration et enjeux stratégiques en entrepriseJAVA 8 : Migration et enjeux stratégiques en entreprise
JAVA 8 : Migration et enjeux stratégiques en entrepriseSOAT
 
ARCHITECTURE MICROSERVICE : TOUR D’HORIZON DU CONCEPT ET BONNES PRATIQUES
ARCHITECTURE MICROSERVICE : TOUR D’HORIZON DU CONCEPT ET BONNES PRATIQUESARCHITECTURE MICROSERVICE : TOUR D’HORIZON DU CONCEPT ET BONNES PRATIQUES
ARCHITECTURE MICROSERVICE : TOUR D’HORIZON DU CONCEPT ET BONNES PRATIQUESSOAT
 
3/3 : The path to CDI 2.0 - Antoine Sabot-Durand
3/3 : The path to CDI 2.0 - Antoine Sabot-Durand3/3 : The path to CDI 2.0 - Antoine Sabot-Durand
3/3 : The path to CDI 2.0 - Antoine Sabot-DurandSOAT
 
1/3 : introduction to CDI - Antoine Sabot-Durand
1/3 : introduction to CDI - Antoine Sabot-Durand1/3 : introduction to CDI - Antoine Sabot-Durand
1/3 : introduction to CDI - Antoine Sabot-DurandSOAT
 
2/3 : CDI advanced - Antoine Sabot-Durand
2/3 : CDI advanced - Antoine Sabot-Durand2/3 : CDI advanced - Antoine Sabot-Durand
2/3 : CDI advanced - Antoine Sabot-DurandSOAT
 
Angular JS - Paterne Gaye-Guingnido
Angular JS - Paterne Gaye-Guingnido Angular JS - Paterne Gaye-Guingnido
Angular JS - Paterne Gaye-Guingnido SOAT
 
Dans l'enfer du Web Mobile - un retour d'expérience - Mathieu Parisot
Dans l'enfer du Web Mobile - un retour d'expérience - Mathieu ParisotDans l'enfer du Web Mobile - un retour d'expérience - Mathieu Parisot
Dans l'enfer du Web Mobile - un retour d'expérience - Mathieu ParisotSOAT
 
RxJava, Getting Started - David Wursteisen - 16 Octobre 2014
RxJava, Getting Started - David Wursteisen - 16 Octobre 2014RxJava, Getting Started - David Wursteisen - 16 Octobre 2014
RxJava, Getting Started - David Wursteisen - 16 Octobre 2014SOAT
 
L'impact du Responsive Web Design sur vos équipes projet - Mathieu Parisot - ...
L'impact du Responsive Web Design sur vos équipes projet - Mathieu Parisot - ...L'impact du Responsive Web Design sur vos équipes projet - Mathieu Parisot - ...
L'impact du Responsive Web Design sur vos équipes projet - Mathieu Parisot - ...SOAT
 
Nio sur Netty par Mouhcine Moulou - 3 avril 2014
Nio sur Netty par Mouhcine Moulou - 3 avril 2014Nio sur Netty par Mouhcine Moulou - 3 avril 2014
Nio sur Netty par Mouhcine Moulou - 3 avril 2014SOAT
 
20140123 java8 lambdas_jose-paumard-soat
20140123 java8 lambdas_jose-paumard-soat20140123 java8 lambdas_jose-paumard-soat
20140123 java8 lambdas_jose-paumard-soatSOAT
 
Développer des applications iOS et Android avec c# grâce à Xamarin par Cyril ...
Développer des applications iOS et Android avec c# grâce à Xamarin par Cyril ...Développer des applications iOS et Android avec c# grâce à Xamarin par Cyril ...
Développer des applications iOS et Android avec c# grâce à Xamarin par Cyril ...SOAT
 
Amazon Web Service par Bertrand Lehurt - 11 mars 2014
Amazon Web Service par Bertrand Lehurt - 11 mars 2014Amazon Web Service par Bertrand Lehurt - 11 mars 2014
Amazon Web Service par Bertrand Lehurt - 11 mars 2014SOAT
 
ASP.Net Web API - Léonard Labat (18 février 2014)
ASP.Net Web API - Léonard Labat (18 février 2014)ASP.Net Web API - Léonard Labat (18 février 2014)
ASP.Net Web API - Léonard Labat (18 février 2014)SOAT
 
Xamarin et le développement natif d’applications Android, iOS et Windows en C#
 Xamarin et le développement natif d’applications Android, iOS et Windows en C# Xamarin et le développement natif d’applications Android, iOS et Windows en C#
Xamarin et le développement natif d’applications Android, iOS et Windows en C#SOAT
 
A la découverte du Responsive Web Design par Mathieu Parisot - Soat
A la découverte du Responsive Web Design par Mathieu Parisot - SoatA la découverte du Responsive Web Design par Mathieu Parisot - Soat
A la découverte du Responsive Web Design par Mathieu Parisot - SoatSOAT
 
MongoDB : la base NoSQL qui réinvente la gestion de données
MongoDB : la base NoSQL qui réinvente la gestion de donnéesMongoDB : la base NoSQL qui réinvente la gestion de données
MongoDB : la base NoSQL qui réinvente la gestion de donnéesSOAT
 
Soirée 3T Soat - Asp.net MVC
Soirée 3T Soat - Asp.net MVCSoirée 3T Soat - Asp.net MVC
Soirée 3T Soat - Asp.net MVCSOAT
 

Más de SOAT (20)

Back from Microsoft //Build 2018
Back from Microsoft //Build 2018Back from Microsoft //Build 2018
Back from Microsoft //Build 2018
 
Amélioration continue, c'est l'affaire de tous !
Amélioration continue, c'est l'affaire de tous !Amélioration continue, c'est l'affaire de tous !
Amélioration continue, c'est l'affaire de tous !
 
JAVA 8 : Migration et enjeux stratégiques en entreprise
JAVA 8 : Migration et enjeux stratégiques en entrepriseJAVA 8 : Migration et enjeux stratégiques en entreprise
JAVA 8 : Migration et enjeux stratégiques en entreprise
 
ARCHITECTURE MICROSERVICE : TOUR D’HORIZON DU CONCEPT ET BONNES PRATIQUES
ARCHITECTURE MICROSERVICE : TOUR D’HORIZON DU CONCEPT ET BONNES PRATIQUESARCHITECTURE MICROSERVICE : TOUR D’HORIZON DU CONCEPT ET BONNES PRATIQUES
ARCHITECTURE MICROSERVICE : TOUR D’HORIZON DU CONCEPT ET BONNES PRATIQUES
 
3/3 : The path to CDI 2.0 - Antoine Sabot-Durand
3/3 : The path to CDI 2.0 - Antoine Sabot-Durand3/3 : The path to CDI 2.0 - Antoine Sabot-Durand
3/3 : The path to CDI 2.0 - Antoine Sabot-Durand
 
1/3 : introduction to CDI - Antoine Sabot-Durand
1/3 : introduction to CDI - Antoine Sabot-Durand1/3 : introduction to CDI - Antoine Sabot-Durand
1/3 : introduction to CDI - Antoine Sabot-Durand
 
2/3 : CDI advanced - Antoine Sabot-Durand
2/3 : CDI advanced - Antoine Sabot-Durand2/3 : CDI advanced - Antoine Sabot-Durand
2/3 : CDI advanced - Antoine Sabot-Durand
 
Angular JS - Paterne Gaye-Guingnido
Angular JS - Paterne Gaye-Guingnido Angular JS - Paterne Gaye-Guingnido
Angular JS - Paterne Gaye-Guingnido
 
Dans l'enfer du Web Mobile - un retour d'expérience - Mathieu Parisot
Dans l'enfer du Web Mobile - un retour d'expérience - Mathieu ParisotDans l'enfer du Web Mobile - un retour d'expérience - Mathieu Parisot
Dans l'enfer du Web Mobile - un retour d'expérience - Mathieu Parisot
 
RxJava, Getting Started - David Wursteisen - 16 Octobre 2014
RxJava, Getting Started - David Wursteisen - 16 Octobre 2014RxJava, Getting Started - David Wursteisen - 16 Octobre 2014
RxJava, Getting Started - David Wursteisen - 16 Octobre 2014
 
L'impact du Responsive Web Design sur vos équipes projet - Mathieu Parisot - ...
L'impact du Responsive Web Design sur vos équipes projet - Mathieu Parisot - ...L'impact du Responsive Web Design sur vos équipes projet - Mathieu Parisot - ...
L'impact du Responsive Web Design sur vos équipes projet - Mathieu Parisot - ...
 
Nio sur Netty par Mouhcine Moulou - 3 avril 2014
Nio sur Netty par Mouhcine Moulou - 3 avril 2014Nio sur Netty par Mouhcine Moulou - 3 avril 2014
Nio sur Netty par Mouhcine Moulou - 3 avril 2014
 
20140123 java8 lambdas_jose-paumard-soat
20140123 java8 lambdas_jose-paumard-soat20140123 java8 lambdas_jose-paumard-soat
20140123 java8 lambdas_jose-paumard-soat
 
Développer des applications iOS et Android avec c# grâce à Xamarin par Cyril ...
Développer des applications iOS et Android avec c# grâce à Xamarin par Cyril ...Développer des applications iOS et Android avec c# grâce à Xamarin par Cyril ...
Développer des applications iOS et Android avec c# grâce à Xamarin par Cyril ...
 
Amazon Web Service par Bertrand Lehurt - 11 mars 2014
Amazon Web Service par Bertrand Lehurt - 11 mars 2014Amazon Web Service par Bertrand Lehurt - 11 mars 2014
Amazon Web Service par Bertrand Lehurt - 11 mars 2014
 
ASP.Net Web API - Léonard Labat (18 février 2014)
ASP.Net Web API - Léonard Labat (18 février 2014)ASP.Net Web API - Léonard Labat (18 février 2014)
ASP.Net Web API - Léonard Labat (18 février 2014)
 
Xamarin et le développement natif d’applications Android, iOS et Windows en C#
 Xamarin et le développement natif d’applications Android, iOS et Windows en C# Xamarin et le développement natif d’applications Android, iOS et Windows en C#
Xamarin et le développement natif d’applications Android, iOS et Windows en C#
 
A la découverte du Responsive Web Design par Mathieu Parisot - Soat
A la découverte du Responsive Web Design par Mathieu Parisot - SoatA la découverte du Responsive Web Design par Mathieu Parisot - Soat
A la découverte du Responsive Web Design par Mathieu Parisot - Soat
 
MongoDB : la base NoSQL qui réinvente la gestion de données
MongoDB : la base NoSQL qui réinvente la gestion de donnéesMongoDB : la base NoSQL qui réinvente la gestion de données
MongoDB : la base NoSQL qui réinvente la gestion de données
 
Soirée 3T Soat - Asp.net MVC
Soirée 3T Soat - Asp.net MVCSoirée 3T Soat - Asp.net MVC
Soirée 3T Soat - Asp.net MVC
 

Último

React Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkReact Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkPixlogix Infotech
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Kaya Weers
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observabilityitnewsafrica
 
A Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxA Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxAna-Maria Mihalceanu
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Nikki Chapple
 
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Jeffrey Haguewood
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Mark Simos
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...itnewsafrica
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 

Último (20)

React Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App FrameworkReact Native vs Ionic - The Best Mobile App Framework
React Native vs Ionic - The Best Mobile App Framework
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
 
A Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxA Glance At The Java Performance Toolbox
A Glance At The Java Performance Toolbox
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
 
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 

Conf soat tests_unitaires_Mockito_jUnit_170113

  • 1. Test unitaire ? Mock ? TDD ? Kezako ? 01/26/13 1
  • 2.
  • 3.
  • 6.
  • 7.
  • 9. 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; }
  • 10. 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 }
  • 11. La documentation a raison 1 /** 2 * Always returns true. 3 */ 4 public boolean isAvailable() { 5 return false; 6 }
  • 12. La documentation a raison 1 /** 2 * Always returns true. 3 */ 4 public boolean isAvailable() { WTF ?!? 5 return false; 6 }
  • 13. fiable La documentation n’est plus une aide utile
  • 14. Faire du code qui marche 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 }
  • 15. Faire du code qui marche 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 }
  • 16. Faire du code qui marche 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 } NullPointerException !
  • 17. 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
  • 18. 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
  • 19. 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
  • 20.
  • 21.
  • 22. simple C’est compliqué de faire un test une évolution
  • 23.
  • 24.
  • 26. Je vous prend dans mon équipe !
  • 27. COMMENT VA T’ON POUVOIR S’EN SORTIR ? HTTP://WWW.SXC.HU/PROFILE/HOTBLACK
  • 31. Ecriture Lancement du test du test
  • 32. Correction de l’implémentation KO Ecriture Lancement du test du test
  • 33. Correction de l’implémentation KO Ecriture Lancement du test du test OK Fin
  • 34. Correction de l’implémentation KO Ecriture Lancement du test du test OK Fin REFACTOR
  • 35. Toujours faire le test cassant avant le test passant (pour tester le test)
  • 36. TEST UNITAIRE tester la plus petite unité de code possible
  • 37. SIM PLE TEST UNITAIRE tester la plus petite unité de code possible
  • 38. SIM FEE PLE DBA TEST UNITAIRE CK tester la plus petite unité de code possible
  • 39. SIM FEE PLE DBA COÛ TEST UNITAIRE CK tester la plus petite unité de code possible T
  • 40.
  • 41. $40 MIL 0 LIO NS
  • 43. Test d’abord ! 1 @Test 2 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 }
  • 44. Test d’abord ! 1 @Test 2 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 }
  • 45. Test d’abord ! 1 @Test 2 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 }
  • 46. Test d’abord ! 1 @Test 2 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 }
  • 47. Test d’abord ! 1 boolean deposit(int amount) { 2 return false; 3 }
  • 48. Test d’abord ! 1 boolean deposit(int amount) { 2 return false; 3 }
  • 49. Test d’abord ! 1 boolean deposit(int amount) { 2 bal = bal + amount; 3 return true; 4 }
  • 50. Test d’abord ! 1 boolean deposit(int amount) { 2 bal = bal + amount; 3 return true; 4 }
  • 51. Test d’abord ! 1 @Test 2 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 }
  • 52. Test d’abord ! 1 @Test 2 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 }
  • 53. Test d’abord ! 1 @Test 2 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 }
  • 54. Test d’abord ! 1 @Test 2 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 }
  • 55. Test d’abord ! 1 boolean deposit(int amount) { 2 bal = bal + amount; 3 return true; 4 }
  • 56. Test d’abord ! 1 boolean deposit(int amount) { 2 bal = bal + amount; 3 return true; 4 }
  • 57. Test d’abord ! 1 boolean deposit(int amount) { 2 if(amount < 0) { 3 return false; 4 } 5 bal = bal + amount; 6 return true; 7 }
  • 58. Test d’abord ! 1 boolean deposit(int amount) { 2 if(amount < 0) { 3 return false; 4 } 5 bal = bal + amount; 6 return true; 7 }
  • 59. Acteur / Action / Assertion
  • 60. les «3 A» : Acteur/Action/Assertion 1 @Test 2 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 }
  • 61. les «3 A» : Acteur/Action/Assertion 1 @Test 2 public void cant_deposit_with_negative_amount() { 3 bankAccount.setBalance(100); 4 5 boolean result = bankAccount.deposit(-20); 6 Acteur 7 assertFalse(result); 8 assertEquals(100, bankAccount.getBalance()); 9 }
  • 62. les «3 A» : Acteur/Action/Assertion 1 @Test 2 public void cant_deposit_with_negative_amount() { 3 bankAccount.setBalance(100); 4 5 boolean result = bankAccount.deposit(-20); 6 Action 7 assertFalse(result); 8 assertEquals(100, bankAccount.getBalance()); 9 }
  • 63. les «3 A» : Acteur/Action/Assertion 1 @Test 2 public void cant_deposit_with_negative_amount() { 3 bankAccount.setBalance(100); 4 5 boolean result = bankAccount.deposit(-20); 6 Assertions 7 assertFalse(result); 8 assertEquals(100, bankAccount.getBalance()); 9 }
  • 64. KISS
  • 65. KISS KEEP IT SIMPLE (AND STUPID)
  • 66. KISS KEEP IT SIMPLE (AND STUPID)
  • 67. 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 }
  • 68. 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 }
  • 69. 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 : {}", BRUIT 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 }
  • 70. KISS ! 1 @Test 2 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 }
  • 73. JUNIT + MOCKITO + FEST-ASSERT
  • 74. JUNIT + MOCKITO + FEST-ASSERT
  • 75. Mock ? simulacre se fait passer pour ce qu’il n’est pas comportement paramétrable
  • 78. doReturn(new BankAccount()) BankAccount()).when(daoService).getObject("product", "id");
  • 88. NOUVEAU CODE = NOUVEAU TEST
  • 89. NOUVEAU BUG = NOUVEAU TEST
  • 90. 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 }
  • 91. 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 } LE BUG EST ICI !
  • 92. nouveau bug = nouveau test 1 @Test 2 public void can_return_null_when_ioexception() throws IOException { 3 Mockito.doThrow(IOException.class) 4 .when(daoService).getObject("product", "azerty"); 5 6 Object product = service.getProduct("azerty"); 7 8 assertThat(product).isNull(); 9 }
  • 93. nouveau bug = nouveau test 1 @Test 2 public void can_return_null_when_ioexception() throws IOException { 3 Mockito.doThrow(IOException.class) 4 .when(daoService).getObject("product", "azerty"); 5 6 Object product = service.getProduct("azerty"); 7 8 assertThat(product).isNull(); 9 }
  • 94. nouveau bug = nouveau test 1 @Test 2 public void can_return_null_when_ioexception() throws IOException { 3 Mockito.doThrow(IOException.class) 4 .when(daoService).getObject("product", "azerty"); 5 6 Object product = service.getProduct("azerty"); 7 8 assertThat(product).isNull(); 9 }
  • 95. nouveau bug = nouveau test 1 @Test 2 public void can_return_null_when_ioexception() throws IOException { 3 Mockito.doThrow(IOException.class) 4 .when(daoService).getObject("product", "azerty"); 5 6 Object product = service.getProduct("azerty"); 7 8 assertThat(product).isNull(); 9 }
  • 96. 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 }
  • 97. 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 }
  • 98. 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 } LE BUG EST TOUJOURS ICI !
  • 99. 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 }
  • 100. 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 }
  • 101. Laissez votre câble tranquille
  • 102. TESTER DOIT ÊTRE SIMPLE
  • 103. 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 }
  • 104. 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" +
  • 105.
  • 106. 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 }
  • 107. 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 }
  • 108. 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 }
  • 109. code complexe 1 @Test 2 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 }
  • 110. LE CODE DOIT ÊTRE MODULAIRE
  • 111. 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 }
  • 112. 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 }
  • 113. 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 }
  • 114. 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 }
  • 115. Singleton Code
  • 116. Singleton Code ProductService
  • 117. Singleton Code ProductService DAOService
  • 118. Singleton Code ProductService DAOService
  • 119. Singleton Code ProductService DAOService
  • 120. Singleton Mock ProductService Code ProductService DAOService
  • 121. 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 }
  • 122. Singleton 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 } COUPLAGE FORT
  • 123. 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 }
  • 124. 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 }
  • 125. 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
  • 126. 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 }
  • 127. 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(); 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 }
  • 128. 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(); 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 }
  • 129. 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 }
  • 130. 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 }
  • 131. 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 }
  • 133. UTILISE L’INJECTION, LUKE YODA (C) DISNEY
  • 134. 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 }
  • 135. 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 }
  • 136. Sans injecteur ? 1 public ProductService getProductService() { 2 return ProductService.getInstance(); 3 } 4 5 public void validateSwap(String id) { 6 Swap swap = (Swap) getProductService() getProductService().getProduct(id); 7 swap.updateState("VALIDATE"); 8 getProductService() getProductService().save(swap); 9 }
  • 137. 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 }
  • 138. 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(); POSSIBLE 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 }
  • 139. 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 }
  • 140. 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 }
  • 141. 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 }
  • 142. 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 }
  • 143. m e n t rt is s e A v e
  • 144. 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 }
  • 145. 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 }
  • 146. 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 }
  • 147. 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 }
  • 148. 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 TARDIF 13 return instance; 14 } 15 }
  • 149. 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 }
  • 150. 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
  • 151. LANCER UN TEST DOIT ÊTRE FACILE
  • 152. Tests dans son IDE INT ELL ECL IJ IPS E NET BEA NS
  • 153. LE CODE DOIT TOUJOURS ÊTRE DÉPLOYABLE
  • 155. Intégration continue [INFO] --------------------------------------------- [INFO] BUILD SUCCESS [INFO] ---------------------------------------------
  • 157. Intégration continue [INFO] --------------------------------------------- [INFO] BUILD FAILURE [INFO] ---------------------------------------------
  • 158. Intégration continue O N K S R O Y W M [INFO] --------------------------------------------- E IN [INFO] BUILD FAILURE CH [INFO] --------------------------------------------- MA
  • 160. Intégration continue Déclenchement Compilation d’un build
  • 161. Intégration continue Déclenchement Compilation Test d’un build
  • 162. Intégration continue Déploiement Déclenchement Compilation Test d’un build Analyse de code
  • 163.
  • 164. AVOIR LA BONNE COUVERTURE
  • 166. 80% DE COUVERTURE DE GETTER/SETTER
  • 168. binomage (pair hero) philosophie différente pour code identique HTTP://WWW.SXC.HU/PHOTO/959091
  • 169. binomage (pair hero) D E S MA N C O M LE S philosophie différente pour code identique
  • 170. binomage (pair hero) LE PLA ND EV philosophie différente pour code identique OL
  • 176. bref
  • 178. 6 mois plus tard...
  • 179. Bugs Bugs Satisfaction 90 67,5 45 22,5 0 Janvier Février Mars Avril Mai Juin
  • 180. Bugs Bugs Satisfaction 90 67,5 45 22,5 0 Janvier Février Mars Avril Mai Juin
  • 181. Bugs Bugs Satisfaction 90 67,5 45 22,5 0 Janvier Février Mars Avril Mai Juin
  • 182. Bugs Bugs Satisfaction 90 67,5 45 22,5 0 Janvier Février Mars Avril Mai Juin
  • 183. Bugs Bugs Satisfaction 90 67,5 45 22,5 0 Janvier Février Mars Avril Mai Juin
  • 184. Bugs Bugs Satisfaction 90 67,5 45 22,5 0 Janvier Février Mars Avril Mai Juin
  • 185. BRAVO À NOTRE ÉQUIPE DE CHOC !
  • 190. (même si il est «trop» simple)