2011 nri-pratiques tests-avancees

Post on 05-Dec-2014

2.071 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Le support de la présentation donné en mars 2011 au ScrumDay

TRANSCRIPT

Pratiques avancées de testsNathaniel Richand

Scrum day France 2011

Merci aux sponsors du Scrum day !

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 illisibles et fragiles

Exemple

Constat :

TDD peut :• devenir un frein, diminuer le rythme• Augmenter la rigidité du code

AMÉLIORER LA LISIBILITÉ

Tip1 : le nom donne l’intention

• testChoose1()• testChoose2()

• whenSelectNullIItem_ShouldThrowAnException()• whenSelectTwoItems_ShouldReturnTheSum()

Tip2 : Ne pas masquer les informations utiles

@DataSetpublic class BrokerDAOTest extends UnitilsTestNG {

@Test public void testGetNameByClauseInId() { BrokerDAS bdao = new BrokerDAO(); 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

@Testpublic void generateNomDeFichierNacXMLTest(){ //Given NacCreatorBO nacCreator = new NacCreatorBO();

//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");}

NacCreatorBO nacCreator;

@Beforepublic void init(){ nacCreator = new NacCreatorBO();}

@Testpublic void generateNomDeFichierNacXMLTest(){ //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");}

@Testpublic void testParserIntraday(){ File file = new File("src/test/resources/fr/haramis/service/commons/util/Planning_Options.xls"); List<IntradaySchedule> listIntradays = null; InputStream stream = null; try { stream = new FileInputStream(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 (IntradaySchedule intradaySchedule : listIntradays) { Assert.assertEquals(24, intradaySchedule.getIntraday().getIntradaySchedules().size()); } }}

@Testpublic void testParserIntraday_OK() throws Exception{ //Given InputStream stream = getStreamFromFile("Planning_Options.xls");

//When List<IntradaySchedule> listIntradays = IntradayParser.parseExcelIntraday(stream, "DIRECT-T01");

//Then assertEquals(8400, listIntradays.size()); for (IntradaySchedule intradaySchedule : listIntradays) { assertEquals(24, intradaySchedule.getIntraday() .getIntradaySchedules().size()); }}

//GivenMap<Date, BigDecimal> charges = new

HashMap<Date, BigDecimal>();

charges.put(dateDebut_13_03_2010,new BigDecimal(QUANTITY_1000));

charges.put(addDaysToDate(dateDebut_13_03_2010, 1),

new BigDecimal(QUANTITY_3000));

//GivenMap<Date, BigDecimal> charges = new

MapCharges<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> */private class MapCharges<T> { private Map<T, BigDecimal> cdcMap = new HashMap<T,

BigDecimal>();

public MapCharges<T> with(T dateDebut, int quantity){ cdcMap.put(dateDebut, new BigDecimal(quantity)); return this; } public MapCharges<T> and(T dateDebut, int quantity){ return with(dateDebut, quantity); } public Map<T, BigDecimal> build(){ return cdcMap; }}

Tip4 : try/catch fail()@Testpublic void testFindByStatutAndDate() { OrdreSpotDAS dao = new OrdreSpotDAO();

try { assertEquals(dao.findByDate("01/07/2008", "OK").size(), 2); assertEquals(dao.findByDate("01/07/2008", "KO").size(), 1); } catch (HaramisException e) { e.printStackTrace(); Assert.fail(); }}

@Testpublic void testFindByStatutAndDate() throws HaramisException{ OrdreSpotDAS dao = new OrdreSpotDAO();

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");

Guard Assert

Tip5 : Simili de toString() dans les assert

assertEquals("Compagnie differente : "+result.getId()+" / "+ result.getName() +" / "+ result.getLocation()

, result, expectedCompany);

assertThat(result).isEqualTo(expectedCompany);

Tip6 : Magic number, magic null

//GivenSite siteNord = createSite(NORD, 10);Site siteSud = createSite(SUD, 12);

//Whenint affectations = dao.selectAffectationsNord(siteNord, siteSud, null);

//ThenassertThat(affectations).isEqualTo(10);

//GivenSite siteNord = createSite(NORD, AFFECTATION_NORD);Site siteSud = createSite(SUD, AFFECTATION_SUD);

//Whenint affectations = dao.selectAffectationsNord(siteNord, siteSud, SITE_NULL);

//ThenassertThat(affectations).isEqualTo(AFFECTATION_NORD);

Tip7 : Garder la même structure@Testpublic void calculTotalTest(){

//Givendouble[] volumes = {10.24556, 21, 43};

//Whendouble total = PositionUtils.calculTotal(UNITE_TEMPS_HORAIRE, volumes);

//ThenassertThat(total).isEqualTo(74.24556);

}

@Testpublic void calculerDateTest(){

//GivenDate date = HaramisDateUtils.creerDateBlanchie(2010, 5, 19);

//WhenString[] datesFormatees = PositionUtils.calculerDates(date, 1, UNITE_TEMPS_HORAIRE, ELECTRICTY);

//ThenassertThat(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 (Company cie : 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 = new RomanCalculator()when:    def result = calculator.add("I", "I")           then:    result == "II"

}

http://code.google.com/p/spock/

def "The lowest number should go at the end"() { setup: def result = 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 seul endroit

public String formatResultToCSV(List<Object[]> positionsResultats) throws ParseException;

private static String[] calculerDeuxDates(Object[] ligne)throws ParseException;

public static String[] obtenirVolumes(Object[] ligne);

Public String formatResultToCSV(List<Object[]> positionsResultats) throws ParseException { StringBuilder sb = new StringBuilder(); 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+"|"); } } return sb.toString();}

Tip3 : Eviter la réflexion@Testpublic void testReglesValidationHRM_118_KO() throws Exception { PortfolioManagerBO portfolioManagerBO = new PortfolioManagerBO(); Method reglesValidationHRM118 = null; PortfolioForm portfolioForm = new PortfolioForm(); portfolioManagerBO.setPortfolioForm(portfolioForm);

reglesValidationHRM118 = ReflectHelper.getPrivateMethod(portfolioManagerBO, "reglesValidationHRM118");

reglesValidationHRM118.setAccessible(true); reglesValidationHRM118.invoke(portfolioManagerBO);

assertFalse(portfolioForm.isMessageAVisible()); assertFalse(portfolioForm.isPopupVisible());}

@Testpublic void testReglesValidationHRM_118_OK() throws Exception { //Given PortfolioManagerBO portfolioManagerBO = new PortfolioManagerBO(); PortfolioForm portfolioForm = new PortfolioForm(); portfolioManagerBO.setPortfolioForm(portfolioForm);

//When portfolioManagerBO.reglesValidationHRM118();

//Then assertFalse(portfolioForm.isMessageAVisible()); assertFalse(portfolioForm.isPopupVisible());}

Tip4 : Quoi tester?

“Bas niveau” : état

private static String formatValue(Object removeNull) { if (removeNull == null) { return ""; } else { return removeNull.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);

return pointsCSV ;}

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.frhttp://blog.xebia.fr

top related