SlideShare a Scribd company logo
16 mai 13
Test unitaire ?
Mock ? TDD ?
Kezako ?
1
Bienvenue !
❤=+
réseaux sociaux
Prochaines conférences : http://soat.fr
twitter : @soatgroup / @soatexpertsjava
slideshares : http://fr.slideshare.net/soatexpert
Aller plus loin : http://blog.soat.fr
Test unitaire ? Mock ? TDD ? Kezako ?
en finir avec les régressions par David Wursteisen
16 MAI 2013
Nouveau client !
Nouveau projet !
HTTP://UPLOAD.WIKIMEDIA.ORG/WIKIPEDIA/COMMONS/THUMB/6/69/HUMAN_EVOLUTION.SVG/1000PX-HUMAN_EVOLUTION.SVG.PNG
LEGACY CODE
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");
534 } else {
535 swap.setType("CURVE");
536 }
537 } else if (test == 2) {
538 if(d.after(spotDate)) {
539 swap.setType("IRS");
540 } else {
541 swap.setType("CURVE");
542 }
543 }
[...] /* encore beaucoup de code... */
1135 return swap;
1136 }
1000
LIGNES !
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() {
5 return false;
6 }
WTF ?!?
La documentation n’est plus
fiable
une aide
utile
4 obj = networkService.getObject("product", id);
1 public Object getProduct(String id) {
2 Object obj = null;
3 try {
4 obj = networkService.getObject("product", id);
5 } catch (IOException e) {
6 System.err.println("Error with obj : " + obj.toString());
7 }
8 return obj;
9 }
Faire du code qui marche
4 obj = networkService.getObject("product", id);
1 public Object getProduct(String id) {
2 Object obj = null;
3 try {
4 obj = networkService.getObject("product", id);
5 } catch (IOException e) {
6 System.err.println("Error with obj : " + obj.toString());
7 }
8 return obj;
9 }
Faire du code qui marche
1 public Object getProduct(String id) {
2 Object obj = null;
3 try {
4 obj = networkService.getObject("product", id);
5 } catch (IOException e) {
6 System.err.println("Error with obj : " + obj.toString());
7 }
8 return obj;
9 }
2 Object obj = null;
5 } catch (IOException e) {
6 System.err.println("Error with obj : " + obj.toString());
7 }
Faire du code qui marche
NullPointerException !
4 account = (BankAccount) service.getProduct(this.name);
5 account.deposit();
1 public void affiche(BankAccount account, ProductService service) {
2 System.out.println("Bank Account : "+this.name);
3 System.out.println("Autres informations : ");
4 account = (BankAccount) service.getProduct(this.name);
5 account.deposit();
6 System.out.println(account);
7 System.out.println("=== FIN ===");
8
9 }
Code simple
HTTP://EN.WIKIPEDIA.ORG/WIKI/FILE:JEU_DE_MIKADO.JPG
4 account = (BankAccount) service.getProduct(this.name);
5 account.deposit();
1 public void affiche(BankAccount account, ProductService service) {
2 System.out.println("Bank Account : "+this.name);
3 System.out.println("Autres informations : ");
4 account = (BankAccount) service.getProduct(this.name);
5 account.deposit();
6 System.out.println(account);
7 System.out.println("=== FIN ===");
8
9 }
Code simple
HTTP://EN.WIKIPEDIA.ORG/WIKI/FILE:JEU_DE_MIKADO.JPG
4 account = (BankAccount) service.getProduct(this.name);
5 account.deposit();
1 public void affiche(BankAccount account, ProductService service) {
2 System.out.println("Bank Account : "+this.name);
3 System.out.println("Autres informations : ");
4 account = (BankAccount) service.getProduct(this.name);
5 account.deposit();
6 System.out.println(account);
7 System.out.println("=== FIN ===");
8
9 }
Code simple
HTTP://EN.WIKIPEDIA.ORG/WIKI/FILE:JEU_DE_MIKADO.JPG
C’est compliqué de faire
simple
un test
une évolution
Bonne nouvelle !
Je vous prend dans mon équipe !
HTTP://WWW.SXC.HU/PROFILE/HOTBLACK
COMMENT VA
T’ON POUVOIR
S’EN SORTIR ?
HTTP://UPLOAD.WIKIMEDIA.ORG/WIKIPEDIA/COMMONS/THUMB/6/69/HUMAN_EVOLUTION.SVG/1000PX-HUMAN_EVOLUTION.SVG.PNG
TEST DRIVEN DEVELOPMENT
PRINCIPE DE BASE
Ecriture
du test
Lancement
du test
Ecriture
du test
Lancement
du test
Correction de
l’implémentation
Ecriture
du test
KO
Lancement
du test
Correction de
l’implémentation
Ecriture
du test
Fin
KO
OK
Lancement
du test
Correction de
l’implémentation
Ecriture
du test
Fin
KO
OK
REFACTOR
Toujours faire le test cassant avant
le test passant
(pour tester le test)
TEST UNITAIRE
tester la plus petite unité de code possible
TEST UNITAIRE
tester la plus petite unité de code possible
SIMPLE
TEST UNITAIRE
tester la plus petite unité de code possible
SIMPLEFEEDBACK
TEST UNITAIRE
tester la plus petite unité de code possible
SIMPLEFEEDBACKCOÛT
$400MILLIONS
EXEMPLE
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 }
3 bankAccount.setBalance(50);
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 }
3 bankAccount.setBalance(50);
Test d’abord !
5 boolean result = bankAccount.deposit(1000);
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 !
7 assertTrue(result);
8 assertEquals(1050, bankAccount.getBalance());
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 }
3 bankAccount.setBalance(100);
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 }
5 boolean result = bankAccount.deposit(-20);
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 }
7 assertFalse(result);
8 assertEquals(100, bankAccount.getBalance());
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 }
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
3 bankAccount.setBalance(100);
Acteur
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
5 boolean result = bankAccount.deposit(-20);
Action
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
7 assertFalse(result);
8 assertEquals(100, bankAccount.getBalance());
Assertions
KISS
KISSKEEP IT SIMPLE (AND STUPID)
KISSKEEP IT SIMPLE (AND STUPID)
7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99");
8
9 // Vérifier.
10 Assert.assertNotNull("Extra non trouvé.", targetDTO);
11 Assert.assertEquals("Les accountId doivent être identiques.",
12 "ABC99", targetDTO.getAccountId());
1 @Test
2 public void testGetCustomerOK() {
3
4 LOGGER.info("======= testGetCustomerOK starting...");
5
6 try {
7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99");
8
9 // Vérifier.
10 Assert.assertNotNull("Extra non trouvé.", targetDTO);
11 Assert.assertEquals("Les accountId doivent être identiques.",
12 "ABC99", targetDTO.getAccountId());
13
14 } catch (CustomerBusinessException exception) {
15 LOGGER.error("CustomerBusinessException : {}",
16 exception.getCause());
17 Assert.fail(exception.getMessage());
18 } catch (UnavailableResourceException exception) {
19 LOGGER.error("UnavailableResourceException : {}",
20 exception.getMessage());
21 Assert.fail(exception.getMessage());
22 } catch (UnexpectedException exception) {
23 LOGGER.error("UnexpectedException : {}" +
24 exception.getMessage());
25 Assert.fail(exception.getMessage());
26 } catch (Exception exception) {
27 LOGGER.error("CRASH : " + exception.getMessage());
28 Assert.fail(exception.getMessage());
29 }
30
31 LOGGER.info("======= testGetCustomerOK done.");
32 }
7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99");
8
9 // Vérifier.
10 Assert.assertNotNull("Extra non trouvé.", targetDTO);
11 Assert.assertEquals("Les accountId doivent être identiques.",
12 "ABC99", targetDTO.getAccountId());
1 @Test
2 public void testGetCustomerOK() {
3
4 LOGGER.info("======= testGetCustomerOK starting...");
5
6 try {
7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99");
8
9 // Vérifier.
10 Assert.assertNotNull("Extra non trouvé.", targetDTO);
11 Assert.assertEquals("Les accountId doivent être identiques.",
12 "ABC99", targetDTO.getAccountId());
13
14 } catch (CustomerBusinessException exception) {
15 LOGGER.error("CustomerBusinessException : {}",
16 exception.getCause());
17 Assert.fail(exception.getMessage());
18 } catch (UnavailableResourceException exception) {
19 LOGGER.error("UnavailableResourceException : {}",
20 exception.getMessage());
21 Assert.fail(exception.getMessage());
22 } catch (UnexpectedException exception) {
23 LOGGER.error("UnexpectedException : {}" +
24 exception.getMessage());
25 Assert.fail(exception.getMessage());
26 } catch (Exception exception) {
27 LOGGER.error("CRASH : " + exception.getMessage());
28 Assert.fail(exception.getMessage());
29 }
30
31 LOGGER.info("======= testGetCustomerOK done.");
32 }
1 @Test
2 public void testGetCustomerOK() {
3
4 LOGGER.info("======= testGetCustomerOK starting...");
5
6 try {
7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99");
8
9 // Vérifier.
10 Assert.assertNotNull("Extra non trouvé.", targetDTO);
11 Assert.assertEquals("Les accountId doivent être identiques.",
12 "ABC99", targetDTO.getAccountId());
13
14 } catch (CustomerBusinessException exception) {
15 LOGGER.error("CustomerBusinessException : {}",
16 exception.getCause());
17 Assert.fail(exception.getMessage());
18 } catch (UnavailableResourceException exception) {
19 LOGGER.error("UnavailableResourceException : {}",
20 exception.getMessage());
21 Assert.fail(exception.getMessage());
22 } catch (UnexpectedException exception) {
23 LOGGER.error("UnexpectedException : {}" +
24 exception.getMessage());
25 Assert.fail(exception.getMessage());
26 } catch (Exception exception) {
27 LOGGER.error("CRASH : " + exception.getMessage());
28 Assert.fail(exception.getMessage());
29 }
30
31 LOGGER.info("======= testGetCustomerOK done.");
32 }
14 } catch (CustomerBusinessException exception) {
15 LOGGER.error("CustomerBusinessException : {}",
16 exception.getCause());
17 Assert.fail(exception.getMessage());
18 } catch (UnavailableResourceException exception) {
19 LOGGER.error("UnavailableResourceException : {}",
20 exception.getMessage());
21 Assert.fail(exception.getMessage());
22 } catch (UnexpectedException exception) {
23 LOGGER.error("UnexpectedException : {}" +
24 exception.getMessage());
25 Assert.fail(exception.getMessage());
26 } catch (Exception exception) {
27 LOGGER.error("CRASH : " + exception.getMessage());
28 Assert.fail(exception.getMessage());
29 }
30
31 LOGGER.info("======= testGetCustomerOK done.");
BRUIT
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 }
HTTP://UPLOAD.WIKIMEDIA.ORG/WIKIPEDIA/COMMONS/THUMB/6/69/HUMAN_EVOLUTION.SVG/1000PX-HUMAN_EVOLUTION.SVG.PNG
EN PRATIQUE
VENIR ARMÉ
JUNIT + MOCKITO + ASSERTJ
JUNIT + MOCKITO + ASSERTJ
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()).when(daoService).getObject("product", "id");doReturn(new BankAccount())
doReturn(new BankAccount()).when(daoService).getObject("product", "id");when(daoService)
doReturn(new BankAccount()).when(daoService).getObject("product", "id");getObject("product", "id");
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", "id");
ASSERTJ
assertThat(age).isGreaterThan(5);
assertThat(myList).containsExactly("MONAD42", "META18")
assertThat(negotation).isBooked();
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 }
1 public Object getProduct(String id) {
2 Object obj = null;
3 try {
4 obj = networkService.getObject("product", id);
5 } catch (IOException e) {
6 System.err.println("Error with obj : " + obj.toString());
7 }
8 return obj;
9 }
nouveau bug = nouveau test
6 System.err.println("Error with obj : " + obj.toString());
LE BUG EST ICI !
nouveau bug = nouveau test
1 @Test
2 public void can_return_null_when_ioexception() throws IOException {
3 Mockito.doThrow(IOException.class)
4 .when(networkService).getObject("product", "azerty");
5
6 Object product = service.getProduct("azerty");
7
8 assertThat(product).isNull();
9 }
3 Mockito.doThrow(IOException.class)
4 .when(networkService).getObject("product", "azerty");
1 @Test
2 public void can_return_null_when_ioexception() throws IOException {
3 Mockito.doThrow(IOException.class)
4 .when(networkService).getObject("product", "azerty");
5
6 Object product = service.getProduct("azerty");
7
8 assertThat(product).isNull();
9 }
nouveau bug = nouveau test
1 @Test
2 public void can_return_null_when_ioexception() throws IOException {
3 Mockito.doThrow(IOException.class)
4 .when(networkService).getObject("product", "azerty");
5
6 Object product = service.getProduct("azerty");
7
8 assertThat(product).isNull();
9 }
6 Object product = service.getProduct("azerty");
nouveau bug = nouveau test
8 assertThat(product).isNull();
1 @Test
2 public void can_return_null_when_ioexception() throws IOException {
3 Mockito.doThrow(IOException.class)
4 .when(networkService).getObject("product", "azerty");
5
6 Object product = service.getProduct("azerty");
7
8 assertThat(product).isNull();
9 }
nouveau bug = nouveau test
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 }
1 public Object getProduct(String id) {
2 Object obj = null;
3 try {
4 obj = networkService.getObject("product", id);
5 } catch (IOException e) {
6 System.err.println("Error with obj : " + obj.toString());
7 }
8 return obj;
9 }
nouveau bug = nouveau test
6 System.err.println("Error with obj : " + obj.toString());
LE BUG EST TOUJOURS ICI !
1 public Object getProduct(String id) {
2 Object obj = null;
3 try {
4 obj = networkService.getObject("product", id);
5 } catch (IOException e) {
6 System.err.println("Error with obj with id: " + id);
7 }
8 return obj;
9 }
nouveau bug = nouveau test
6 System.err.println("Error with obj with id: " + id);
nouveau bug = nouveau test
1 public Object getProduct(String id) {
2 Object obj = null;
3 try {
4 obj = networkService.getObject("product", id);
5 } catch (IOException e) {
6 System.err.println("Error with obj with id: " + id);
7 }
8 return obj;
9 }
6 System.err.println("Error with obj with id: " + id);
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 }
1 /**
2 *
3 * @param xml : document xml représentant le swap
4 * @return objet Swap
5 */
6 public Swap parse(String xml) {
7 Swap swap = new Swap();
8 String currency = getNodeValue("/swap/currency", xml);
9 swap.setCurrency(currency);
[...] /* beaucoup de code... */
530 Date d = new Date();
531 if(test == 1) {
532 if(d.after(spotDate)) {
533 swap.setType("IRS");
534 } else {
535 swap.setType("CURVE");
536 }
537 } else if (test == 2) {
538 if(d.after(spotDate)) {
539 swap.setType("IRS");
540 } else {
541 swap.setType("CURVE");
542 }
543 }
[...] /* encore beaucoup de code... */
1135 return swap;
1136 }
code complexe
531 if(test == 1) {
532 if(d.after(spotDate)) {
533 swap.setType("IRS");
534 } else {
535 swap.setType("CURVE");
536 }
537 } else if (test == 2) {
538 if(d.after(spotDate)) {
539 swap.setType("IRS");
540 } else {
541 swap.setType("CURVE");
542 }
543 }
EXTRACT METHOD !
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 }
1 public class ProductService {
2
3 private static ProductService instance = new ProductService();
4
5 private DAOService daoService;
6
7 private ProductService() {
8 System.out.println("ProductService constructor");
9 daoService = DAOService.getInstance();
10 }
11
12 public static ProductService getInstance() {
13 return instance;
14 }
15
16
17
18 public Object getProduct(String id) {
19 return daoService.getObject("product", id);
20 }
21 }
Singleton
3 private static ProductService instance = new ProductService();
1 public class ProductService {
2
3 private static ProductService instance = new ProductService();
4
5 private DAOService daoService;
6
7 private ProductService() {
8 System.out.println("ProductService constructor");
9 daoService = DAOService.getInstance();
10 }
11
12 public static ProductService getInstance() {
13 return instance;
14 }
15
16
17
18 public Object getProduct(String id) {
19 return daoService.getObject("product", id);
20 }
21 }
Singleton
7 private ProductService() {
9 daoService = DAOService.getInstance();
10 }
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
Code ProductService DAOService
Mock
ProductService
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 }
1 public void validateSwap(String id) {
2 Swap swap = (Swap) ProductService.getInstance().getProduct(id);
3 swap.updateState("VALIDATE");
4 ProductService.getInstance().save(swap);
5 }
Singleton
ProductService.getInstance()
4 ProductService.getInstance()
COUPLAGE FORT
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 }
1 private ProductService productService;
2
3 public void setProductService(ProductService injectedService) {
4 this.productService = injectedService;
5 }
6
7 public void validateSwap(String id) {
8 Swap swap = (Swap) productService.getProduct(id);
9 swap.updateState("VALIDATE");
10 productService.save(swap);
11 }
Injection
3 public void setProductService(ProductService injectedService) {
4 this.productService = injectedService;
5 }
INJECTION
1 private ProductService productService;
2
3 public void setProductService(ProductService injectedService) {
4 this.productService = injectedService;
5 }
6
7 public void validateSwap(String id) {
8 Swap swap = (Swap) productService.getProduct(id);
9 swap.updateState("VALIDATE");
10 productService.save(swap);
11 }
Injection
8 Swap swap = (Swap) productService.getProduct(id);
UTILISATION
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 }
1 @InjectMocks
2 private BankAccount bankAccount;
3
4 @Mock
5 private ProductService productService;
6
7 @Test
8 public void can_validate_swap() {
9 Swap swap = new Swap();
10
11 Mockito.doReturn(swap).when(productService).getProduct("fakeId");
12 Mockito.doNothing().when(productService).save(swap);
13
14 bankAccount.validateSwap("fakeId");
15
16 assertEquals("VALIDATE", swap.getState());
17 }
Injection
4 @Mock
5 private ProductService productService;
MOCK
1 @InjectMocks
2 private BankAccount bankAccount;
3
4 @Mock
5 private ProductService productService;
6
7 @Test
8 public void can_validate_swap() {
9 Swap swap = new Swap();
10
11 Mockito.doReturn(swap).when(productService).getProduct("fakeId");
12 Mockito.doNothing().when(productService).save(swap);
13
14 bankAccount.validateSwap("fakeId");
15
16 assertEquals("VALIDATE", swap.getState());
17 }
Injection
1 @InjectMocks
2 private BankAccount bankAccount;
INJECTION AUTOMATIQUE
DES MOCKS
1 @InjectMocks
2 private BankAccount bankAccount;
3
4 @Mock
5 private ProductService productService;
6
7 @Test
8 public void can_validate_swap() {
9 Swap swap = new Swap();
10
11 Mockito.doReturn(swap).when(productService).getProduct("fakeId");
12 Mockito.doNothing().when(productService).save(swap);
13
14 bankAccount.validateSwap("fakeId");
15
16 assertEquals("VALIDATE", swap.getState());
17 }
Injection
11 Mockito.doReturn(swap).when(productService).getProduct("fakeId");
12 Mockito.doNothing().when(productService).save(swap);
1 @InjectMocks
2 private BankAccount bankAccount;
3
4 @Mock
5 private ProductService productService;
6
7 @Test
8 public void can_validate_swap() {
9 Swap swap = new Swap();
10
11 Mockito.doReturn(swap).when(productService).getProduct("fakeId");
12 Mockito.doNothing().when(productService).save(swap);
13
14 bankAccount.validateSwap("fakeId");
15
16 assertEquals("VALIDATE", swap.getState());
17 }
14 bankAccount.validateSwap("fakeId");
Injection
Injection
1 @InjectMocks
2 private BankAccount bankAccount;
3
4 @Mock
5 private ProductService productService;
6
7 @Test
8 public void can_validate_swap() {
9 Swap swap = new Swap();
10
11 Mockito.doReturn(swap).when(productService).getProduct("fakeId");
12 Mockito.doNothing().when(productService).save(swap);
13
14 bankAccount.validateSwap("fakeId");
15
16 assertEquals("VALIDATE", swap.getState());
17 }
16 assertEquals("VALIDATE", swap.getState());
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 }
1 public void validateSwap(String id) {
2 Swap swap = (Swap) ProductService.getInstance().getProduct(id);
3 swap.updateState("VALIDATE");
4 ProductService.getInstance().save(swap);
5 }
Sans injecteur ?
ProductService.getInstance()
4 ProductService.getInstance()
EXTRACT METHOD !
1 public ProductService getProductService() {
2 return ProductService.getInstance();
3 }
4
5 public void validateSwap(String id) {
6 Swap swap = (Swap) getProductService().getProduct(id);
7 swap.updateState("VALIDATE");
8 getProductService().save(swap);
9 }
Sans injecteur ?
1 public ProductService getProductService() {
2 return ProductService.getInstance();
3 }
getProductService()
8 getProductService()
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 }
1 @Spy
2 private BankAccount bankAccount = new BankAccount("", 23, "", 3);
3
4 @Mock
5 private ProductService productService;
6
7 @Test
8 public void can_validate_swap() {
9 Swap swap = new Swap();
10
11 Mockito.doReturn(productService).when(bankAccount).getProductService();
12
13 Mockito.doReturn(swap).when(productService).getProduct("fakeId");
14 Mockito.doNothing().when(productService).save(swap);
15
16 bankAccount.validateSwap("fakeId");
17
18 assertEquals("VALIDATE", swap.getState());
19 }
Sans injecteur ?
1 @Spy
2 private BankAccount bankAccount = new BankAccount("", 23, "", 3);
REDÉFINITION DES MÉTHODES
POSSIBLE
1 @Spy
2 private BankAccount bankAccount = new BankAccount("", 23, "", 3);
3
4 @Mock
5 private ProductService productService;
6
7 @Test
8 public void can_validate_swap() {
9 Swap swap = new Swap();
10
11 Mockito.doReturn(productService).when(bankAccount).getProductService();
12
13 Mockito.doReturn(swap).when(productService).getProduct("fakeId");
14 Mockito.doNothing().when(productService).save(swap);
15
16 bankAccount.validateSwap("fakeId");
17
18 assertEquals("VALIDATE", swap.getState());
19 }
Sans injecteur ?
11 Mockito.doReturn(productService).when(bankAccount).getProductService();
1 @Spy
2 private BankAccount bankAccount = new BankAccount("", 23, "", 3);
3
4 @Mock
5 private ProductService productService;
6
7 @Test
8 public void can_validate_swap() {
9 Swap swap = new Swap();
10
11 Mockito.doReturn(productService).when(bankAccount).getProductService();
12
13 Mockito.doReturn(swap).when(productService).getProduct("fakeId");
14 Mockito.doNothing().when(productService).save(swap);
15
16 bankAccount.validateSwap("fakeId");
17
18 assertEquals("VALIDATE", swap.getState());
19 }
Sans injecteur ?
13 Mockito.doReturn(swap).when(productService).getProduct("fakeId");
14 Mockito.doNothing().when(productService).save(swap);
Sans injecteur ?
1 @Spy
2 private BankAccount bankAccount = new BankAccount("", 23, "", 3);
3
4 @Mock
5 private ProductService productService;
6
7 @Test
8 public void can_validate_swap() {
9 Swap swap = new Swap();
10
11 Mockito.doReturn(productService).when(bankAccount).getProductService();
12
13 Mockito.doReturn(swap).when(productService).getProduct("fakeId");
14 Mockito.doNothing().when(productService).save(swap);
15
16 bankAccount.validateSwap("fakeId");
17
18 assertEquals("VALIDATE", swap.getState());
19 }
16 bankAccount.validateSwap("fakeId");
Sans injecteur ?
1 @Spy
2 private BankAccount bankAccount = new BankAccount("", 23, "", 3);
3
4 @Mock
5 private ProductService productService;
6
7 @Test
8 public void can_validate_swap() {
9 Swap swap = new Swap();
10
11 Mockito.doReturn(productService).when(bankAccount).getProductService();
12
13 Mockito.doReturn(swap).when(productService).getProduct("fakeId");
14 Mockito.doNothing().when(productService).save(swap);
15
16 bankAccount.validateSwap("fakeId");
17
18 assertEquals("VALIDATE", swap.getState());
19 }
18 assertEquals("VALIDATE", swap.getState());
Avertissement
LANCER UN TEST DOIT ÊTRE FACILE
Tests dans son IDE
ECLIPSE
NETBEANS
INTELLIJ
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
[INFO] ---------------------------------------------
[INFO] BUILD FAILURE
[INFO] ---------------------------------------------
WORKS ON
MY
MACHINE
Intégration continue
Déclenchement
d’un build
Intégration continue
Déclenchement
d’un build
Compilation
Intégration continue
Déclenchement
d’un build
Compilation Test
Intégration continue
Déclenchement
d’un build
Compilation Test
Déploiement
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)
philosophie différente pour code identiqueLES COMMANDES
binomage (pair hero)
philosophie différente pour code identique
LE PLAN DE VOL
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
0
22,5
45
67,5
90
Janvier Février Mars Avril Mai Juin
Bugs Satisfaction
Bugs
0
22,5
45
67,5
90
Janvier Février Mars Avril Mai Juin
Bugs Satisfaction
Bugs
0
22,5
45
67,5
90
Janvier Février Mars Avril Mai Juin
Bugs Satisfaction
Bugs
0
22,5
45
67,5
90
Janvier Février Mars Avril Mai Juin
Bugs Satisfaction
Bugs
0
22,5
45
67,5
90
Janvier Février Mars Avril Mai Juin
Bugs Satisfaction
Bugs
0
22,5
45
67,5
90
Janvier Février Mars Avril Mai Juin
Bugs Satisfaction
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...
...AVANT DE GAGNER
DES COMPÉTITIONS
HTTP://WWW.SXC.HU/PHOTO/1008962
( DEMO )
HTTP://UPLOAD.WIKIMEDIA.ORG/WIKIPEDIA/COMMONS/THUMB/6/69/HUMAN_EVOLUTION.SVG/1000PX-HUMAN_EVOLUTION.SVG.PNG
QUESTIONS ?
Merci !
It’s Pizza Time !Drink
@DWURSTEISEN
référence
jenkins : http://jenkins-ci.org/
assertj : https://github.com/joel-costigliola/assertj
mockito : https://code.google.com/p/mockito/
démo : http://parleys.com/play/5148922a0364bc17fc56c85a/about

More Related Content

What's hot

LISA QooxdooTutorial Slides
LISA QooxdooTutorial SlidesLISA QooxdooTutorial Slides
LISA QooxdooTutorial Slides
Tobias Oetiker
 
Jasmine - why JS tests don't smell fishy
Jasmine - why JS tests don't smell fishyJasmine - why JS tests don't smell fishy
Jasmine - why JS tests don't smell fishy
Igor Napierala
 
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
Tomek Kaczanowski
 
The Ring programming language version 1.10 book - Part 94 of 212
The Ring programming language version 1.10 book - Part 94 of 212The Ring programming language version 1.10 book - Part 94 of 212
The Ring programming language version 1.10 book - Part 94 of 212
Mahmoud Samir Fayed
 
Object oriented JavaScript
Object oriented JavaScriptObject oriented JavaScript
Object oriented JavaScript
Rafał Wesołowski
 
Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101
Roy Yu
 
Extreme JavaScript Performance
Extreme JavaScript PerformanceExtreme JavaScript Performance
Extreme JavaScript Performance
Thomas Fuchs
 
Node.js flow control
Node.js flow controlNode.js flow control
Node.js flow control
Simon Su
 
Dat testing - An introduction to Java and Android Testing
Dat testing - An introduction to Java and Android TestingDat testing - An introduction to Java and Android Testing
Dat testing - An introduction to Java and Android Testing
Saúl Díaz González
 
The Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 SeasonsThe Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 Seasons
Baruch Sadogursky
 
Kotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresKotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan Soares
iMasters
 
Rich and Snappy Apps (No Scaling Required)
Rich and Snappy Apps (No Scaling Required)Rich and Snappy Apps (No Scaling Required)
Rich and Snappy Apps (No Scaling Required)
Thomas Fuchs
 
Understanding JavaScript Testing
Understanding JavaScript TestingUnderstanding JavaScript Testing
Understanding JavaScript Testing
jeresig
 
NetBeans Plugin Development: JRebel Experience Report
NetBeans Plugin Development: JRebel Experience ReportNetBeans Plugin Development: JRebel Experience Report
NetBeans Plugin Development: JRebel Experience Report
Anton Arhipov
 
The Promised Land (in Angular)
The Promised Land (in Angular)The Promised Land (in Angular)
The Promised Land (in Angular)
Domenic Denicola
 
Understanding JavaScript Testing
Understanding JavaScript TestingUnderstanding JavaScript Testing
Understanding JavaScript Testing
Kissy Team
 
Taking a Test Drive
Taking a Test DriveTaking a Test Drive
Taking a Test Drive
Graham Lee
 
Testing My Patience
Testing My PatienceTesting My Patience
Testing My Patience
Adam Lowry
 
201913001 khairunnisa progres_harian
201913001 khairunnisa progres_harian201913001 khairunnisa progres_harian
201913001 khairunnisa progres_harian
KhairunnisaPekanbaru
 
Fia fabila
Fia fabilaFia fabila
Fia fabila
fiafabila
 

What's hot (20)

LISA QooxdooTutorial Slides
LISA QooxdooTutorial SlidesLISA QooxdooTutorial Slides
LISA QooxdooTutorial Slides
 
Jasmine - why JS tests don't smell fishy
Jasmine - why JS tests don't smell fishyJasmine - why JS tests don't smell fishy
Jasmine - why JS tests don't smell fishy
 
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
 
The Ring programming language version 1.10 book - Part 94 of 212
The Ring programming language version 1.10 book - Part 94 of 212The Ring programming language version 1.10 book - Part 94 of 212
The Ring programming language version 1.10 book - Part 94 of 212
 
Object oriented JavaScript
Object oriented JavaScriptObject oriented JavaScript
Object oriented JavaScript
 
Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101
 
Extreme JavaScript Performance
Extreme JavaScript PerformanceExtreme JavaScript Performance
Extreme JavaScript Performance
 
Node.js flow control
Node.js flow controlNode.js flow control
Node.js flow control
 
Dat testing - An introduction to Java and Android Testing
Dat testing - An introduction to Java and Android TestingDat testing - An introduction to Java and Android Testing
Dat testing - An introduction to Java and Android Testing
 
The Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 SeasonsThe Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 Seasons
 
Kotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresKotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan Soares
 
Rich and Snappy Apps (No Scaling Required)
Rich and Snappy Apps (No Scaling Required)Rich and Snappy Apps (No Scaling Required)
Rich and Snappy Apps (No Scaling Required)
 
Understanding JavaScript Testing
Understanding JavaScript TestingUnderstanding JavaScript Testing
Understanding JavaScript Testing
 
NetBeans Plugin Development: JRebel Experience Report
NetBeans Plugin Development: JRebel Experience ReportNetBeans Plugin Development: JRebel Experience Report
NetBeans Plugin Development: JRebel Experience Report
 
The Promised Land (in Angular)
The Promised Land (in Angular)The Promised Land (in Angular)
The Promised Land (in Angular)
 
Understanding JavaScript Testing
Understanding JavaScript TestingUnderstanding JavaScript Testing
Understanding JavaScript Testing
 
Taking a Test Drive
Taking a Test DriveTaking a Test Drive
Taking a Test Drive
 
Testing My Patience
Testing My PatienceTesting My Patience
Testing My Patience
 
201913001 khairunnisa progres_harian
201913001 khairunnisa progres_harian201913001 khairunnisa progres_harian
201913001 khairunnisa progres_harian
 
Fia fabila
Fia fabilaFia fabila
Fia fabila
 

Viewers also liked

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 entreprise
SOAT
 
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
SOAT
 
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
SOAT
 
L'entreprise libérée
L'entreprise libéréeL'entreprise libérée
L'entreprise libérée
SOAT
 
Test unitaires visual studio
Test unitaires visual studioTest unitaires visual studio
Test unitaires visual studio
SOAT
 
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
SOAT
 

Viewers also liked (8)

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
 
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
 
Test unitaire
Test unitaireTest unitaire
Test unitaire
 
L'entreprise libérée
L'entreprise libéréeL'entreprise libérée
L'entreprise libérée
 
Test unitaires visual studio
Test unitaires visual studioTest unitaires visual studio
Test unitaires visual studio
 
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
 

Similar to Tests unitaires mock_kesako_20130516

Conf soat tests_unitaires_Mockito_jUnit_170113
Conf soat tests_unitaires_Mockito_jUnit_170113Conf soat tests_unitaires_Mockito_jUnit_170113
Conf soat tests_unitaires_Mockito_jUnit_170113
SOAT
 
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
alexandre freire
 
Tdd iPhone For Dummies
Tdd iPhone For DummiesTdd iPhone For Dummies
Tdd iPhone For Dummies
Giordano Scalzo
 
Google guava
Google guavaGoogle guava
An Introduction to Property Based Testing
An Introduction to Property Based TestingAn Introduction to Property Based Testing
An Introduction to Property Based Testing
C4Media
 
Javascript Everywhere
Javascript EverywhereJavascript Everywhere
Javascript Everywhere
Pascal Rettig
 
Aaron Bedra - Effective Software Security Teams
Aaron Bedra - Effective Software Security TeamsAaron Bedra - Effective Software Security Teams
Aaron Bedra - Effective Software Security Teams
centralohioissa
 
Javaone2008 Bof 5101 Groovytesting
Javaone2008 Bof 5101 GroovytestingJavaone2008 Bof 5101 Groovytesting
Javaone2008 Bof 5101 Groovytesting
Andres Almiray
 
Boosting Your Testing Productivity with Groovy
Boosting Your Testing Productivity with GroovyBoosting Your Testing Productivity with Groovy
Boosting Your Testing Productivity with Groovy
James Williams
 
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
Thierry Wasylczenko
 
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
Robot Media
 
Testing the waters of iOS
Testing the waters of iOSTesting the waters of iOS
Testing the waters of iOS
Kremizas Kostas
 
Test Infected Presentation
Test Infected PresentationTest Infected Presentation
Test Infected Presentation
willmation
 
A Lifecycle Of Code Under Test by Robert Fornal
A Lifecycle Of Code Under Test by Robert FornalA Lifecycle Of Code Under Test by Robert Fornal
A Lifecycle Of Code Under Test by Robert Fornal
QA or the Highway
 
PHPunit and you
PHPunit and youPHPunit and you
PHPunit and you
markstory
 
Developer Test - Things to Know
Developer Test - Things to KnowDeveloper Test - Things to Know
Developer Test - Things to Know
vilniusjug
 
04 - Dublerzy testowi
04 - Dublerzy testowi04 - Dublerzy testowi
04 - Dublerzy testowi
Krzysztof Jelski
 
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Julian Robichaux
 
DEV-1550: Why Java 8? Or, What's a Lambda? – IBM Connect 2017
DEV-1550: Why Java 8? Or, What's a Lambda? – IBM Connect 2017DEV-1550: Why Java 8? Or, What's a Lambda? – IBM Connect 2017
DEV-1550: Why Java 8? Or, What's a Lambda? – IBM Connect 2017
panagenda
 
We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End Development
All Things Open
 

Similar to Tests unitaires mock_kesako_20130516 (20)

Conf soat tests_unitaires_Mockito_jUnit_170113
Conf soat tests_unitaires_Mockito_jUnit_170113Conf soat tests_unitaires_Mockito_jUnit_170113
Conf soat tests_unitaires_Mockito_jUnit_170113
 
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
 
Tdd iPhone For Dummies
Tdd iPhone For DummiesTdd iPhone For Dummies
Tdd iPhone For Dummies
 
Google guava
Google guavaGoogle guava
Google guava
 
An Introduction to Property Based Testing
An Introduction to Property Based TestingAn Introduction to Property Based Testing
An Introduction to Property Based Testing
 
Javascript Everywhere
Javascript EverywhereJavascript Everywhere
Javascript Everywhere
 
Aaron Bedra - Effective Software Security Teams
Aaron Bedra - Effective Software Security TeamsAaron Bedra - Effective Software Security Teams
Aaron Bedra - Effective Software Security Teams
 
Javaone2008 Bof 5101 Groovytesting
Javaone2008 Bof 5101 GroovytestingJavaone2008 Bof 5101 Groovytesting
Javaone2008 Bof 5101 Groovytesting
 
Boosting Your Testing Productivity with Groovy
Boosting Your Testing Productivity with GroovyBoosting Your Testing Productivity with Groovy
Boosting Your Testing Productivity with Groovy
 
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
 
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
 
Testing the waters of iOS
Testing the waters of iOSTesting the waters of iOS
Testing the waters of iOS
 
Test Infected Presentation
Test Infected PresentationTest Infected Presentation
Test Infected Presentation
 
A Lifecycle Of Code Under Test by Robert Fornal
A Lifecycle Of Code Under Test by Robert FornalA Lifecycle Of Code Under Test by Robert Fornal
A Lifecycle Of Code Under Test by Robert Fornal
 
PHPunit and you
PHPunit and youPHPunit and you
PHPunit and you
 
Developer Test - Things to Know
Developer Test - Things to KnowDeveloper Test - Things to Know
Developer Test - Things to Know
 
04 - Dublerzy testowi
04 - Dublerzy testowi04 - Dublerzy testowi
04 - Dublerzy testowi
 
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
Connect2017 DEV-1550 Why Java 8? Or, What's a Lambda?
 
DEV-1550: Why Java 8? Or, What's a Lambda? – IBM Connect 2017
DEV-1550: Why Java 8? Or, What's a Lambda? – IBM Connect 2017DEV-1550: Why Java 8? Or, What's a Lambda? – IBM Connect 2017
DEV-1550: Why Java 8? Or, What's a Lambda? – IBM Connect 2017
 
We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End Development
 

More from SOAT

Back from Microsoft //Build 2018
Back from Microsoft //Build 2018Back from Microsoft //Build 2018
Back from Microsoft //Build 2018
SOAT
 
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
SOAT
 
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 Parisot
SOAT
 
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
SOAT
 
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 2014
SOAT
 
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 2014
SOAT
 
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 - Soat
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
SOAT
 
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
 
Présentation spring data Matthieu Briend
Présentation spring data  Matthieu BriendPrésentation spring data  Matthieu Briend
Présentation spring data Matthieu BriendSOAT
 
Je suis agile tout seul - Ricardo Minhoto
Je suis agile tout seul - Ricardo MinhotoJe suis agile tout seul - Ricardo Minhoto
Je suis agile tout seul - Ricardo Minhoto
SOAT
 
Facilitez vous la vie - Ricardo Minhoto
Facilitez vous la vie - Ricardo MinhotoFacilitez vous la vie - Ricardo Minhoto
Facilitez vous la vie - Ricardo Minhoto
SOAT
 
Play : Premiers pas par l'exemple le 120613
Play : Premiers pas par l'exemple le 120613Play : Premiers pas par l'exemple le 120613
Play : Premiers pas par l'exemple le 120613
SOAT
 
Transition Agile technique à grande échelle
Transition Agile technique à grande échelleTransition Agile technique à grande échelle
Transition Agile technique à grande échelle
SOAT
 

More from SOAT (20)

Back from Microsoft //Build 2018
Back from Microsoft //Build 2018Back from Microsoft //Build 2018
Back from Microsoft //Build 2018
 
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
 
Présentation spring data Matthieu Briend
Présentation spring data  Matthieu BriendPrésentation spring data  Matthieu Briend
Présentation spring data Matthieu Briend
 
Je suis agile tout seul - Ricardo Minhoto
Je suis agile tout seul - Ricardo MinhotoJe suis agile tout seul - Ricardo Minhoto
Je suis agile tout seul - Ricardo Minhoto
 
Facilitez vous la vie - Ricardo Minhoto
Facilitez vous la vie - Ricardo MinhotoFacilitez vous la vie - Ricardo Minhoto
Facilitez vous la vie - Ricardo Minhoto
 
Play : Premiers pas par l'exemple le 120613
Play : Premiers pas par l'exemple le 120613Play : Premiers pas par l'exemple le 120613
Play : Premiers pas par l'exemple le 120613
 
Transition Agile technique à grande échelle
Transition Agile technique à grande échelleTransition Agile technique à grande échelle
Transition Agile technique à grande échelle
 

Recently uploaded

UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6
DianaGray10
 
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
Neo4j
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
Kari Kakkonen
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
Quotidiano Piemontese
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
KAMESHS29
 
“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”
Claudio Di Ciccio
 
A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...
sonjaschweigert1
 
Large Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial ApplicationsLarge Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial Applications
Rohit Gautam
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
Neo4j
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
DianaGray10
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
SOFTTECHHUB
 
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
Edge AI and Vision Alliance
 
Mind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AIMind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AI
Kumud Singh
 
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
Neo4j
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
Octavian Nadolu
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Paige Cruz
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
danishmna97
 
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Speck&Tech
 
Building RAG with self-deployed Milvus vector database and Snowpark Container...
Building RAG with self-deployed Milvus vector database and Snowpark Container...Building RAG with self-deployed Milvus vector database and Snowpark Container...
Building RAG with self-deployed Milvus vector database and Snowpark Container...
Zilliz
 

Recently uploaded (20)

UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6UiPath Test Automation using UiPath Test Suite series, part 6
UiPath Test Automation using UiPath Test Suite series, part 6
 
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
GraphSummit Singapore | Neo4j Product Vision & Roadmap - Q2 2024
 
Climate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing DaysClimate Impact of Software Testing at Nordic Testing Days
Climate Impact of Software Testing at Nordic Testing Days
 
National Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practicesNational Security Agency - NSA mobile device best practices
National Security Agency - NSA mobile device best practices
 
RESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for studentsRESUME BUILDER APPLICATION Project for students
RESUME BUILDER APPLICATION Project for students
 
“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”“I’m still / I’m still / Chaining from the Block”
“I’m still / I’m still / Chaining from the Block”
 
A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...
 
Large Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial ApplicationsLarge Language Model (LLM) and it’s Geospatial Applications
Large Language Model (LLM) and it’s Geospatial Applications
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
 
Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1Communications Mining Series - Zero to Hero - Session 1
Communications Mining Series - Zero to Hero - Session 1
 
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
Goodbye Windows 11: Make Way for Nitrux Linux 3.5.0!
 
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
“Building and Scaling AI Applications with the Nx AI Manager,” a Presentation...
 
Mind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AIMind map of terminologies used in context of Generative AI
Mind map of terminologies used in context of Generative AI
 
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024GraphSummit Singapore | The Art of the  Possible with Graph - Q2 2024
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
 
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdfObservability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
Observability Concepts EVERY Developer Should Know -- DeveloperWeek Europe.pdf
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
How to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptxHow to Get CNIC Information System with Paksim Ga.pptx
How to Get CNIC Information System with Paksim Ga.pptx
 
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
Cosa hanno in comune un mattoncino Lego e la backdoor XZ?
 
Building RAG with self-deployed Milvus vector database and Snowpark Container...
Building RAG with self-deployed Milvus vector database and Snowpark Container...Building RAG with self-deployed Milvus vector database and Snowpark Container...
Building RAG with self-deployed Milvus vector database and Snowpark Container...
 

Tests unitaires mock_kesako_20130516

  • 1. 16 mai 13 Test unitaire ? Mock ? TDD ? Kezako ? 1
  • 4. réseaux sociaux Prochaines conférences : http://soat.fr twitter : @soatgroup / @soatexpertsjava slideshares : http://fr.slideshare.net/soatexpert Aller plus loin : http://blog.soat.fr
  • 5. Test unitaire ? Mock ? TDD ? Kezako ? en finir avec les régressions par David Wursteisen 16 MAI 2013
  • 6.
  • 7.
  • 10.
  • 11.
  • 13. 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; }
  • 14. La documentation explique le code 1 /** 2 * 3 * @param xml : document xml représentant le swap 4 * @return objet Swap 5 */ 6 public Swap parse(String xml) { 7 Swap swap = new Swap(); 8 String currency = getNodeValue("/swap/currency", xml); 9 swap.setCurrency(currency); [...] /* beaucoup de code... */ 530 Date d = new Date(); 531 if(test == 1) { 532 if(d.after(spotDate)) { 533 swap.setType("IRS"); 534 } else { 535 swap.setType("CURVE"); 536 } 537 } else if (test == 2) { 538 if(d.after(spotDate)) { 539 swap.setType("IRS"); 540 } else { 541 swap.setType("CURVE"); 542 } 543 } [...] /* encore beaucoup de code... */ 1135 return swap; 1136 } 1000 LIGNES !
  • 15. La documentation a raison 1 /** 2 * Always returns true. 3 */ 4 public boolean isAvailable() { 5 return false; 6 }
  • 16. La documentation a raison 1 /** 2 * Always returns true. 3 */ 4 public boolean isAvailable() { 5 return false; 6 } WTF ?!?
  • 17. La documentation n’est plus fiable une aide utile
  • 18. 4 obj = networkService.getObject("product", id); 1 public Object getProduct(String id) { 2 Object obj = null; 3 try { 4 obj = networkService.getObject("product", id); 5 } catch (IOException e) { 6 System.err.println("Error with obj : " + obj.toString()); 7 } 8 return obj; 9 } Faire du code qui marche
  • 19. 4 obj = networkService.getObject("product", id); 1 public Object getProduct(String id) { 2 Object obj = null; 3 try { 4 obj = networkService.getObject("product", id); 5 } catch (IOException e) { 6 System.err.println("Error with obj : " + obj.toString()); 7 } 8 return obj; 9 } Faire du code qui marche
  • 20. 1 public Object getProduct(String id) { 2 Object obj = null; 3 try { 4 obj = networkService.getObject("product", id); 5 } catch (IOException e) { 6 System.err.println("Error with obj : " + obj.toString()); 7 } 8 return obj; 9 } 2 Object obj = null; 5 } catch (IOException e) { 6 System.err.println("Error with obj : " + obj.toString()); 7 } Faire du code qui marche NullPointerException !
  • 21. 4 account = (BankAccount) service.getProduct(this.name); 5 account.deposit(); 1 public void affiche(BankAccount account, ProductService service) { 2 System.out.println("Bank Account : "+this.name); 3 System.out.println("Autres informations : "); 4 account = (BankAccount) service.getProduct(this.name); 5 account.deposit(); 6 System.out.println(account); 7 System.out.println("=== FIN ==="); 8 9 } Code simple HTTP://EN.WIKIPEDIA.ORG/WIKI/FILE:JEU_DE_MIKADO.JPG
  • 22. 4 account = (BankAccount) service.getProduct(this.name); 5 account.deposit(); 1 public void affiche(BankAccount account, ProductService service) { 2 System.out.println("Bank Account : "+this.name); 3 System.out.println("Autres informations : "); 4 account = (BankAccount) service.getProduct(this.name); 5 account.deposit(); 6 System.out.println(account); 7 System.out.println("=== FIN ==="); 8 9 } Code simple HTTP://EN.WIKIPEDIA.ORG/WIKI/FILE:JEU_DE_MIKADO.JPG
  • 23. 4 account = (BankAccount) service.getProduct(this.name); 5 account.deposit(); 1 public void affiche(BankAccount account, ProductService service) { 2 System.out.println("Bank Account : "+this.name); 3 System.out.println("Autres informations : "); 4 account = (BankAccount) service.getProduct(this.name); 5 account.deposit(); 6 System.out.println(account); 7 System.out.println("=== FIN ==="); 8 9 } Code simple HTTP://EN.WIKIPEDIA.ORG/WIKI/FILE:JEU_DE_MIKADO.JPG
  • 24.
  • 25.
  • 26. C’est compliqué de faire simple un test une évolution
  • 27.
  • 28.
  • 30. Je vous prend dans mon équipe !
  • 39. Toujours faire le test cassant avant le test passant (pour tester le test)
  • 40. TEST UNITAIRE tester la plus petite unité de code possible
  • 41. TEST UNITAIRE tester la plus petite unité de code possible SIMPLE
  • 42. TEST UNITAIRE tester la plus petite unité de code possible SIMPLEFEEDBACK
  • 43. TEST UNITAIRE tester la plus petite unité de code possible SIMPLEFEEDBACKCOÛT
  • 44.
  • 47. 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 } 3 bankAccount.setBalance(50); Test d’abord !
  • 48. 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 } 3 bankAccount.setBalance(50); Test d’abord !
  • 49. 5 boolean result = bankAccount.deposit(1000); 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 !
  • 50. 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 ! 7 assertTrue(result); 8 assertEquals(1050, bankAccount.getBalance());
  • 51. Test d’abord ! 1 boolean deposit(int amount) { 2 return false; 3 }
  • 52. Test d’abord ! 1 boolean deposit(int amount) { 2 return false; 3 }
  • 53. Test d’abord ! 1 boolean deposit(int amount) { 2 bal = bal + amount; 3 return true; 4 }
  • 54. Test d’abord ! 1 boolean deposit(int amount) { 2 bal = bal + amount; 3 return true; 4 }
  • 55. 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 }
  • 56. 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 } 3 bankAccount.setBalance(100);
  • 57. 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 } 5 boolean result = bankAccount.deposit(-20);
  • 58. 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 } 7 assertFalse(result); 8 assertEquals(100, bankAccount.getBalance());
  • 59. Test d’abord ! 1 boolean deposit(int amount) { 2 bal = bal + amount; 3 return true; 4 }
  • 60. Test d’abord ! 1 boolean deposit(int amount) { 2 bal = bal + amount; 3 return true; 4 }
  • 61. Test d’abord ! 1 boolean deposit(int amount) { 2 if(amount < 0) { 3 return false; 4 } 5 bal = bal + amount; 6 return true; 7 }
  • 62. Test d’abord ! 1 boolean deposit(int amount) { 2 if(amount < 0) { 3 return false; 4 } 5 bal = bal + amount; 6 return true; 7 }
  • 63. Acteur / Action / Assertion
  • 64. 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 }
  • 65. 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 3 bankAccount.setBalance(100); Acteur
  • 66. 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 5 boolean result = bankAccount.deposit(-20); Action
  • 67. 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 7 assertFalse(result); 8 assertEquals(100, bankAccount.getBalance()); Assertions
  • 68. KISS
  • 69. KISSKEEP IT SIMPLE (AND STUPID)
  • 70. KISSKEEP IT SIMPLE (AND STUPID)
  • 71. 7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99"); 8 9 // Vérifier. 10 Assert.assertNotNull("Extra non trouvé.", targetDTO); 11 Assert.assertEquals("Les accountId doivent être identiques.", 12 "ABC99", targetDTO.getAccountId()); 1 @Test 2 public void testGetCustomerOK() { 3 4 LOGGER.info("======= testGetCustomerOK starting..."); 5 6 try { 7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99"); 8 9 // Vérifier. 10 Assert.assertNotNull("Extra non trouvé.", targetDTO); 11 Assert.assertEquals("Les accountId doivent être identiques.", 12 "ABC99", targetDTO.getAccountId()); 13 14 } catch (CustomerBusinessException exception) { 15 LOGGER.error("CustomerBusinessException : {}", 16 exception.getCause()); 17 Assert.fail(exception.getMessage()); 18 } catch (UnavailableResourceException exception) { 19 LOGGER.error("UnavailableResourceException : {}", 20 exception.getMessage()); 21 Assert.fail(exception.getMessage()); 22 } catch (UnexpectedException exception) { 23 LOGGER.error("UnexpectedException : {}" + 24 exception.getMessage()); 25 Assert.fail(exception.getMessage()); 26 } catch (Exception exception) { 27 LOGGER.error("CRASH : " + exception.getMessage()); 28 Assert.fail(exception.getMessage()); 29 } 30 31 LOGGER.info("======= testGetCustomerOK done."); 32 }
  • 72. 7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99"); 8 9 // Vérifier. 10 Assert.assertNotNull("Extra non trouvé.", targetDTO); 11 Assert.assertEquals("Les accountId doivent être identiques.", 12 "ABC99", targetDTO.getAccountId()); 1 @Test 2 public void testGetCustomerOK() { 3 4 LOGGER.info("======= testGetCustomerOK starting..."); 5 6 try { 7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99"); 8 9 // Vérifier. 10 Assert.assertNotNull("Extra non trouvé.", targetDTO); 11 Assert.assertEquals("Les accountId doivent être identiques.", 12 "ABC99", targetDTO.getAccountId()); 13 14 } catch (CustomerBusinessException exception) { 15 LOGGER.error("CustomerBusinessException : {}", 16 exception.getCause()); 17 Assert.fail(exception.getMessage()); 18 } catch (UnavailableResourceException exception) { 19 LOGGER.error("UnavailableResourceException : {}", 20 exception.getMessage()); 21 Assert.fail(exception.getMessage()); 22 } catch (UnexpectedException exception) { 23 LOGGER.error("UnexpectedException : {}" + 24 exception.getMessage()); 25 Assert.fail(exception.getMessage()); 26 } catch (Exception exception) { 27 LOGGER.error("CRASH : " + exception.getMessage()); 28 Assert.fail(exception.getMessage()); 29 } 30 31 LOGGER.info("======= testGetCustomerOK done."); 32 }
  • 73. 1 @Test 2 public void testGetCustomerOK() { 3 4 LOGGER.info("======= testGetCustomerOK starting..."); 5 6 try { 7 CustomerDTO targetDTO = this.serviceImpl.getCustomer("ABC99"); 8 9 // Vérifier. 10 Assert.assertNotNull("Extra non trouvé.", targetDTO); 11 Assert.assertEquals("Les accountId doivent être identiques.", 12 "ABC99", targetDTO.getAccountId()); 13 14 } catch (CustomerBusinessException exception) { 15 LOGGER.error("CustomerBusinessException : {}", 16 exception.getCause()); 17 Assert.fail(exception.getMessage()); 18 } catch (UnavailableResourceException exception) { 19 LOGGER.error("UnavailableResourceException : {}", 20 exception.getMessage()); 21 Assert.fail(exception.getMessage()); 22 } catch (UnexpectedException exception) { 23 LOGGER.error("UnexpectedException : {}" + 24 exception.getMessage()); 25 Assert.fail(exception.getMessage()); 26 } catch (Exception exception) { 27 LOGGER.error("CRASH : " + exception.getMessage()); 28 Assert.fail(exception.getMessage()); 29 } 30 31 LOGGER.info("======= testGetCustomerOK done."); 32 } 14 } catch (CustomerBusinessException exception) { 15 LOGGER.error("CustomerBusinessException : {}", 16 exception.getCause()); 17 Assert.fail(exception.getMessage()); 18 } catch (UnavailableResourceException exception) { 19 LOGGER.error("UnavailableResourceException : {}", 20 exception.getMessage()); 21 Assert.fail(exception.getMessage()); 22 } catch (UnexpectedException exception) { 23 LOGGER.error("UnexpectedException : {}" + 24 exception.getMessage()); 25 Assert.fail(exception.getMessage()); 26 } catch (Exception exception) { 27 LOGGER.error("CRASH : " + exception.getMessage()); 28 Assert.fail(exception.getMessage()); 29 } 30 31 LOGGER.info("======= testGetCustomerOK done."); BRUIT
  • 74. 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 }
  • 77. JUNIT + MOCKITO + ASSERTJ
  • 78. JUNIT + MOCKITO + ASSERTJ
  • 79. Mock ? simulacre se fait passer pour ce qu’il n’est pas comportement paramétrable
  • 93. NOUVEAU CODE = NOUVEAU TEST
  • 94. NOUVEAU BUG = NOUVEAU TEST
  • 95. 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 }
  • 96. 1 public Object getProduct(String id) { 2 Object obj = null; 3 try { 4 obj = networkService.getObject("product", id); 5 } catch (IOException e) { 6 System.err.println("Error with obj : " + obj.toString()); 7 } 8 return obj; 9 } nouveau bug = nouveau test 6 System.err.println("Error with obj : " + obj.toString()); LE BUG EST ICI !
  • 97. nouveau bug = nouveau test 1 @Test 2 public void can_return_null_when_ioexception() throws IOException { 3 Mockito.doThrow(IOException.class) 4 .when(networkService).getObject("product", "azerty"); 5 6 Object product = service.getProduct("azerty"); 7 8 assertThat(product).isNull(); 9 }
  • 98. 3 Mockito.doThrow(IOException.class) 4 .when(networkService).getObject("product", "azerty"); 1 @Test 2 public void can_return_null_when_ioexception() throws IOException { 3 Mockito.doThrow(IOException.class) 4 .when(networkService).getObject("product", "azerty"); 5 6 Object product = service.getProduct("azerty"); 7 8 assertThat(product).isNull(); 9 } nouveau bug = nouveau test
  • 99. 1 @Test 2 public void can_return_null_when_ioexception() throws IOException { 3 Mockito.doThrow(IOException.class) 4 .when(networkService).getObject("product", "azerty"); 5 6 Object product = service.getProduct("azerty"); 7 8 assertThat(product).isNull(); 9 } 6 Object product = service.getProduct("azerty"); nouveau bug = nouveau test
  • 100. 8 assertThat(product).isNull(); 1 @Test 2 public void can_return_null_when_ioexception() throws IOException { 3 Mockito.doThrow(IOException.class) 4 .when(networkService).getObject("product", "azerty"); 5 6 Object product = service.getProduct("azerty"); 7 8 assertThat(product).isNull(); 9 } nouveau bug = nouveau test
  • 101. 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 }
  • 102. 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 }
  • 103. 1 public Object getProduct(String id) { 2 Object obj = null; 3 try { 4 obj = networkService.getObject("product", id); 5 } catch (IOException e) { 6 System.err.println("Error with obj : " + obj.toString()); 7 } 8 return obj; 9 } nouveau bug = nouveau test 6 System.err.println("Error with obj : " + obj.toString()); LE BUG EST TOUJOURS ICI !
  • 104. 1 public Object getProduct(String id) { 2 Object obj = null; 3 try { 4 obj = networkService.getObject("product", id); 5 } catch (IOException e) { 6 System.err.println("Error with obj with id: " + id); 7 } 8 return obj; 9 } nouveau bug = nouveau test 6 System.err.println("Error with obj with id: " + id);
  • 105. nouveau bug = nouveau test 1 public Object getProduct(String id) { 2 Object obj = null; 3 try { 4 obj = networkService.getObject("product", id); 5 } catch (IOException e) { 6 System.err.println("Error with obj with id: " + id); 7 } 8 return obj; 9 } 6 System.err.println("Error with obj with id: " + id);
  • 106. Laissez votre câble tranquille
  • 107. TESTER DOIT ÊTRE SIMPLE
  • 108. 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 }
  • 109. 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" +
  • 110.
  • 111. 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 }
  • 112. 1 /** 2 * 3 * @param xml : document xml représentant le swap 4 * @return objet Swap 5 */ 6 public Swap parse(String xml) { 7 Swap swap = new Swap(); 8 String currency = getNodeValue("/swap/currency", xml); 9 swap.setCurrency(currency); [...] /* beaucoup de code... */ 530 Date d = new Date(); 531 if(test == 1) { 532 if(d.after(spotDate)) { 533 swap.setType("IRS"); 534 } else { 535 swap.setType("CURVE"); 536 } 537 } else if (test == 2) { 538 if(d.after(spotDate)) { 539 swap.setType("IRS"); 540 } else { 541 swap.setType("CURVE"); 542 } 543 } [...] /* encore beaucoup de code... */ 1135 return swap; 1136 } code complexe 531 if(test == 1) { 532 if(d.after(spotDate)) { 533 swap.setType("IRS"); 534 } else { 535 swap.setType("CURVE"); 536 } 537 } else if (test == 2) { 538 if(d.after(spotDate)) { 539 swap.setType("IRS"); 540 } else { 541 swap.setType("CURVE"); 542 } 543 } EXTRACT METHOD !
  • 113. 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 }
  • 114. 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 }
  • 115. LE CODE DOIT ÊTRE MODULAIRE
  • 116. 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 }
  • 117. 1 public class ProductService { 2 3 private static ProductService instance = new ProductService(); 4 5 private DAOService daoService; 6 7 private ProductService() { 8 System.out.println("ProductService constructor"); 9 daoService = DAOService.getInstance(); 10 } 11 12 public static ProductService getInstance() { 13 return instance; 14 } 15 16 17 18 public Object getProduct(String id) { 19 return daoService.getObject("product", id); 20 } 21 } Singleton 3 private static ProductService instance = new ProductService();
  • 118. 1 public class ProductService { 2 3 private static ProductService instance = new ProductService(); 4 5 private DAOService daoService; 6 7 private ProductService() { 8 System.out.println("ProductService constructor"); 9 daoService = DAOService.getInstance(); 10 } 11 12 public static ProductService getInstance() { 13 return instance; 14 } 15 16 17 18 public Object getProduct(String id) { 19 return daoService.getObject("product", id); 20 } 21 } Singleton 7 private ProductService() { 9 daoService = DAOService.getInstance(); 10 }
  • 119. 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 }
  • 126. 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 }
  • 127. 1 public void validateSwap(String id) { 2 Swap swap = (Swap) ProductService.getInstance().getProduct(id); 3 swap.updateState("VALIDATE"); 4 ProductService.getInstance().save(swap); 5 } Singleton ProductService.getInstance() 4 ProductService.getInstance() COUPLAGE FORT
  • 128. 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 }
  • 129. 1 private ProductService productService; 2 3 public void setProductService(ProductService injectedService) { 4 this.productService = injectedService; 5 } 6 7 public void validateSwap(String id) { 8 Swap swap = (Swap) productService.getProduct(id); 9 swap.updateState("VALIDATE"); 10 productService.save(swap); 11 } Injection 3 public void setProductService(ProductService injectedService) { 4 this.productService = injectedService; 5 } INJECTION
  • 130. 1 private ProductService productService; 2 3 public void setProductService(ProductService injectedService) { 4 this.productService = injectedService; 5 } 6 7 public void validateSwap(String id) { 8 Swap swap = (Swap) productService.getProduct(id); 9 swap.updateState("VALIDATE"); 10 productService.save(swap); 11 } Injection 8 Swap swap = (Swap) productService.getProduct(id); UTILISATION
  • 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 }
  • 132. 1 @InjectMocks 2 private BankAccount bankAccount; 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 12 Mockito.doNothing().when(productService).save(swap); 13 14 bankAccount.validateSwap("fakeId"); 15 16 assertEquals("VALIDATE", swap.getState()); 17 } Injection 4 @Mock 5 private ProductService productService; MOCK
  • 133. 1 @InjectMocks 2 private BankAccount bankAccount; 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 12 Mockito.doNothing().when(productService).save(swap); 13 14 bankAccount.validateSwap("fakeId"); 15 16 assertEquals("VALIDATE", swap.getState()); 17 } Injection 1 @InjectMocks 2 private BankAccount bankAccount; INJECTION AUTOMATIQUE DES MOCKS
  • 134. 1 @InjectMocks 2 private BankAccount bankAccount; 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 12 Mockito.doNothing().when(productService).save(swap); 13 14 bankAccount.validateSwap("fakeId"); 15 16 assertEquals("VALIDATE", swap.getState()); 17 } Injection 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 12 Mockito.doNothing().when(productService).save(swap);
  • 135. 1 @InjectMocks 2 private BankAccount bankAccount; 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 12 Mockito.doNothing().when(productService).save(swap); 13 14 bankAccount.validateSwap("fakeId"); 15 16 assertEquals("VALIDATE", swap.getState()); 17 } 14 bankAccount.validateSwap("fakeId"); Injection
  • 136. Injection 1 @InjectMocks 2 private BankAccount bankAccount; 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 12 Mockito.doNothing().when(productService).save(swap); 13 14 bankAccount.validateSwap("fakeId"); 15 16 assertEquals("VALIDATE", swap.getState()); 17 } 16 assertEquals("VALIDATE", swap.getState());
  • 139. 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 }
  • 140. 1 public void validateSwap(String id) { 2 Swap swap = (Swap) ProductService.getInstance().getProduct(id); 3 swap.updateState("VALIDATE"); 4 ProductService.getInstance().save(swap); 5 } Sans injecteur ? ProductService.getInstance() 4 ProductService.getInstance() EXTRACT METHOD !
  • 141. 1 public ProductService getProductService() { 2 return ProductService.getInstance(); 3 } 4 5 public void validateSwap(String id) { 6 Swap swap = (Swap) getProductService().getProduct(id); 7 swap.updateState("VALIDATE"); 8 getProductService().save(swap); 9 } Sans injecteur ? 1 public ProductService getProductService() { 2 return ProductService.getInstance(); 3 } getProductService() 8 getProductService()
  • 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. 1 @Spy 2 private BankAccount bankAccount = new BankAccount("", 23, "", 3); 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(productService).when(bankAccount).getProductService(); 12 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 14 Mockito.doNothing().when(productService).save(swap); 15 16 bankAccount.validateSwap("fakeId"); 17 18 assertEquals("VALIDATE", swap.getState()); 19 } Sans injecteur ? 1 @Spy 2 private BankAccount bankAccount = new BankAccount("", 23, "", 3); REDÉFINITION DES MÉTHODES POSSIBLE
  • 144. 1 @Spy 2 private BankAccount bankAccount = new BankAccount("", 23, "", 3); 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(productService).when(bankAccount).getProductService(); 12 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 14 Mockito.doNothing().when(productService).save(swap); 15 16 bankAccount.validateSwap("fakeId"); 17 18 assertEquals("VALIDATE", swap.getState()); 19 } Sans injecteur ? 11 Mockito.doReturn(productService).when(bankAccount).getProductService();
  • 145. 1 @Spy 2 private BankAccount bankAccount = new BankAccount("", 23, "", 3); 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(productService).when(bankAccount).getProductService(); 12 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 14 Mockito.doNothing().when(productService).save(swap); 15 16 bankAccount.validateSwap("fakeId"); 17 18 assertEquals("VALIDATE", swap.getState()); 19 } Sans injecteur ? 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 14 Mockito.doNothing().when(productService).save(swap);
  • 146. Sans injecteur ? 1 @Spy 2 private BankAccount bankAccount = new BankAccount("", 23, "", 3); 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(productService).when(bankAccount).getProductService(); 12 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 14 Mockito.doNothing().when(productService).save(swap); 15 16 bankAccount.validateSwap("fakeId"); 17 18 assertEquals("VALIDATE", swap.getState()); 19 } 16 bankAccount.validateSwap("fakeId");
  • 147. Sans injecteur ? 1 @Spy 2 private BankAccount bankAccount = new BankAccount("", 23, "", 3); 3 4 @Mock 5 private ProductService productService; 6 7 @Test 8 public void can_validate_swap() { 9 Swap swap = new Swap(); 10 11 Mockito.doReturn(productService).when(bankAccount).getProductService(); 12 13 Mockito.doReturn(swap).when(productService).getProduct("fakeId"); 14 Mockito.doNothing().when(productService).save(swap); 15 16 bankAccount.validateSwap("fakeId"); 17 18 assertEquals("VALIDATE", swap.getState()); 19 } 18 assertEquals("VALIDATE", swap.getState());
  • 149. LANCER UN TEST DOIT ÊTRE FACILE
  • 150. Tests dans son IDE ECLIPSE NETBEANS INTELLIJ
  • 151. LE CODE DOIT TOUJOURS ÊTRE DÉPLOYABLE
  • 153. Intégration continue [INFO] --------------------------------------------- [INFO] BUILD SUCCESS [INFO] ---------------------------------------------
  • 155. Intégration continue [INFO] --------------------------------------------- [INFO] BUILD FAILURE [INFO] ---------------------------------------------
  • 156. Intégration continue [INFO] --------------------------------------------- [INFO] BUILD FAILURE [INFO] --------------------------------------------- WORKS ON MY MACHINE
  • 161.
  • 162. AVOIR LA BONNE COUVERTURE
  • 164. 80%DE COUVERTURE DE GETTER/SETTER
  • 166. binomage (pair hero) philosophie différente pour code identique HTTP://WWW.SXC.HU/PHOTO/959091
  • 167. binomage (pair hero) philosophie différente pour code identiqueLES COMMANDES
  • 168. binomage (pair hero) philosophie différente pour code identique LE PLAN DE VOL
  • 174. bref
  • 176. 6 mois plus tard...
  • 177. Bugs 0 22,5 45 67,5 90 Janvier Février Mars Avril Mai Juin Bugs Satisfaction
  • 178. Bugs 0 22,5 45 67,5 90 Janvier Février Mars Avril Mai Juin Bugs Satisfaction
  • 179. Bugs 0 22,5 45 67,5 90 Janvier Février Mars Avril Mai Juin Bugs Satisfaction
  • 180. Bugs 0 22,5 45 67,5 90 Janvier Février Mars Avril Mai Juin Bugs Satisfaction
  • 181. Bugs 0 22,5 45 67,5 90 Janvier Février Mars Avril Mai Juin Bugs Satisfaction
  • 182. Bugs 0 22,5 45 67,5 90 Janvier Février Mars Avril Mai Juin Bugs Satisfaction
  • 183. BRAVO À NOTRE ÉQUIPE DE CHOC !
  • 188. (même si il est «trop» simple)
  • 190. ...AVANT DE GAGNER DES COMPÉTITIONS HTTP://WWW.SXC.HU/PHOTO/1008962
  • 194. It’s Pizza Time !Drink
  • 196. référence jenkins : http://jenkins-ci.org/ assertj : https://github.com/joel-costigliola/assertj mockito : https://code.google.com/p/mockito/ démo : http://parleys.com/play/5148922a0364bc17fc56c85a/about