2019_2020:s3:methodo:td:env1:tests
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
2019_2020:s3:methodo:td:env1:tests [2019/08/25 09:08] – created blay | 2019_2020:s3:methodo:td:env1:tests [2019/08/25 14:24] (current) – [Eclipse et couverture de tests] blay | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ouvent un processus créatif difficile, un peu comme écrire un code de production. Pour cette raison, il n' | ||
- | - Jeûne. Les tests unitaires sont destinés à être exécutés souvent, et dans de nombreux cas dans le cadre d'un cycle de programmation-compilation-exécution. Pour cette raison, n' | ||
- | - Indépendant. Chaque test unitaire devrait pouvoir être exécuté de façon isolée. Cela signifie, par exemple, qu'un test ne doit pas dépendre du fait qu'un autre test s' | ||
- | 6 Cependant, seules les instances d' | ||
- | |||
- | 5.5 StructuringTests 103 | ||
- | n' | ||
- | - Répétable. L' | ||
- | - Concentré. Les tests doivent exercer et vérifier une partie du comportement d' | ||
- | - Lisibles. La structure et le style de codage du test devraient faciliter l' | ||
- | Par exemple, écrivons quelques tests unitaires pour une méthode canMoveTo d'une classe hypothétique FoundationPile qui pourrait faire partie de la conception de l' | ||
- | Traduit | + | |
+ | ====== Tests en Java - Rappel ou Apprentissage ====== | ||
+ | . | ||
+ | <note warning> | ||
+ | |||
+ | Il devrait être disponible à la bibliothèque et vous trouverez une version électronique en ligne. (voir plus bas dans la catégorie référence). | ||
+ | |||
+ | **L' | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | ===== Structuration d'une suite de tests ===== | ||
+ | |||
+ | Une question courante lors de la construction d'une suite de tests unitaires est de savoir comment organiser nos tests de manière sensée. Il existe différentes approches, mais en Java un idiome commun est d' | ||
+ | |||
+ | De plus, il est de pratique courante de localiser tout le code de test** dans un dossier source différent** | ||
+ | |||
+ | |||
+ | ===== Propriétés des tests ===== | ||
+ | |||
+ | Écrire des tests unitaires pour des classes non triviales est souvent un processus créatif difficile, un peu comme écrire un code de production. Pour cette raison, il n' | ||
+ | * **Rapides**. Les tests unitaires sont destinés à être exécutés souvent, et dans de nombreux cas dans le cadre d'un cycle de programmation-compilation-exécution. Pour cette raison, n' | ||
+ | * **Indépendant**. Chaque test unitaire devrait pouvoir être exécuté de façon isolée. Cela signifie, par exemple, qu'un test ne doit pas dépendre du fait qu'un autre test s' | ||
+ | * **Répétable**. L' | ||
+ | * **Concentré**. Les tests doivent exercer et vérifier une partie du comportement d' | ||
+ | * **Lisible**. La structure et le style de codage du test devraient faciliter l' | ||
+ | |||
+ | ==== Retour sur l' | ||
+ | |||
+ | En utilisant l' | ||
+ | |||
+ | === Test fixture === | ||
+ | Une fixture est un morceau de code qui permet de fixer un environnement logiciel pour exécuter des tests logiciels. Cet environnement constant est toujours le même à chaque exécution des tests. Il permet de répéter les tests indéfiniment et d' | ||
+ | |||
+ | |||
+ | |||
+ | <code java> | ||
+ | package testRobillardBook; | ||
+ | |||
+ | import static org.junit.jupiter.api.Assertions.*; | ||
+ | |||
+ | import org.junit.jupiter.api.BeforeEach; | ||
+ | import org.junit.jupiter.api.Test; | ||
+ | |||
+ | public class TestFoundationPile { | ||
+ | // Test Fisture | ||
+ | private static final Card ACE_CLUBS = Card.get(Rank.ACE, | ||
+ | private static final Card TWO_CLUBS = Card.get(Rank.TWO, | ||
+ | private static final Card THREE_CLUBS = Card.get(Rank.THREE, | ||
+ | private FoundationPile aPile; | ||
+ | @BeforeEach | ||
+ | public void setUp() { aPile = new FoundationPile(); | ||
+ | |||
+ | @Test | ||
+ | public void testCanMoveTo_Empty() { | ||
+ | assertTrue(aPile.canMoveTo(ACE_CLUBS)); | ||
+ | assertFalse(aPile.canMoveTo(THREE_CLUBS)); | ||
+ | } | ||
+ | @Test | ||
+ | public void testCanMoveTo_NotEmptyAndSameSuit() { | ||
+ | aPile.push(ACE_CLUBS); | ||
+ | assertTrue(aPile.canMoveTo(TWO_CLUBS)); | ||
+ | assertFalse(aPile.canMoveTo(THREE_CLUBS)); | ||
+ | } } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Couverture des tests ===== | ||
+ | |||
+ | Il n'est pas toujours physiquement possible de tester de façon exhaustive l' | ||
+ | |||
+ | De toute évidence, nous devons choisir les tests à réaliser parmi toutes les possibilités (par exemple, sélectionner les configurations du jeu de dame à tester). | ||
+ | |||
+ | Une méthode classique pour déterminer ce qu'il faut tester est basée sur le concept de couverture. De manière informelle, une mesure de couverture de test est un nombre (généralement un pourcentage) qui détermine la quantité de code exécutée lorsque nous exécutons nos tests. Les mesures de couverture de test peuvent ensuite être calculées par des outils de couverture de code qui gardent la trace du code qui est exécuté lorsque nous exécutons des tests unitaires. Cela peut paraître simple, mais le problème est qu'il existe différentes définitions de ce que l'on peut entendre par " | ||
+ | |||
+ | ==== Couverture d' | ||
+ | |||
+ | La couverture des instructions est simplement le nombre d' | ||
+ | <code java> | ||
+ | public boolean canMove() { | ||
+ | if( isEmpty() ) | ||
+ | return false; | ||
+ | else | ||
+ | return true; | ||
+ | } | ||
+ | </ | ||
+ | Le test suivant ne couvre alors que les premières instructions soit 60% du code de la méthode. | ||
+ | |||
+ | <code java> | ||
+ | @Test | ||
+ | public void testCanMove_Empty() | ||
+ | { | ||
+ | aPile = new FoundationPile(); | ||
+ | assertFalse(aPile.canMove()); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | La logique qui sous-tend la couverture des instructions est simplement que si un défaut est présent dans une instruction qui n'est jamais exécutée, les tests ne vont pas aider à le trouver. Bien que cette logique puisse sembler attrayante, la couverture des relevés est en fait une mauvaise mesure de couverture. Une première raison est que cela dépend fortement de la structure détaillée du code. Nous pourrions réécrire la méthode '' | ||
+ | <code java> | ||
+ | public boolean canMove() { | ||
+ | return !(isEmpty()); | ||
+ | } | ||
+ | </ | ||
+ | La deuxième raison est que toutes les instructions ne sont pas créées de la même manière, et il peut y avoir beaucoup de choses qui se passent dans une instruction, | ||
+ | |||
+ | ==== Couverture des branches ==== | ||
+ | |||
+ | La couverture des branches est le nombre de " | ||
+ | <code java> | ||
+ | public boolean canMoveTo(Card pCard) | ||
+ | { | ||
+ | if( isEmpty() ) | ||
+ | { | ||
+ | return pCard.getRank() == Rank.ACE; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | return pCard.getSuit() == peek().getSuit() && | ||
+ | pCard.getRank().ordinal() == | ||
+ | peek().getRank().ordinal()+1; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | Cependant, les branches vraies et fausses conduisent toutes deux à des instructions qui sont constituées d' | ||
+ | |||
+ | |||
+ | D'une manière générale, la couverture des branches est l'un des critères de couverture des tests les plus utiles. Elle est bien étayée par des outils de test et relativement facile à interpréter, | ||
+ | |||
+ | ==== Eclipse et couverture de tests ==== | ||
+ | [[https://www.eclemma.org/ | ||
+ | Depuis la version 2.0, EclEmma est basé sur la bibliothèque de codes JaCoCoCo. L' | ||
+ | |||
+ | |||
+ | |||
+ | Vous avez différents types de compteurs à disposition (voir https:// | ||
+ | {{: | ||
+ | {{: | ||
+ | |||
+ | et pour mieux comprendre les codes en couleur : https:// | ||
+ | |||
+ | ==== Sélection des cas de tests ==== | ||
+ | |||
+ | |||
+ | Aujourd' | ||
+ | |||
+ | * Les **tests fonctionnels (ou de boîte noire)** tentent de couvrir autant que possible le comportement spécifié d'un programme, en se basant sur certaines spécifications externes de ce que le programme doit faire en particulier au travers de post-condition(Nous verrons également que dans le processus de production d'un programme, on prévoit des tests à réaliser dans les histoires utilisateurs). Les tests de boîte noire présentent de nombreux avantages, notamment le fait qu'il n'est pas nécessaire d' | ||
+ | * Les **tests structurels (ou de boîte blanche)** tentent de couvrir autant que possible le comportement implémenté d'un programme, sur la base d'une analyse du code source de l' | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Références ===== | ||
+ | 1. Robert C. Martin. Clean Code: A Handbook of Agile Software Craftmanship. Prentice Hall, 2009.\\ | ||
+ | 2. Le livre de référence : https:// | ||
+ | 3. Les codes sources associés au livre : https:// |
2019_2020/s3/methodo/td/env1/tests.1566724139.txt.gz · Last modified: 2019/08/25 09:08 by blay