SlideShare a Scribd company logo
1 of 44
Pratiques avancées de testsNathaniel Richand Scrumday France 2011
Merci aux sponsors du Scrumday ! Sponsors Platinum Sponsors Gold Parrainage :
Restons pragmatique ! Doit-on : Tester les messages d’exceptions ? Tester les messages de logs ? Contexte
TDD a beaucoup aidé
Certains tests vieillissent mal
Tests illisibleset fragiles Exemple
Constat : TDD peut : devenir un frein, diminuer le rythme Augmenter la rigidité du code
Améliorer la lisibilité
Tip1 : le nom donnel’intention testChoose1() testChoose2() whenSelectNullIItem_ShouldThrowAnException() whenSelectTwoItems_ShouldReturnTheSum()
Tip2 : Ne pas masquer les informationsutiles @DataSet publicclassBrokerDAOTestextendsUnitilsTestNG { @Test publicvoidtestGetNameByClauseInId() { BrokerDASbdao = newBrokerDAO(); JpaUnitils.injectEntityManagerInto(bdao);        List<String> brokers = bdao.getNameByClauseInId("in (1)"); assertEquals(brokers.size(), 1); assertEquals(brokers.get(0), "Kerviel");     } } WTF?
Tip3 : Masquer tout ce qui est inutile Setup & Teardown Fixture Creation method Creation Builder Static import
@Test publicvoidgenerateNomDeFichierNacXMLTest(){ //Given NacCreatorBOnacCreator = newNacCreatorBO(); //when     String nomFichier= 	nacCreator.generateNomDeFichierNacXML			(creerDateBlanchie(2010, 01, 02), "123456", creerDateBlanchie(2010, 03, 04), 10); //then assertThat(nomFichier).isEqualTo	("NAC_R_123456RE_020110_10_040310000000.xml"); }
NacCreatorBOnacCreator; @Before publicvoidinit(){ nacCreator= newNacCreatorBO(); } @Test publicvoidgenerateNomDeFichierNacXMLTest(){ //when   String nomFichier = nacCreator.generateNomDeFichierNacXML	(creerDateBlanchie(2010, 01, 02), "123456", creerDateBlanchie(2010, 03, 04), 10); //then assertThat(nomFichier).isEqualTo	("NAC_R_123456RE_020110_10_040310000000.xml"); }
@Test publicvoidtestParserIntraday(){     File file = new File("src/test/resources/fr/haramis/service/commons/util/Planning_Options.xls");    List<IntradaySchedule> listIntradays = null; InputStreamstream = null; try{ stream= newFileInputStream(file.getAbsolutePath());     } catch(FileNotFoundException e) { stream= null;     } if(stream != null){ try{ listIntradays= IntradayParser.parseExcelIntraday(stream, "DIRECT-T01");         } catch(HermesException e) { e.printStackTrace(); logger.error(e); Assert.fail();         } logger.info(" ListIntradaysSize() " +listIntradays.size()); Assert.assertEquals(8400, listIntradays.size()); for(IntradayScheduleintradaySchedule : listIntradays) { Assert.assertEquals(24, intradaySchedule.getIntraday().getIntradaySchedules().size());         }     } }
@Test publicvoidtestParserIntraday_OK() throws Exception{ //Given InputStreamstream = getStreamFromFile("Planning_Options.xls"); //When     List<IntradaySchedule> listIntradays = IntradayParser.parseExcelIntraday(stream, "DIRECT-T01"); //Then assertEquals(8400, listIntradays.size());     for(IntradayScheduleintradaySchedule : listIntradays) { assertEquals(24, intradaySchedule.getIntraday()  				.getIntradaySchedules().size());     } }
//Given Map<Date, BigDecimal> charges = newHashMap<Date, BigDecimal>(); charges.put(dateDebut_13_03_2010, newBigDecimal(QUANTITY_1000)); charges.put(addDaysToDate(dateDebut_13_03_2010, 1), newBigDecimal(QUANTITY_3000));
//Given Map<Date, BigDecimal> charges = newMapCharges<Date>()   .with(dateDebut_13_03_2010, QUANTITY_1000)   .and(addDaysToDate(dateDebut_13_03_2010, 1)						QUANTITY_3000) 	 .build();
/**  * Builder pour créer plus facilement des Map<Date, BigDecimal> ou des Map<String, BigDecimal>  */ privateclassMapCharges<T> { privateMap<T, BigDecimal> cdcMap = newHashMap<T, 							BigDecimal>();     publicMapCharges<T> with(T dateDebut, intquantity){         cdcMap.put(dateDebut, newBigDecimal(quantity));         returnthis;     }     publicMapCharges<T> and(T dateDebut, intquantity){         returnwith(dateDebut, quantity);     }     publicMap<T, BigDecimal> build(){         returncdcMap;     } }
Tip4 : try/catch fail() @Test publicvoidtestFindByStatutAndDate() { OrdreSpotDASdao = newOrdreSpotDAO(); try{ assertEquals(dao.findByDate("01/07/2008", "OK").size(), 2); assertEquals(dao.findByDate("01/07/2008", "KO").size(), 1); } catch (HaramisExceptione) { e.printStackTrace(); Assert.fail();   } }
@Test publicvoidtestFindByStatutAndDate() throwsHaramisException{ OrdreSpotDASdao = newOrdreSpotDAO(); assertEquals(dao.findByDate("01/07/2008", "OK").size(), 2); assertEquals(dao.findByDate("01/07/2008", "KO").size(), 1); }
Tip4 (bis) : if/else fail() if (sd.getTimeRef() == 0) { assertEquals(sd.getPrice(), "301"); } else{ fail("pas normal"); }
assertThat(sd.getTimeRef()).isEqualTo(0); assertEquals(sd.getPrice(), "301"); GuardAssert
Tip5 : Simili de toString() dans les assert assertEquals("Compagniedifferente : "+result.getId()+" / "+ result.getName() +" / "+ result.getLocation() , result, expectedCompany); assertThat(result).isEqualTo(expectedCompany);
Tip6 : Magic number, magic null //Given Site siteNord = createSite(NORD, 10); Site siteSud = createSite(SUD, 12); //When intaffectations = dao.selectAffectationsNord(siteNord, siteSud, null);  //Then assertThat(affectations).isEqualTo(10);
//Given Site siteNord = createSite(NORD, AFFECTATION_NORD); Site siteSud = createSite(SUD, AFFECTATION_SUD); //When intaffectations = dao.selectAffectationsNord(siteNord, siteSud, SITE_NULL);  //Then assertThat(affectations).isEqualTo(AFFECTATION_NORD);
Tip7 : Garder la même structure @Test publicvoidcalculTotalTest(){ //Given 	double[] volumes = {10.24556, 21, 43}; 	//When 	double total = PositionUtils.calculTotal(UNITE_TEMPS_HORAIRE, volumes); 	//Then assertThat(total).isEqualTo(74.24556); }
@Test publicvoidcalculerDateTest(){ //Given 	Date date = HaramisDateUtils.creerDateBlanchie(2010, 5, 19); //When 	String[] datesFormatees = PositionUtils.calculerDates(date, 1, 	UNITE_TEMPS_HORAIRE, ELECTRICTY); //Then assertThat(datesFormatees).hasSize(2); assertThat(datesFormatees[0]).isEqualTo("19/05/2010 01:00"); assertThat(datesFormatees[1]).isEqualTo("19/05/2010 02:00"); }
Tip8 : Faire de belles assertions Ne surtout pas faire :  assertFalse(toto == null); assertTrue(list.size() == 0); assertEquals(result, null);
File emptyFile = writeFile("emptyFile", ""); assertThat(emptyFile).hasSize(0); List<String> names = Arrays.asList("Bob", ”Vince", ”Nat"); assertThat(names)     .hasSize(3)    .contains("Vince")    .doesNotHaveDuplicates(); String nullString = null; assertThat(nullString).isNull(); http://docs.codehaus.org/display/FEST/Fluent+Assertions+Module
for (Companycie : companies) { Assert.assertFalse(cie.getStatus() 		.equalsIgnoreCase(ConstantsUtils.SIMPLE_STATUS_ANNULE) 		, "Cie " + cie.getId()); } assertThat(companies) 	.onProperty("status") 	.containsOnly(SIMPLE_STATUS_VALIDE);
Tip9 : Utiliser Spock def"I plus I should equal II"() { given:def calculator = newRomanCalculator()when:    def result = calculator.add("I", "I")           then:    result == "II" } http://code.google.com/p/spock/
def"The lowestnumbershould go at the end"() {   setup: defresult = calculator.add(a, b)expect:result == sum  where:     a   |  b  |  sum    "X"  | "I" | "XI"    "I"  | "X" | "XI"    "XX" | "I" | "XXI"    "XX" | "II"| "XXII"    "II" | "XX"| "XXII"   } http://www.wakaleo.com/blog/303-an-introduction-to-spock
Faire des tests plus robustes
Tip1 : Pas de duplication Cf. Tip 3 : Masquer tout ce qui est inutile Creation fixture Creation builder Test Helper Custom assertions
Tip2 : Tester un comportementà un seulendroit publicString formatResultToCSV(List<Object[]> positionsResultats) throwsParseException; privatestatic String[] calculerDeuxDates(Object[] ligne) throwsParseException; publicstatic String[] obtenirVolumes(Object[] ligne);
PublicString formatResultToCSV(List<Object[]> positionsResultats) throwsParseException { StringBuildersb = newStringBuilder();     for(Object[] ligne : positionsResultats) { String[] twoDates = calculerDeuxDates(ligne); String[] newLine = new String[ligne.length -1]; newLine[0] = twoDates[0]; newLine[1] = twoDates[1]; String[] volumes = PositionUtils.obtenirVolumes(ligne); System.arraycopy(volumes, 0, newLine, 2, volumes.length); for(String elementLigne : newLine) { sb.append(elementLigne+"|"); } } returnsb.toString(); }
Tip3 : Eviter la réflexion @Test publicvoid testReglesValidationHRM_118_KO() throws Exception { PortfolioManagerBOportfolioManagerBO = newPortfolioManagerBO(); Method reglesValidationHRM118 = null; PortfolioFormportfolioForm = newPortfolioForm(); portfolioManagerBO.setPortfolioForm(portfolioForm); reglesValidationHRM118 = ReflectHelper.getPrivateMethod(portfolioManagerBO, "reglesValidationHRM118");     reglesValidationHRM118.setAccessible(true);     reglesValidationHRM118.invoke(portfolioManagerBO); assertFalse(portfolioForm.isMessageAVisible()); assertFalse(portfolioForm.isPopupVisible()); }
@Test publicvoid testReglesValidationHRM_118_OK() throws Exception {     //Given PortfolioManagerBOportfolioManagerBO = newPortfolioManagerBO(); PortfolioFormportfolioForm = newPortfolioForm(); portfolioManagerBO.setPortfolioForm(portfolioForm);     //When     portfolioManagerBO.reglesValidationHRM118();     //Then assertFalse(portfolioForm.isMessageAVisible()); assertFalse(portfolioForm.isPopupVisible()); }
Tip4 : Quoi tester? “Bas niveau” : état privatestaticString formatValue(Object removeNull) { if(removeNull == null) {         return"";     }  else {         returnremoveNull.toString();     } }
“Haut niveau” : comportement public String getPointsHoraires(String dateDeb, String dateFin, String portFolios, String password) { passwordChecker.checkPassword(password);     List<Long> listIdPortfolio = convertPortfoliosIdToLong(portFolios);     List<Object[]> pointsResultats = executeCalculPointsPortefeuille( dateDeb, dateFin, listIdPortfolio);     String pointsCSV= formatResultToCSV(pointsResultats); returnpointsCSV; }
Bilan Aimez vos tests et ils vous le rendront Les principes “Clean code” s’appliquent également au code de test!
Ressources http://www.wakaleo.com/blog http://misko.hevery.com/
Merci nrichand@xebia.fr http://blog.xebia.fr

More Related Content

What's hot

The Ring programming language version 1.8 book - Part 90 of 202
The Ring programming language version 1.8 book - Part 90 of 202The Ring programming language version 1.8 book - Part 90 of 202
The Ring programming language version 1.8 book - Part 90 of 202Mahmoud Samir Fayed
 
The Ring programming language version 1.3 book - Part 50 of 88
The Ring programming language version 1.3 book - Part 50 of 88The Ring programming language version 1.3 book - Part 50 of 88
The Ring programming language version 1.3 book - Part 50 of 88Mahmoud Samir Fayed
 
The Ring programming language version 1.4 book - Part 17 of 30
The Ring programming language version 1.4 book - Part 17 of 30The Ring programming language version 1.4 book - Part 17 of 30
The Ring programming language version 1.4 book - Part 17 of 30Mahmoud Samir Fayed
 
Spring data access
Spring data accessSpring data access
Spring data access명철 강
 
The Ring programming language version 1.4 book - Part 18 of 30
The Ring programming language version 1.4 book - Part 18 of 30The Ring programming language version 1.4 book - Part 18 of 30
The Ring programming language version 1.4 book - Part 18 of 30Mahmoud Samir Fayed
 
The Ring programming language version 1.5.3 book - Part 77 of 184
The Ring programming language version 1.5.3 book - Part 77 of 184The Ring programming language version 1.5.3 book - Part 77 of 184
The Ring programming language version 1.5.3 book - Part 77 of 184Mahmoud Samir Fayed
 
The Ring programming language version 1.5.4 book - Part 59 of 185
The Ring programming language version 1.5.4 book - Part 59 of 185The Ring programming language version 1.5.4 book - Part 59 of 185
The Ring programming language version 1.5.4 book - Part 59 of 185Mahmoud Samir Fayed
 
VISUALIZAR REGISTROS EN UN JTABLE
VISUALIZAR REGISTROS EN UN JTABLEVISUALIZAR REGISTROS EN UN JTABLE
VISUALIZAR REGISTROS EN UN JTABLEDarwin Durand
 
Scala meetup
Scala meetupScala meetup
Scala meetup扬 明
 
Design pattern - part 3
Design pattern - part 3Design pattern - part 3
Design pattern - part 3Jieyi Wu
 
드로이드 나이츠 2018: RxJava 적용 팁 및 트러블 슈팅
드로이드 나이츠 2018: RxJava 적용 팁 및 트러블 슈팅드로이드 나이츠 2018: RxJava 적용 팁 및 트러블 슈팅
드로이드 나이츠 2018: RxJava 적용 팁 및 트러블 슈팅재춘 노
 
IP project for class 12 cbse
IP project for class 12 cbseIP project for class 12 cbse
IP project for class 12 cbsesiddharthjha34
 
Design pattern part 2 - structural pattern
Design pattern part 2 - structural patternDesign pattern part 2 - structural pattern
Design pattern part 2 - structural patternJieyi Wu
 
Tools and Techniques for Understanding Threading Behavior in Android*
Tools and Techniques for Understanding Threading Behavior in Android*Tools and Techniques for Understanding Threading Behavior in Android*
Tools and Techniques for Understanding Threading Behavior in Android*Intel® Software
 
Wwe Management System
Wwe Management SystemWwe Management System
Wwe Management SystemNeerajMudgal1
 
생산적인 개발을 위한 지속적인 테스트
생산적인 개발을 위한 지속적인 테스트생산적인 개발을 위한 지속적인 테스트
생산적인 개발을 위한 지속적인 테스트기룡 남
 

What's hot (20)

The Ring programming language version 1.8 book - Part 90 of 202
The Ring programming language version 1.8 book - Part 90 of 202The Ring programming language version 1.8 book - Part 90 of 202
The Ring programming language version 1.8 book - Part 90 of 202
 
The Ring programming language version 1.3 book - Part 50 of 88
The Ring programming language version 1.3 book - Part 50 of 88The Ring programming language version 1.3 book - Part 50 of 88
The Ring programming language version 1.3 book - Part 50 of 88
 
The Ring programming language version 1.4 book - Part 17 of 30
The Ring programming language version 1.4 book - Part 17 of 30The Ring programming language version 1.4 book - Part 17 of 30
The Ring programming language version 1.4 book - Part 17 of 30
 
Spring data access
Spring data accessSpring data access
Spring data access
 
The Ring programming language version 1.4 book - Part 18 of 30
The Ring programming language version 1.4 book - Part 18 of 30The Ring programming language version 1.4 book - Part 18 of 30
The Ring programming language version 1.4 book - Part 18 of 30
 
The Ring programming language version 1.5.3 book - Part 77 of 184
The Ring programming language version 1.5.3 book - Part 77 of 184The Ring programming language version 1.5.3 book - Part 77 of 184
The Ring programming language version 1.5.3 book - Part 77 of 184
 
The Ring programming language version 1.5.4 book - Part 59 of 185
The Ring programming language version 1.5.4 book - Part 59 of 185The Ring programming language version 1.5.4 book - Part 59 of 185
The Ring programming language version 1.5.4 book - Part 59 of 185
 
Writing Good Tests
Writing Good TestsWriting Good Tests
Writing Good Tests
 
662305 11
662305 11662305 11
662305 11
 
VISUALIZAR REGISTROS EN UN JTABLE
VISUALIZAR REGISTROS EN UN JTABLEVISUALIZAR REGISTROS EN UN JTABLE
VISUALIZAR REGISTROS EN UN JTABLE
 
Container adapters
Container adaptersContainer adapters
Container adapters
 
Scala meetup
Scala meetupScala meetup
Scala meetup
 
MaintainStaffTable
MaintainStaffTableMaintainStaffTable
MaintainStaffTable
 
Design pattern - part 3
Design pattern - part 3Design pattern - part 3
Design pattern - part 3
 
드로이드 나이츠 2018: RxJava 적용 팁 및 트러블 슈팅
드로이드 나이츠 2018: RxJava 적용 팁 및 트러블 슈팅드로이드 나이츠 2018: RxJava 적용 팁 및 트러블 슈팅
드로이드 나이츠 2018: RxJava 적용 팁 및 트러블 슈팅
 
IP project for class 12 cbse
IP project for class 12 cbseIP project for class 12 cbse
IP project for class 12 cbse
 
Design pattern part 2 - structural pattern
Design pattern part 2 - structural patternDesign pattern part 2 - structural pattern
Design pattern part 2 - structural pattern
 
Tools and Techniques for Understanding Threading Behavior in Android*
Tools and Techniques for Understanding Threading Behavior in Android*Tools and Techniques for Understanding Threading Behavior in Android*
Tools and Techniques for Understanding Threading Behavior in Android*
 
Wwe Management System
Wwe Management SystemWwe Management System
Wwe Management System
 
생산적인 개발을 위한 지속적인 테스트
생산적인 개발을 위한 지속적인 테스트생산적인 개발을 위한 지속적인 테스트
생산적인 개발을 위한 지속적인 테스트
 

Similar to 2011 nri-pratiques tests-avancees

Testing persistence in PHP with DbUnit
Testing persistence in PHP with DbUnitTesting persistence in PHP with DbUnit
Testing persistence in PHP with DbUnitPeter Wilcsinszky
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4Abed Bukhari
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy codeShriKant Vashishtha
 
Kickstarting SItes With a Custom Package
Kickstarting SItes With a Custom PackageKickstarting SItes With a Custom Package
Kickstarting SItes With a Custom PackageJeff Segars
 
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)David Gómez García
 
Windows Azure - Cloud Service Development Best Practices
Windows Azure - Cloud Service Development Best PracticesWindows Azure - Cloud Service Development Best Practices
Windows Azure - Cloud Service Development Best PracticesSriram Krishnan
 
Presentacion clean code
Presentacion clean codePresentacion clean code
Presentacion clean codeIBM
 
Move Accumulation To Collecting Parameter
Move Accumulation To Collecting ParameterMove Accumulation To Collecting Parameter
Move Accumulation To Collecting Parametermelbournepatterns
 
All I know about rsc.io/c2go
All I know about rsc.io/c2goAll I know about rsc.io/c2go
All I know about rsc.io/c2goMoriyoshi Koizumi
 
Chainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみたChainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみたAkira Maruoka
 

Similar to 2011 nri-pratiques tests-avancees (20)

JavaScript Refactoring
JavaScript RefactoringJavaScript Refactoring
JavaScript Refactoring
 
Chapter 2
Chapter 2Chapter 2
Chapter 2
 
Drools BeJUG 2010
Drools BeJUG 2010Drools BeJUG 2010
Drools BeJUG 2010
 
Testing persistence in PHP with DbUnit
Testing persistence in PHP with DbUnitTesting persistence in PHP with DbUnit
Testing persistence in PHP with DbUnit
 
Whats new in_csharp4
Whats new in_csharp4Whats new in_csharp4
Whats new in_csharp4
 
Working effectively with legacy code
Working effectively with legacy codeWorking effectively with legacy code
Working effectively with legacy code
 
Kickstarting SItes With a Custom Package
Kickstarting SItes With a Custom PackageKickstarting SItes With a Custom Package
Kickstarting SItes With a Custom Package
 
Domain Driven Design 101
Domain Driven Design 101Domain Driven Design 101
Domain Driven Design 101
 
Qt Workshop
Qt WorkshopQt Workshop
Qt Workshop
 
Functional C++
Functional C++Functional C++
Functional C++
 
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
Midiendo la calidad de código en WTF/Min (Revisado EUI Abril 2014)
 
Java and xml
Java and xmlJava and xml
Java and xml
 
Windows Azure - Cloud Service Development Best Practices
Windows Azure - Cloud Service Development Best PracticesWindows Azure - Cloud Service Development Best Practices
Windows Azure - Cloud Service Development Best Practices
 
Intro
IntroIntro
Intro
 
Presentacion clean code
Presentacion clean codePresentacion clean code
Presentacion clean code
 
applet.docx
applet.docxapplet.docx
applet.docx
 
Move Accumulation To Collecting Parameter
Move Accumulation To Collecting ParameterMove Accumulation To Collecting Parameter
Move Accumulation To Collecting Parameter
 
C#, What Is Next?
C#, What Is Next?C#, What Is Next?
C#, What Is Next?
 
All I know about rsc.io/c2go
All I know about rsc.io/c2goAll I know about rsc.io/c2go
All I know about rsc.io/c2go
 
Chainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみたChainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみた
 

More from Nathaniel Richand

More from Nathaniel Richand (19)

Devenir une entreprise resiliente avec la permagilité
Devenir une entreprise resiliente avec la permagilitéDevenir une entreprise resiliente avec la permagilité
Devenir une entreprise resiliente avec la permagilité
 
Proposition séminaire agile
Proposition séminaire agileProposition séminaire agile
Proposition séminaire agile
 
Permagilite
PermagilitePermagilite
Permagilite
 
2017 brownbaglunch Kanban
2017 brownbaglunch Kanban2017 brownbaglunch Kanban
2017 brownbaglunch Kanban
 
Présentation Dashing
Présentation DashingPrésentation Dashing
Présentation Dashing
 
Devenir une organisation apprenante dans l'IT en 2014
Devenir une organisation apprenante dans l'IT en 2014Devenir une organisation apprenante dans l'IT en 2014
Devenir une organisation apprenante dans l'IT en 2014
 
2013 brownbaglunch - lean startup
2013 brownbaglunch - lean startup2013 brownbaglunch - lean startup
2013 brownbaglunch - lean startup
 
Brownbaglunch Rétrospective
Brownbaglunch RétrospectiveBrownbaglunch Rétrospective
Brownbaglunch Rétrospective
 
Brown baglunch xebia
Brown baglunch xebiaBrown baglunch xebia
Brown baglunch xebia
 
Lean canvas brochure
Lean canvas brochureLean canvas brochure
Lean canvas brochure
 
Continuous integration
Continuous integrationContinuous integration
Continuous integration
 
Josiane ScrumDay 2012
Josiane ScrumDay 2012Josiane ScrumDay 2012
Josiane ScrumDay 2012
 
2011 XKE - Kanban in action
2011 XKE - Kanban in action2011 XKE - Kanban in action
2011 XKE - Kanban in action
 
2010 agile conférence - Comment vendre les tests automatisés
2010 agile conférence - Comment vendre les tests automatisés2010 agile conférence - Comment vendre les tests automatisés
2010 agile conférence - Comment vendre les tests automatisés
 
XKE - La communication
XKE - La communicationXKE - La communication
XKE - La communication
 
Presentation Zen
Presentation ZenPresentation Zen
Presentation Zen
 
Presentation Spring
Presentation SpringPresentation Spring
Presentation Spring
 
Tests Logiciel
Tests LogicielTests Logiciel
Tests Logiciel
 
Presentation Spring, Spring MVC
Presentation Spring, Spring MVCPresentation Spring, Spring MVC
Presentation Spring, Spring MVC
 

Recently uploaded

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu SubbuApidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbuapidays
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024The Digital Insurer
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...apidays
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
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
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024The Digital Insurer
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
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
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
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
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 

Recently uploaded (20)

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu SubbuApidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
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
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
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
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
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
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 

2011 nri-pratiques tests-avancees

  • 1. Pratiques avancées de testsNathaniel Richand Scrumday France 2011
  • 2. Merci aux sponsors du Scrumday ! Sponsors Platinum Sponsors Gold Parrainage :
  • 3.
  • 4. Restons pragmatique ! Doit-on : Tester les messages d’exceptions ? Tester les messages de logs ? Contexte
  • 8. Constat : TDD peut : devenir un frein, diminuer le rythme Augmenter la rigidité du code
  • 10. Tip1 : le nom donnel’intention testChoose1() testChoose2() whenSelectNullIItem_ShouldThrowAnException() whenSelectTwoItems_ShouldReturnTheSum()
  • 11. Tip2 : Ne pas masquer les informationsutiles @DataSet publicclassBrokerDAOTestextendsUnitilsTestNG { @Test publicvoidtestGetNameByClauseInId() { BrokerDASbdao = newBrokerDAO(); JpaUnitils.injectEntityManagerInto(bdao); List<String> brokers = bdao.getNameByClauseInId("in (1)"); assertEquals(brokers.size(), 1); assertEquals(brokers.get(0), "Kerviel"); } } WTF?
  • 12. Tip3 : Masquer tout ce qui est inutile Setup & Teardown Fixture Creation method Creation Builder Static import
  • 13. @Test publicvoidgenerateNomDeFichierNacXMLTest(){ //Given NacCreatorBOnacCreator = newNacCreatorBO(); //when String nomFichier= nacCreator.generateNomDeFichierNacXML (creerDateBlanchie(2010, 01, 02), "123456", creerDateBlanchie(2010, 03, 04), 10); //then assertThat(nomFichier).isEqualTo ("NAC_R_123456RE_020110_10_040310000000.xml"); }
  • 14. NacCreatorBOnacCreator; @Before publicvoidinit(){ nacCreator= newNacCreatorBO(); } @Test publicvoidgenerateNomDeFichierNacXMLTest(){ //when String nomFichier = nacCreator.generateNomDeFichierNacXML (creerDateBlanchie(2010, 01, 02), "123456", creerDateBlanchie(2010, 03, 04), 10); //then assertThat(nomFichier).isEqualTo ("NAC_R_123456RE_020110_10_040310000000.xml"); }
  • 15. @Test publicvoidtestParserIntraday(){ File file = new File("src/test/resources/fr/haramis/service/commons/util/Planning_Options.xls"); List<IntradaySchedule> listIntradays = null; InputStreamstream = null; try{ stream= newFileInputStream(file.getAbsolutePath()); } catch(FileNotFoundException e) { stream= null; } if(stream != null){ try{ listIntradays= IntradayParser.parseExcelIntraday(stream, "DIRECT-T01"); } catch(HermesException e) { e.printStackTrace(); logger.error(e); Assert.fail(); } logger.info(" ListIntradaysSize() " +listIntradays.size()); Assert.assertEquals(8400, listIntradays.size()); for(IntradayScheduleintradaySchedule : listIntradays) { Assert.assertEquals(24, intradaySchedule.getIntraday().getIntradaySchedules().size()); } } }
  • 16. @Test publicvoidtestParserIntraday_OK() throws Exception{ //Given InputStreamstream = getStreamFromFile("Planning_Options.xls"); //When List<IntradaySchedule> listIntradays = IntradayParser.parseExcelIntraday(stream, "DIRECT-T01"); //Then assertEquals(8400, listIntradays.size()); for(IntradayScheduleintradaySchedule : listIntradays) { assertEquals(24, intradaySchedule.getIntraday() .getIntradaySchedules().size()); } }
  • 17. //Given Map<Date, BigDecimal> charges = newHashMap<Date, BigDecimal>(); charges.put(dateDebut_13_03_2010, newBigDecimal(QUANTITY_1000)); charges.put(addDaysToDate(dateDebut_13_03_2010, 1), newBigDecimal(QUANTITY_3000));
  • 18. //Given Map<Date, BigDecimal> charges = newMapCharges<Date>() .with(dateDebut_13_03_2010, QUANTITY_1000) .and(addDaysToDate(dateDebut_13_03_2010, 1) QUANTITY_3000) .build();
  • 19. /** * Builder pour créer plus facilement des Map<Date, BigDecimal> ou des Map<String, BigDecimal> */ privateclassMapCharges<T> { privateMap<T, BigDecimal> cdcMap = newHashMap<T, BigDecimal>(); publicMapCharges<T> with(T dateDebut, intquantity){ cdcMap.put(dateDebut, newBigDecimal(quantity)); returnthis; } publicMapCharges<T> and(T dateDebut, intquantity){ returnwith(dateDebut, quantity); } publicMap<T, BigDecimal> build(){ returncdcMap; } }
  • 20. Tip4 : try/catch fail() @Test publicvoidtestFindByStatutAndDate() { OrdreSpotDASdao = newOrdreSpotDAO(); try{ assertEquals(dao.findByDate("01/07/2008", "OK").size(), 2); assertEquals(dao.findByDate("01/07/2008", "KO").size(), 1); } catch (HaramisExceptione) { e.printStackTrace(); Assert.fail(); } }
  • 21. @Test publicvoidtestFindByStatutAndDate() throwsHaramisException{ OrdreSpotDASdao = newOrdreSpotDAO(); assertEquals(dao.findByDate("01/07/2008", "OK").size(), 2); assertEquals(dao.findByDate("01/07/2008", "KO").size(), 1); }
  • 22. Tip4 (bis) : if/else fail() if (sd.getTimeRef() == 0) { assertEquals(sd.getPrice(), "301"); } else{ fail("pas normal"); }
  • 24. Tip5 : Simili de toString() dans les assert assertEquals("Compagniedifferente : "+result.getId()+" / "+ result.getName() +" / "+ result.getLocation() , result, expectedCompany); assertThat(result).isEqualTo(expectedCompany);
  • 25. Tip6 : Magic number, magic null //Given Site siteNord = createSite(NORD, 10); Site siteSud = createSite(SUD, 12); //When intaffectations = dao.selectAffectationsNord(siteNord, siteSud, null); //Then assertThat(affectations).isEqualTo(10);
  • 26. //Given Site siteNord = createSite(NORD, AFFECTATION_NORD); Site siteSud = createSite(SUD, AFFECTATION_SUD); //When intaffectations = dao.selectAffectationsNord(siteNord, siteSud, SITE_NULL); //Then assertThat(affectations).isEqualTo(AFFECTATION_NORD);
  • 27. Tip7 : Garder la même structure @Test publicvoidcalculTotalTest(){ //Given double[] volumes = {10.24556, 21, 43}; //When double total = PositionUtils.calculTotal(UNITE_TEMPS_HORAIRE, volumes); //Then assertThat(total).isEqualTo(74.24556); }
  • 28. @Test publicvoidcalculerDateTest(){ //Given Date date = HaramisDateUtils.creerDateBlanchie(2010, 5, 19); //When String[] datesFormatees = PositionUtils.calculerDates(date, 1, UNITE_TEMPS_HORAIRE, ELECTRICTY); //Then assertThat(datesFormatees).hasSize(2); assertThat(datesFormatees[0]).isEqualTo("19/05/2010 01:00"); assertThat(datesFormatees[1]).isEqualTo("19/05/2010 02:00"); }
  • 29. Tip8 : Faire de belles assertions Ne surtout pas faire : assertFalse(toto == null); assertTrue(list.size() == 0); assertEquals(result, null);
  • 30. File emptyFile = writeFile("emptyFile", ""); assertThat(emptyFile).hasSize(0); List<String> names = Arrays.asList("Bob", ”Vince", ”Nat"); assertThat(names) .hasSize(3) .contains("Vince") .doesNotHaveDuplicates(); String nullString = null; assertThat(nullString).isNull(); http://docs.codehaus.org/display/FEST/Fluent+Assertions+Module
  • 31. for (Companycie : companies) { Assert.assertFalse(cie.getStatus() .equalsIgnoreCase(ConstantsUtils.SIMPLE_STATUS_ANNULE) , "Cie " + cie.getId()); } assertThat(companies) .onProperty("status") .containsOnly(SIMPLE_STATUS_VALIDE);
  • 32. Tip9 : Utiliser Spock def"I plus I should equal II"() { given:def calculator = newRomanCalculator()when:    def result = calculator.add("I", "I")           then:    result == "II" } http://code.google.com/p/spock/
  • 33. def"The lowestnumbershould go at the end"() { setup: defresult = calculator.add(a, b)expect:result == sum  where: a   | b  | sum    "X"  | "I" | "XI"    "I"  | "X" | "XI"    "XX" | "I" | "XXI"    "XX" | "II"| "XXII"    "II" | "XX"| "XXII"   } http://www.wakaleo.com/blog/303-an-introduction-to-spock
  • 34. Faire des tests plus robustes
  • 35. Tip1 : Pas de duplication Cf. Tip 3 : Masquer tout ce qui est inutile Creation fixture Creation builder Test Helper Custom assertions
  • 36. Tip2 : Tester un comportementà un seulendroit publicString formatResultToCSV(List<Object[]> positionsResultats) throwsParseException; privatestatic String[] calculerDeuxDates(Object[] ligne) throwsParseException; publicstatic String[] obtenirVolumes(Object[] ligne);
  • 37. PublicString formatResultToCSV(List<Object[]> positionsResultats) throwsParseException { StringBuildersb = newStringBuilder(); for(Object[] ligne : positionsResultats) { String[] twoDates = calculerDeuxDates(ligne); String[] newLine = new String[ligne.length -1]; newLine[0] = twoDates[0]; newLine[1] = twoDates[1]; String[] volumes = PositionUtils.obtenirVolumes(ligne); System.arraycopy(volumes, 0, newLine, 2, volumes.length); for(String elementLigne : newLine) { sb.append(elementLigne+"|"); } } returnsb.toString(); }
  • 38. Tip3 : Eviter la réflexion @Test publicvoid testReglesValidationHRM_118_KO() throws Exception { PortfolioManagerBOportfolioManagerBO = newPortfolioManagerBO(); Method reglesValidationHRM118 = null; PortfolioFormportfolioForm = newPortfolioForm(); portfolioManagerBO.setPortfolioForm(portfolioForm); reglesValidationHRM118 = ReflectHelper.getPrivateMethod(portfolioManagerBO, "reglesValidationHRM118"); reglesValidationHRM118.setAccessible(true); reglesValidationHRM118.invoke(portfolioManagerBO); assertFalse(portfolioForm.isMessageAVisible()); assertFalse(portfolioForm.isPopupVisible()); }
  • 39. @Test publicvoid testReglesValidationHRM_118_OK() throws Exception { //Given PortfolioManagerBOportfolioManagerBO = newPortfolioManagerBO(); PortfolioFormportfolioForm = newPortfolioForm(); portfolioManagerBO.setPortfolioForm(portfolioForm); //When portfolioManagerBO.reglesValidationHRM118(); //Then assertFalse(portfolioForm.isMessageAVisible()); assertFalse(portfolioForm.isPopupVisible()); }
  • 40. Tip4 : Quoi tester? “Bas niveau” : état privatestaticString formatValue(Object removeNull) { if(removeNull == null) { return""; } else { returnremoveNull.toString(); } }
  • 41. “Haut niveau” : comportement public String getPointsHoraires(String dateDeb, String dateFin, String portFolios, String password) { passwordChecker.checkPassword(password); List<Long> listIdPortfolio = convertPortfoliosIdToLong(portFolios); List<Object[]> pointsResultats = executeCalculPointsPortefeuille( dateDeb, dateFin, listIdPortfolio); String pointsCSV= formatResultToCSV(pointsResultats); returnpointsCSV; }
  • 42. Bilan Aimez vos tests et ils vous le rendront Les principes “Clean code” s’appliquent également au code de test!

Editor's Notes

  1. 3 symptomes :Plus d’assert@Test en commentaireCode commenté
  2. MarketDataControllerBOTest
  3. Chaque test porte une intention, un butOn ne teste pas une classe, mais plutôt un ensemble de comportement
  4. Creation fixture (+varargs)Creation builder
  5. Sortir les magic en constantes de classes
  6. Plus facile pour détecter la méthodetestéeIncite à faire uneméthode de test = un testIncite à faire de petit tests
  7. Fest
  8. Fest
  9. Fest
  10. http://meetspock.appspot.com/Montrer:Nom de méthode en defGiven/When/Then : plus d’assertData Driven
  11. http://meetspock.appspot.com/Montrer:Nom de méthode en defGiven/When/ThenData Driven
  12. Inclus : Pas d’assertsur les init
  13. Package private
  14. Parler de dp4J : https://sites.google.com/a/mysimpatico.com/home//dp4j