Tests Unitaires Frédéric Moalannée 2010/2011 POO.

42
Tests Unitaires Frédéric Moal année 2010/2011 POO

Transcript of Tests Unitaires Frédéric Moalannée 2010/2011 POO.

Page 1: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

Tests Unitaires

Frédéric Moal année 2010/2011

POO

Page 2: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

2

Différents type de tests

Vérification d'un système, logiciel ou matériel, en vue de savoir s'il satisfait les exigences requises en termes de qualité.

Qualité du code : Découvrir les bugs avant qu'ils ne cassent l'application. Assurer la qualité très tôt pendant le codage en utilisant des

outils d'analyse dynamique (débuggeur, génération du diagramme de séquence pendant l'exécution, etc.)

Page 3: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

3

Différents type de tests

Fonctionnalités : réaliser des tests unitaires, des tests de non-régression, des tests d'intégration, des tests de validation des composants dans l'application;

Performances : Test de charge mise à l'épreuve d’une application en émulant des “vrais” utilisateurs

avec un outil de génération de Charge détecter les goulots d'étranglement sur les ressources systèmes à

observer (temps de réponses, occupation mémoire, etc.)

Réception : Réalisé par le client (acceptance, clean-room tests) S’assurer que le cahier des charges a été respecté.

Page 4: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

4

Les tests unitaires

Test structurel (white-box test) : L'implémentation de la classe doit être connue. Test vérifiant si le code est robuste en contrôlant son comportement

avec des cas de test inattendus (cas limites). Le but de ce test est d'exécuter chaque branche du code avec

différentes conditions d'entrée afin de détecter tous les comportements anormaux (test "boîte blanche").

Exemple : nombre min, max, état d'une instance, dépassement de capacité, etc.

Test de validation (black-box test) : Ils s'effectuent sans connaissance de la structure interne (tests

"boîte noire"). Test permettant de vérifier que les exigences fonctionnelles et

techniques du cahier des charges sont respectées. Le test boîte noire vérifie la fonctionnalité de l'interface publique

d'une unité.

Page 5: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

5

Quelle catégorie de tests choisir ?

Les tests boîte blanche sont très difficiles à mettre en oeuvre tandis que les tests boîte noire peuvent être automatisés

De quels outils dispose t-on en Java ?

Page 6: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

6

Quelle catégorie de tests choisir ?

Tests structurels : assertions embarquées dans le code; Pré/post conditions d'exécution d'une instruction; issues des travaux de Tony Hoare sur les

spécifications algébriques pour la preuve de programme dans les années 1960;

Tests boîtes noires : Conception par contrats (design by contracts)

Pré/post conditions d'appel à des objets; Assertions Java; Outil d'exécution de tests unitaires (JUnit,

Rational Functional Tester, etc.);

Page 7: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

7

Tests unitaires

Page 8: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

8

Pourquoi JUnit ?Traces (instruction log) dans les programmes Utilisation d’un debugger (possibilité de redéfinir les expressions de test) sans avoir à recompiler les programmes Sévère limitations

nécessitent un jugement humain problèmes de composition :Une seule expression exécutable à la fois avec un debuggerSi une trace contient de nombreux print, perte de lisibilité

Test

s u

nit

aire

s

Page 9: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

Le débutant…

Tests embarqués dans la classe. Lancement et vérification manuels.

TEST…

Page 10: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

Le débutant…

AIE ! Plusieurs méthodes….

Page 11: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

Le débutant…

Devient TRES complexe ….

Page 12: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

12

Test dans les classes ?

C’est une mauvaise pratique car elle entraîne : L'augmentation de l'entropie :

plus l'interface de la classe grandit, plus le programme principal "main()" grandit (jusqu'à dépasser le code fonctionnel);

Le code de production est plus important que nécessaire;

Absence de sécurité (exemple: mot de passe en clair dans le programme principal compilé).

Page 13: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

13

Test dans les classes ?

C’est une mauvaise pratique car elle entraîne : Une défaillance des tests :

La méthode "main()" appartient à la classe et accède aux méthodes et membres privés.

Les clients de cette classe n'ont pas ce privilège => source d'erreur;

La plus petite unité à tester dans la classe est la méthode : chaque méthode doit être testées séparément pour détecter les cas d'erreur;

Chaque méthode doit être testée en dépit de tests précédents défaillants afin de connaître le pourcentage de tests défaillants.

Page 14: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

14

Test dans les classes ?

C’est une mauvaise pratique car elle entraîne : La difficulté d'automatiser le test :

Il est encore nécessaire de créer un script pour passer des arguments à "main()";

Chaque classe à un programme spécifique avec son code d'initialisation et des appels à des routines spécifiques.

Un système de report d'anomalies maison doit être défini.

Page 15: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

15

JUnit origine :

TDD (test-driven developpment), Xtreme programming XP, méthodes agiles

Erich Gamma et Kent Beck canevas (framework) ecrit en Java open source : www.junit.org intégration dans Eclipse et Maven ; différences notables entre JUnit 3.8 et JUnit 4

JUnit 4 plus facile a utiliser ; JUnit 3.8 plus facile a comprendre

=>connaître les 2 !

Page 16: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

16

JUnit un ensemble d'interfaces et de classes qui

collaborent qui ne s'utilisent pas directement c'est une application (( a trous )) qui

offre la partie commune des traitements et est spécialisée par chaque utilisateur

il faut implanter/spécialiser les types fournis

ex : pour créer un cas de test on hérite de la classe TestCase

Page 17: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

17

Classes de JUnitTe

sts

un

itai

res

Page 18: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

18

Classes et méthodes de test Classe de test

hérite de JUnit.framework.TestCase contient les méthodes de test peut utiliser les assertXXX sans import constructeur a paramètre String (dépend des

versions) Méthodes de test

publique, type de retour void le nom commence obligatoirement par test pas de paramètre, peut lever une exception contiennent des assertions

Page 19: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

19

Ecriture d’une classe de test

Classe à tester :

Test

s u

nit

aire

s

Page 20: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

20

Ecriture d’une classe de test

Classe de test :

Création des objets qui vont interagir lors du testCode qui agit sur les objets impliqués dans le testVérification que le résultat obtenu correspond bien au résultat attendu

Test

s u

nit

aire

s

Page 21: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

21

Ecriture d’une classe de test

static void assertTrue(boolean test)

méthode JUnit : vérifie que test == true et dans le cas contraire lance une exception (en fait une Error) de type AssertionFailedError

L’exécuteur de tests JUnit attrape ces objets Errors et indique les tests qui ont échoué

Page 22: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

22

Les méthodes assert static void assertTrue(String message, boolean

test)Le message optionnel est inclus dans l’Error

static void assertFalse(boolean test) static void assertFalse(String message, boolean

test)vérifie que test == true

assertEquals(expected, actual) assertEquals(String message, expected, actual)

méthode largement surchargée: arg1 et arg2 doivent être tout deux des objets ou bien du même type primitifPour les objets, utilise la méthode equals (public boolean equals(Object o) sinon utilise ==

Page 23: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

23

Les méthodes assert

assertSame(Object expected, Object actual) assertSame(String message, Object expected, Object

actual) Vérifie que expected et actual référencent le même objet (==)

assertNotSame(Object expected, Object actual) assertNotSame(String message, Object expected, Object

actual) Vérifie que expected et actual ne référencent pas le même objet (==)

assertNull(Object object) assertNull(String message, Object object)

Vérifie que objet est null

assertNotNull(Object object) assertNotNull(String message, Object object)

Vérifie que objet n’est pas null

Page 24: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

24

Les méthodes assertfail()fail(String message) Provoque l’échec du test et lance une AssertionFailedError Utile lorsque les autres méthodes assert ne correspondent pas exactement à vos besoins ou pour tester que certaines exceptions sont bien lancées

try {// appel d’une méthode devant lancer une Exceptionfail("Did not throw an ExpectedException");

}catch (ExpectedException e) { }

Page 25: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

25

setup / tearDown

méthode setUp appelée avant chaque méthode de test permet de factoriser la construction de (( l'état du

monde ))

méthode tearDown appelée après chaque méthode de test permet de défaire (( l'état du monde ))

Page 26: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

26

Ecriture d’une classe de test

Page 27: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

27

Exécution d’un test

Pour exécuter un testTestResult result = (new CounterTest("testIncrement")).run();

Pour exécuter une suite de testsTestSuite suite = new TestSuite();suite.addTest(new CounterTest("testIncrement"));

suite.addTest(new CounterTest("testDecrement"));

TestResult result = suite.run(); En utilisant l’introspection

TestSuite suite = new TestSuite(CounterTest.class);

TestResult result = suite.run();

Page 28: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

28

Résultats d’un test JUnit propose des outils pour exécuter suite de tests et afficher les résultats Ajouter à la classe de test une méthode statique suite pour rendre une suite accessible à un "exécuteur de test" (TestRunner) :

public static Test suite() {TestSuite suite = new TestSuite();suite.addTest(new CounterTest("testIncrement"));suite.addTest(new CounterTest("testDecrement"));return suite;}

Autre solution (introsepection)junit.textui.TestRunner.run(CounterTest.class);

De nombreux IDE intègrent JUnit : NetBeans, Eclipse

Page 29: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

29

Jouer tous les tests d’un package

TestSuite contient des objets Test Des TestCase mais aussi des TestSuite Une classe AllTest

Teste toutes les suite de tests du packagepublic class AllTests {

public static Test suite() {TestSuite suite =

new TestSuite("Test for default package");suite.addTest(new TestSuite(TokenizerTest.class));suite.addTest(new TestSuite(NodeTest.class));suite.addTest(new TestSuite(ParserTest.class));suite.addTest(new TestSuite(TreeTest.class));return suite;}

}

Page 30: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

30

Jouer tous les tests de sous-package

Dans chaque package définir une suite qui inclus les suites des sous packages

public class AllTests_{public static Test suite() {

TestSuite suite =new TestSuite("All helix.* and subpackages tests");

suite.addTest(helix.edb.AllTests_.suite());suite.addTest(helix.def.AllTests_.suite());

return suite;}

}

Page 31: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

31

JUnit 4

Différences notables dans l ’écriture utilise les @tags java 5

Même philosophie test unitaire setup/teardown …

Plus souple pour l’écriture

Page 32: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

32

JUnit 4 - @Test

@Test Mark your test cases with @Test annotations.

You don’t need to prefix your test cases with “test”. In addition, your class does not need to extend from “TestCase” class.

@Test

public void addition() {

assertEquals(12, simpleMath.add(7, 5));

}

@Test

public void subtraction() {

assertEquals(9, simpleMath.substract(12, 3));

}

Page 33: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

33

JUnit 4 - @Before and @After

@Before and @After Use @Before and @After annotations for

“setup” and “tearDown” methods respectively. They run before and after every test case.

@Before

public void runBeforeEveryTest() {

simpleMath = new SimpleMath();

}

@After

public void runAfterEveryTest() {

simpleMath = null;

}

Page 34: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

34

JUnit 4 – @BeforeClass and @AfterClass

@BeforeClass and @AfterClass Use @BeforeClass and @AfterClass

annotations for class wide “setup” and “tearDown” respectively. Think them as one time setup and tearDown. They run for one time before and after all test cases.

@BeforeClass

public static void runBeforeClass() {

// run for one time before all test cases

}

@AfterClass

public static void runAfterClass() {

// run for one time after all test cases

}

Page 35: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

35

JUnit 4 - Exception Handling

Exception Handling Use “expected” paramater with @Test

annotation for test cases that expect exception. Write the class name of the exception that will be thrown.

@Test(expected = ArithmeticException.class)

public void divisionWithException() {

// divide by zero

simpleMath.divide(1, 0);

}

Page 36: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

36

JUnit 4 - @Ignore

@Ignore Put @Ignore annotation for test cases you

want to ignore. You can add a string parameter that defines the reason of ignorance if you want.

@Ignore("Not Ready to Run")

@Test

public void multiplication() {

assertEquals(15, simpleMath.multiply(3, 5));

}

Page 37: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

37

JUnit 4 - Timeout

Timeout Define a timeout period in milliseconds with

“timeout” parameter. The test fails when the timeout period exceeds.

@Test(timeout = 1000)

public void infinity() {

while (true) ;

}

Page 38: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

38

JUnit 4 - New Assertions

New Assertions Compare arrays with new assertion methods. Two

arrays are equal if they have the same length and each element is equal to the corresponding element in the other array; otherwise, they’re not.

public static void assertEquals(Object[] expected, Object[] actual);

public static void assertEquals(String message, Object[] expected, Object[] actual);

@Test

public void listEquality() {

List<Integer> expected = new ArrayList<Integer>();

expected.add(5);

List<Integer> actual = new ArrayList<Integer>();

actual.add(5);

assertEquals(expected, actual);

}

Page 39: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

39

Test Tips Code a little, test a little, code a little, test a little . . . Run your tests as often as possible, at least as often

as you run the compiler ☺ Begin by writing tests for the areas of the code that

you’re the most worried about . . .write tests that have the highest possible return on your testing investment

When you need to add new functionality to the system, write the tests first

If you find yourself debugging using System.out.println(), write a test case instead

When a bug is reported, write a test case to expose the bug

Don’t deliver code that doesn’t pass all the tests

Page 40: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

40

Principes

Integration continue – Pendant le développement, le programme marche toujours – peut être qu’il ne fait pas tout ce qui est requis mais ce qu’il fait, il le fait bien.TDD Test Driven Development :pratique qui se rattache à l’eXtreme Programming

“Any program feature without an automated test simply doesn’t exist.” from Extreme Programming Explained, Kent Beck

Page 41: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

41

Tests : Références

www.junit.org www.extremeprogramming.org www.developpez.com http://cruisecontrol.sourceforge.net/

Page 42: Tests Unitaires Frédéric Moalannée 2010/2011 POO.

42

Conclusion Outils d’aide au développement, en

particulier en groupe Javadoc : indispensable ! Gain de temps

énorme pour la documentation.... Log : indispensable pour le suivit après

mise en production d’un logiciel Asserts/Tests unitaires : assert moins

utilisés, souvent « déportés » vers tests unitaires... Tests unitaires indispensables, exécutés en continu pendant le projet, livrés avec le produit final au client.