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

AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraDeakin University
 
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsSnow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsHyundai Motor Group
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAndikSusilo4
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 

Recently uploaded (20)

AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning era
 
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter RoadsSnow Chain-Integrated Tire for a Safe Drive on Winter Roads
Snow Chain-Integrated Tire for a Safe Drive on Winter Roads
 
The transition to renewables in India.pdf
The transition to renewables in India.pdfThe transition to renewables in India.pdf
The transition to renewables in India.pdf
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & Application
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 

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