SlideShare une entreprise Scribd logo
1  sur  196
Télécharger pour lire hors ligne
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

Contenu connexe

Tendances

LISA QooxdooTutorial Slides
LISA QooxdooTutorial SlidesLISA QooxdooTutorial Slides
LISA QooxdooTutorial SlidesTobias 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 fishyIgor 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 TestsTomek 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 212Mahmoud Samir Fayed
 
Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101Javascript Testing with Jasmine 101
Javascript Testing with Jasmine 101Roy Yu
 
Extreme JavaScript Performance
Extreme JavaScript PerformanceExtreme JavaScript Performance
Extreme JavaScript PerformanceThomas Fuchs
 
Node.js flow control
Node.js flow controlNode.js flow control
Node.js flow controlSimon 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 TestingSaú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 SeasonsBaruch Sadogursky
 
Kotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresKotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresiMasters
 
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 Testingjeresig
 
NetBeans Plugin Development: JRebel Experience Report
NetBeans Plugin Development: JRebel Experience ReportNetBeans Plugin Development: JRebel Experience Report
NetBeans Plugin Development: JRebel Experience ReportAnton 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 TestingKissy Team
 
Taking a Test Drive
Taking a Test DriveTaking a Test Drive
Taking a Test DriveGraham Lee
 
Testing My Patience
Testing My PatienceTesting My Patience
Testing My PatienceAdam Lowry
 
201913001 khairunnisa progres_harian
201913001 khairunnisa progres_harian201913001 khairunnisa progres_harian
201913001 khairunnisa progres_harianKhairunnisaPekanbaru
 

Tendances (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
 

En vedette

Amélioration continue, c'est l'affaire de tous !
Amélioration continue, c'est l'affaire de tous !Amélioration continue, c'est l'affaire de tous !
Amélioration continue, c'est l'affaire de tous !SOAT
 
JAVA 8 : Migration et enjeux stratégiques en entreprise
JAVA 8 : Migration et enjeux stratégiques en entrepriseJAVA 8 : Migration et enjeux stratégiques en entreprise
JAVA 8 : Migration et enjeux stratégiques en entrepriseSOAT
 
3/3 : The path to CDI 2.0 - Antoine Sabot-Durand
3/3 : The path to CDI 2.0 - Antoine Sabot-Durand3/3 : The path to CDI 2.0 - Antoine Sabot-Durand
3/3 : The path to CDI 2.0 - Antoine Sabot-DurandSOAT
 
1/3 : introduction to CDI - Antoine Sabot-Durand
1/3 : introduction to CDI - Antoine Sabot-Durand1/3 : introduction to CDI - Antoine Sabot-Durand
1/3 : introduction to CDI - Antoine Sabot-DurandSOAT
 
L'entreprise libérée
L'entreprise libéréeL'entreprise libérée
L'entreprise libéréeSOAT
 
Test unitaires visual studio
Test unitaires visual studioTest unitaires visual studio
Test unitaires visual studioSOAT
 
ARCHITECTURE MICROSERVICE : TOUR D’HORIZON DU CONCEPT ET BONNES PRATIQUES
ARCHITECTURE MICROSERVICE : TOUR D’HORIZON DU CONCEPT ET BONNES PRATIQUESARCHITECTURE MICROSERVICE : TOUR D’HORIZON DU CONCEPT ET BONNES PRATIQUES
ARCHITECTURE MICROSERVICE : TOUR D’HORIZON DU CONCEPT ET BONNES PRATIQUESSOAT
 

En vedette (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
 

Similaire à 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_170113SOAT
 
Como NÃO testar o seu projeto de Software. DevDay 2014
Como NÃO testar o seu projeto de Software. DevDay 2014Como NÃO testar o seu projeto de Software. DevDay 2014
Como NÃO testar o seu projeto de Software. DevDay 2014alexandre freire
 
An Introduction to Property Based Testing
An Introduction to Property Based TestingAn Introduction to Property Based Testing
An Introduction to Property Based TestingC4Media
 
Javascript Everywhere
Javascript EverywhereJavascript Everywhere
Javascript EverywherePascal Rettig
 
Aaron Bedra - Effective Software Security Teams
Aaron Bedra - Effective Software Security TeamsAaron Bedra - Effective Software Security Teams
Aaron Bedra - Effective Software Security Teamscentralohioissa
 
Boosting Your Testing Productivity with Groovy
Boosting Your Testing Productivity with GroovyBoosting Your Testing Productivity with Groovy
Boosting Your Testing Productivity with GroovyJames Williams
 
Javaone2008 Bof 5101 Groovytesting
Javaone2008 Bof 5101 GroovytestingJavaone2008 Bof 5101 Groovytesting
Javaone2008 Bof 5101 GroovytestingAndres Almiray
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleThierry Wasylczenko
 
Unit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMockUnit testing in iOS featuring OCUnit, GHUnit & OCMock
Unit testing in iOS featuring OCUnit, GHUnit & OCMockRobot Media
 
Testing the waters of iOS
Testing the waters of iOSTesting the waters of iOS
Testing the waters of iOSKremizas Kostas
 
Test Infected Presentation
Test Infected PresentationTest Infected Presentation
Test Infected Presentationwillmation
 
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 FornalQA or the Highway
 
PHPunit and you
PHPunit and youPHPunit and you
PHPunit and youmarkstory
 
Developer Test - Things to Know
Developer Test - Things to KnowDeveloper Test - Things to Know
Developer Test - Things to Knowvilniusjug
 
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 2017panagenda
 
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 DevelopmentAll Things Open
 

Similaire à 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
 
Boosting Your Testing Productivity with Groovy
Boosting Your Testing Productivity with GroovyBoosting Your Testing Productivity with Groovy
Boosting Your Testing Productivity with Groovy
 
Javaone2008 Bof 5101 Groovytesting
Javaone2008 Bof 5101 GroovytestingJavaone2008 Bof 5101 Groovytesting
Javaone2008 Bof 5101 Groovytesting
 
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
 

Plus de SOAT

Back from Microsoft //Build 2018
Back from Microsoft //Build 2018Back from Microsoft //Build 2018
Back from Microsoft //Build 2018SOAT
 
2/3 : CDI advanced - Antoine Sabot-Durand
2/3 : CDI advanced - Antoine Sabot-Durand2/3 : CDI advanced - Antoine Sabot-Durand
2/3 : CDI advanced - Antoine Sabot-DurandSOAT
 
Angular JS - Paterne Gaye-Guingnido
Angular JS - Paterne Gaye-Guingnido Angular JS - Paterne Gaye-Guingnido
Angular JS - Paterne Gaye-Guingnido SOAT
 
Dans l'enfer du Web Mobile - un retour d'expérience - Mathieu Parisot
Dans l'enfer du Web Mobile - un retour d'expérience - Mathieu ParisotDans l'enfer du Web Mobile - un retour d'expérience - Mathieu Parisot
Dans l'enfer du Web Mobile - un retour d'expérience - Mathieu ParisotSOAT
 
RxJava, Getting Started - David Wursteisen - 16 Octobre 2014
RxJava, Getting Started - David Wursteisen - 16 Octobre 2014RxJava, Getting Started - David Wursteisen - 16 Octobre 2014
RxJava, Getting Started - David Wursteisen - 16 Octobre 2014SOAT
 
L'impact du Responsive Web Design sur vos équipes projet - Mathieu Parisot - ...
L'impact du Responsive Web Design sur vos équipes projet - Mathieu Parisot - ...L'impact du Responsive Web Design sur vos équipes projet - Mathieu Parisot - ...
L'impact du Responsive Web Design sur vos équipes projet - Mathieu Parisot - ...SOAT
 
Nio sur Netty par Mouhcine Moulou - 3 avril 2014
Nio sur Netty par Mouhcine Moulou - 3 avril 2014Nio sur Netty par Mouhcine Moulou - 3 avril 2014
Nio sur Netty par Mouhcine Moulou - 3 avril 2014SOAT
 
20140123 java8 lambdas_jose-paumard-soat
20140123 java8 lambdas_jose-paumard-soat20140123 java8 lambdas_jose-paumard-soat
20140123 java8 lambdas_jose-paumard-soatSOAT
 
Développer des applications iOS et Android avec c# grâce à Xamarin par Cyril ...
Développer des applications iOS et Android avec c# grâce à Xamarin par Cyril ...Développer des applications iOS et Android avec c# grâce à Xamarin par Cyril ...
Développer des applications iOS et Android avec c# grâce à Xamarin par Cyril ...SOAT
 
Amazon Web Service par Bertrand Lehurt - 11 mars 2014
Amazon Web Service par Bertrand Lehurt - 11 mars 2014Amazon Web Service par Bertrand Lehurt - 11 mars 2014
Amazon Web Service par Bertrand Lehurt - 11 mars 2014SOAT
 
ASP.Net Web API - Léonard Labat (18 février 2014)
ASP.Net Web API - Léonard Labat (18 février 2014)ASP.Net Web API - Léonard Labat (18 février 2014)
ASP.Net Web API - Léonard Labat (18 février 2014)SOAT
 
Xamarin et le développement natif d’applications Android, iOS et Windows en C#
 Xamarin et le développement natif d’applications Android, iOS et Windows en C# Xamarin et le développement natif d’applications Android, iOS et Windows en C#
Xamarin et le développement natif d’applications Android, iOS et Windows en C#SOAT
 
A la découverte du Responsive Web Design par Mathieu Parisot - Soat
A la découverte du Responsive Web Design par Mathieu Parisot - SoatA la découverte du Responsive Web Design par Mathieu Parisot - Soat
A la découverte du Responsive Web Design par Mathieu Parisot - SoatSOAT
 
MongoDB : la base NoSQL qui réinvente la gestion de données
MongoDB : la base NoSQL qui réinvente la gestion de donnéesMongoDB : la base NoSQL qui réinvente la gestion de données
MongoDB : la base NoSQL qui réinvente la gestion de donnéesSOAT
 
Soirée 3T Soat - Asp.net MVC
Soirée 3T Soat - Asp.net MVCSoirée 3T Soat - Asp.net MVC
Soirée 3T Soat - Asp.net MVCSOAT
 
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 MinhotoSOAT
 
Facilitez vous la vie - Ricardo Minhoto
Facilitez vous la vie - Ricardo MinhotoFacilitez vous la vie - Ricardo Minhoto
Facilitez vous la vie - Ricardo MinhotoSOAT
 
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 120613SOAT
 
Transition Agile technique à grande échelle
Transition Agile technique à grande échelleTransition Agile technique à grande échelle
Transition Agile technique à grande échelleSOAT
 

Plus de 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
 

Dernier

Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfOrbitshub
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...apidays
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Victor Rentea
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsNanddeep Nachan
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusZilliz
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamUiPathCommunity
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Victor Rentea
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdfSandro Moreira
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWERMadyBayot
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistandanishmna97
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...apidays
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 

Dernier (20)

Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 

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