Les tests d’acceptation

La qualification correspond à toutes les activités réalisées pour vérifier qu’un système logiciel est conforme aux attentes.

Les tests d’acceptation s’inscrivent dans une démarche de qualification pour déterminer si le produit est conforme dans son utilisation aux objectifs fixés. Il s’agit d’une description formelle du comportement d’un logiciel par des scénarios de test.

Néanmoins, les tests d’acceptation s’inscrivent aussi dans le cycle de développement logiciel. Ils ne sont donc pas envisagés de la même manière selon la méthode utilisée. Dans ce chapitre, nous verrons les différences dans la mise en place d’une stratégie de test d’acceptation dans le cadre de la méthode de gestion de projet et dans le cadre d’une méthode agile.

Méthode de gestion de projet

La méthode de gestion de projet n’est pas spécifique au développement informatique mais est très largement utilisée depuis les années 1980. Elle est souvent appelée Cycle en V pour les projets informatiques.

La notion de projet s’impose aujourd’hui à nous comme si elle était naturelle. Mais elle est assez récente dans l’industrie et ne recouvre qu’un processus précis de développement. Le mot projet a fait l’objet d’une définition par l’ISO :

Processus unique, qui consiste en un ensemble d’activités coordonnées et maîtrisées, comportant des dates de début et de fin, entrepris dans le but d’atteindre un objectif conforme à des exigences spécifiées, telles que les contraintes de délais, de coûts et de ressources.

—Extrait de ISO 10006 : Systèmes de management de la qualité — Lignes directrices pour le management de la qualité dans les projets

Dans la définition précédente, on voit qu’un projet est limité dans le temps, et que cette limite fait partie de sa définition : un projet a un début et une fin connus et envisagés dès le lancement. De plus, un projet doit permettre d’atteindre un objectif conforme à des exigences.

Notion d’exigence

Une exigence est une forme d’expression de besoins. Il s’agit d’un énoncé décrivant un besoin que doit satisfaire le système à réaliser. Une exigence ne se limite pas à la description d’une fonctionnalité, elle peut aussi établir des critères de disponibilité, de performance, de sécurité… Dans cette perspective, un système est présenté sous la forme d’une liste d’exigences (souvent plusieurs centaines).

Une exigence doit posséder certaines caractéristiques :

  • Elle est non ambiguë. Elle ne doit donc pas laisser de place à l’interprétation.

  • Elle est délimitée, c’est-à-dire que son intention doit être suffisamment précise. Par exemple, une exigence de performance ne doit pas se limiter à exprimer que l’application doit répondre rapidement. Elle doit, par exemple, fournir des éléments chiffrés : le temps de réponse de l’application doit être inférieur à une seconde.

  • Elle doit être testable. C’est cette caractéristique qui nous intéresse en premier lieu dans ce chapitre.

Une seule exigence ne suffit généralement pas à exprimer le détail d’une fonctionnalité.

Recette fonctionnelle

Dans la méthode de gestion de projet, le développement est organisé par phases successives. Chaque phase correspond à un ensemble d’activités spécifiques. On distingue généralement les phases suivantes :

  1. La phase d’expression de besoin : c’est au cours de cette phase que l’on rédige la liste des exigences et le cahier des charges

  2. La phase de conception

  3. La phase de réalisation

  4. La phase de test (recette)

  5. La phase de livraison (fin du projet)

La phase de test est souvent appelée la recette fonctionnelle (ou plus simplement la recette). Dans cette approche, les tests sont bien là pour vérifier l’adéquation entre les exigences d’une part (phase 1) et la conception et la réalisation d’autre part (phase 2 et 3). La recette implique également les éventuelles corrections des défauts révélés par les tests.

La recette fonctionnelle est un moyen de vérification de la conformité d’un système produit par rapport aux spécifications émises par le client. Les tests d’acceptation (souvent appelés tests fonctionnels) servent à réaliser cette vérification.

La recette implique de réaliser des campagnes de test. Les testeurs ont à leur disposition des cahiers de test qui décrivent les procédures à réaliser sous la forme de scénarios de test. Un scénario de test est décrit par des cas de test.

Les cahiers de test sont rédigés tardivement dans le processus de développement puisqu’ils ne sont réellement exploités qu’au moment de la recette. La plupart du temps, leur rédaction constitue la première étape de la phase de recette.

Notion de cas de test

Un cas de test désigne une interaction avec le système destinée à produire un résultat attendu.

Un cas de test est décrit par son titre. Il contient une liste d’étapes à réaliser. Chaque étape doit correspondre à une action de l’utilisateur et s’accompagne obligatoirement d’un résultat attendu (et si possible un seul). Le résultat attendu doit être explicité clairement et ne doit pas être interprétable. De plus, un cas de test se rapporte à une ou plusieurs exigences dans la mesure où il permet d’attester que le système est conforme à ces exigences.

Les consignes a respecter pour rédiger un cas de test :

  • limiter le nombre d’étapes d’un cas de test pour en réduire sa complexité

  • un cas de test ne doit pas contenir de condition (s’il se passe ceci alors faire cela sinon…). Un cas de test décrit une seule interaction possible. Pour traduire, une alternative, il suffit d’écrire un autre cas de test

  • Donner la valeur des entrées sous la forme de paramètres de manière a pouvoir utiliser un même cas de test pour des données différentes.

    Cas de test : afficher son profil utilisateur

    Étape : Sélectionner le menu utilisateur

    Résultat attendu : Le menu s’affiche et contient l’entrée « Profil »

    Étape : Sélectionner l’entrée « Profil »

    Résultat attendu : Le détail du profil s’affiche dans une popup avec le nom $nom, le prénom $prenom et la photo, les boutons « modifier » et « fermer » sont visibles et cliquables.

    Cas de test : éditer le profil utilisateur

    Étape : Cliquer sur le bouton « modifier »

    Résultat attendu : Les champs nom et prénom deviennent éditables, le bouton « modifier » disparaît et le bouton « sauvegarder » apparaît.

    Étape : Modifier le nom du profil par la valeur $nouveau_nom

    Résultat attendu : La valeur du champ nom est $nouveau_nom

    Étape : Modifier le prénom du profil par la valeur $nouveau_prenom

    Résultat attendu : La valeur du champ prénom est $nouveau_prenom

    Cas de test : sauver le profil utilisateur

    Étape : Cliquer sur le bouton « sauvegarder »

    Résultat attendu : Les champs nom et prénom ne sont plus éditables. Un message confirme que le profil a bien été enregistré.

    Cas de test : annuler la modification du profil utilisateur

    Étape : Cliquer sur le bouton « fermer »

    Résultat attendu : La popup du profil utilisateur se ferme.

La façon d’écrire les cas de test dépend de la connaissance présupposée qu’auront les testeurs de l’application. Il ne faut pas croire qu’il existerait objectivement un niveau idéal de rédaction pour les cas d’utilisation. Le niveau de rédaction nécessaire est donc largement dépendant de l’équipe qui participera aux campagnes de test. S’il s’agit d’une équipe spécialisée pour la réalisation des tests mais n’ayant que très peu d’implication dans le développement du système, alors les cas de tests devront être extrêmement détaillés pour guider au mieux les testeurs. A contrario, si les personnes réalisant les tests travaillent quotidiennement avec les développeurs et/ou les experts du domaine, les cas de test pourront contenir des termes propres au domaine de l’application et résumer plus facilement chaque étape en profitant d’un savoir commun de l’ensemble de l’équipe. De même, pour les personnes en charge de participer aux sessions de test, il faut tenir compte du savoir-faire technique dans la rédaction des cas de tests. L’ambiguïté d’un cas de test peut reposer sur un écart des savoirs techniques entre le rédacteur et le testeur. Par exemple, si une étape d’un cas de test nécessite de vérifier le code retour d’un programme, le testeur doit avoir une idée de ce qu’est un code retour et de comment l’obtenir.

Scénario de test

Un scénario de test est un regroupement de cas de test. Alors qu’un cas de test représente une interaction limitée avec le système, un scénario représente la réalisation d’une fonctionnalité complète.

Un ensemble de scénarios permet de s’assurer qu’une fonctionnalité fournie est conforme à l’ensemble des exigences qui la spécifie. Chaque scénario fournit son jeu de données particulier pour les paramètres décrits par les cas de tests. Un scénario peut également s’accompagner d’un pré-requis sur l’état nécessaire du système.

Scénario : Modification du profil utilisateur

Pré-requis : Il existe un profil utilisateur pour David Gayerie

Paramètre

Valeur

$nom

Gayerie

$prenom

David

$nouveau_nom

Erin

$nouveau_prenom

Julien

Cas de test : afficher son profil utilisateur

Cas de test : éditer le profil utilisateur

Cas de test : sauver le profil utilisateur

Scénario : Annuler la modification du profil utilisateur

Pré-requis : Il existe un profil utilisateur pour David Gayerie

Paramètre

Valeur

$nom

Gayerie

$prenom

David

$nouveau_nom

Erin

$nouveau_prenom

Julien

Cas de test : afficher son profil utilisateur

Cas de test : éditer le profil utilisateur

Cas de test : annuler la modification du profil utilisateur

L’ensemble des scénarios de test retenus pour une session de test forme le cahier de test.

Exercice

Cahier de tests pour une application de commande de pizza

Rédigez le cahier de test pour une application de commandes de pizza. Le cahier de test doit contenir :

  • La liste des cas de test (constitués des étapes et des exigences associées)

  • La liste des scénarios de test (constitués de cas de test)

Vous devez couvrir l’ensemble des fonctionnalités de l’application :

  • commander une pizza,

  • préparer une pizza,

Vous pouvez présenter votre cahier de test sous la forme de plusieurs feuilles de tableur. Pensez à faire apparaître des paramètres dans les étapes des cas de tests afin de pouvoir définir des jeux de données pour les scénarios.

Pizza EE

Finaliser la commande de pizza

L’utilisateur remplit le formulaire de commande avec la pizza choisie (il ne peut en choisir qu’une), son nom et son numéro de téléphone. Lorsqu’il clique sur le bouton Commander, les données doivent être envoyées au serveur et une commande doit être créée. Une page récapitulant la commande doit s’afficher avec la pizza choisie et la date et l’heure de création de la commande. Tous les champs doivent être obligatoirement saisis par l’utilisateur (sinon le formulaire doit être à nouveau affiché avec des messages précisant les champs erronés).

Numéro

Exigence

E0001

Une commande est constituée par un nom, un numéro de téléphone et une pizza

E0002

Une commande ne concerne qu’une seule pizza

E0003

Dans la commande, le nom est obligatoire

E0004

Dans la commande, le numéro de téléphone est obligatoire

E0005

Dans la commande, la pizza est obligatoire

E0006

Lorsque la commande aboutie, un récapitulatif de la commande est fourni au client

E0007

Le récapitulatif de commande précise la pizza choisie ainsi que la date et l’heure de la commande

E0008

Le système doit présenter au moins les pizzas suivantes parmi les pizzas à commander : Margherita, Regina, Trois Fromages

E0009

Après l’affichage du récapitulatif de la commande, le client peut passer une nouvelle commande

Préparer une pizza

Pour la préparation d’une pizza, l’application doit disposer d’un nouvel écran qui affiche la liste des commandes de pizzas sous la forme d’un tableau. Le tableau doit indiquer le nom de la personne qui a commandé la pizza et l’heure de la commande. Ce tableau est trié dans l’ordre chronologique (la commande la plus ancienne est en première position). Sur cet écran, apparaît également un bouton commande suivante. Quand l’utilisateur clique sur ce bouton, un nouvel écran s’affiche avec le détail de la commande : la date, le nom et le téléphone de la personne qui a commandé. On indique la pizza commandée et sa composition (la liste des ingrédients). Cet écran contient un bouton pizza prête. Quand l’utilisateur clique sur ce bouton, la commande n’est plus en attente. Elle ne s’affiche donc plus dans le tableau des commandes. Ce tableau est à nouveau affiché afin de permettre de passer à la commande suivante.

Numéro

Exigence

E0100

Un écran doit afficher la liste des commandes non réalisées

E0101

Chaque commande dans la liste indique le nom du client et la date et l’heure de la commande.

E0102

La liste des commandes non réalisées est triée dans l’ordre chronologique.

E0103

Le préparateur de pizza doit pouvoir afficher le détail de la commande suivante

E0104

La commande suivante est la commande non réalisées la plus ancienne

E0105

Le détail de la commande suivante indique la date de la commande, le nom du client, le numéro de téléphone, la pizza commandée et la liste des ingrédients pour cette pizza.

E0106

Le préparateur de pizza doit pouvoir indiquer que la commande est prête

E0107

Une commande prête ne doit plus figurer dans la liste des commandes non réalisées

E0108

Lorsque le préparateur de pizza signale qu’une commande est prête, il doit pouvoir ensuite afficher le détail de la commande suivante

La matrice de traçabilité des exigences

Les tests d’acceptation permettent de valider la conformité d’un système à une liste d’exigences. Mais comment savoir si les tests d’acceptation couvrent l’ensemble des éléments de cette liste ? Pour cela, nous pouvons construire une matrice de traçabilité des exigences.

Puisque chaque cas de test est lié à une ou plusieurs exigences, on considère que chaque scénario qui utilise ce cas de test est également lié à ces exigences. On peut facilement construire un tableau à double entrée. En ligne, nous plaçons les exigences et en colonne, les scénarios de test. À l’intersection d’une ligne et d’une colonne nous pouvons indiquer si l’exigence est couverte par ce scénario (ou plus précisément par un des cas de test qui le constitue).

Note

L’utilisation d’un outil informatique pour la gestion des exigences, des cas de test et des scénarios de test se révèle ici très utile. Ce type d’outil est capable de produire une matrice de traçabilité pour un ensemble de scénarios de test.

Exercice

Matrice de traçabilité des exigences pour une application de commande de pizza

Pour l’application de commande de pizza, construisez la matrice de traçabilité des exigences pour l’ensemble de vos scénarios de test.

Rapport de test

La phase de recette est constituée de plusieurs sessions de test au cours desquelles on doit réaliser les tests décrits dans les cahiers de test. Le résultat de ces sessions est conservé sous la forme de rapports de test. Un rapport de test indique pour chaque étape d’un scénario si le résultat attendu a bien été observé. Sinon, le testeur a la possibilité de rapporter le résultat observé afin de fournir une indication sur l’écart par rapport au résultat attendu.

L’utilisation d’un outil informatique permet de créer facilement des rapports de test en proposant au testeur de valider ou non un scénario de test étape par étape. Dans le cas d’une non validation, le testeur peut immédiatement décrire le comportement observé.

Pour le développement de solution de tests automatisés, il existe de nombreuses bibliothèques de programmation qui permettent de produire automatiquement le rapport d’exécution des tests.

Exercice

Rapport de test pour une application de commande de pizza

Pour l’application de commande de pizza, réalisez une session de test en vous connectant à l’application en ligne. Produisez le rapport de test de cette session de test. Le rapport de test doit préciser pour chaque étape si le résultat obtenu est conforme au résultat attendu. Si ce n’est pas le cas, le testeur doit indiquer ce qui a été observé pour permettre d’identifier éventuellement un défaut.

Méthodes agiles

Il existe plusieurs méthodes agiles. Les plus utilisées et les plus connues sont Scrum et eXtreme Programming (XP). Ces méthodes ne reposent pas sur la notion de projet et ne se présentent donc pas comme une succession de phases situées entre une date de début et une date de fin.

Les méthodes agiles sont dites itératives et incrémentales. Le travail de l’équipe de développement est découpé en bloc de temps fixe (appelé Sprint dans Scrum et Itération dans XP) ne dépassant pas quelques semaines. À la fin de chaque bloc de temps, l’équipe fournit un produit correspondant au produit précédent plus ce qui a été rajouté par le travail de l’équipe. Il peut s’agir de nouvelles fonctionnalités : on parle alors de développement incrémental puisque le produit dispose de nouveaux éléments par rapport à la version précédente. Il peut s’agir d’une amélioration de fonctionnalités existantes : on parle alors de développement itératif puisque l’équipe a repris quelque chose d’existant pour l’enrichir. Dans la réalité, les équipes utilisent indifféremment ces deux approches pour, petit à petit, développer le produit.

Dans une approche agile, l’expression de besoin n’est pas nécessairement entièrement collectée au lancement des développements. Cette approche insiste sur la capacité à améliorer le produit et à s’adapter au changement au fur et à mesure des développements. La notion d’exigence est alors peu applicable et on la remplace, entre autres, pour l’utilisation de User Stories. Une User Story décrit une interaction du point de vue d’un utilisateur. Un produit est défini par l’ensemble des User Stories qui évolue au cours des développements. Chaque User Story doit être testable, c’est-à-dire fournir des critères d’acceptation.

Dans une approche agile, les tests d’acceptation s’inscrivent dans un processus de développement différent. Les tests sont rédigés lorsque les développeurs doivent implémenter la partie du système répondant à une User Story. Ainsi, les tests d’acceptation servent d’abord à compléter la description d’une User Story. Il n’est plus question de vérifier un écart avec une exigence mais de préciser les objectifs du développement.

L’eXtreme Programming a proposé l’approche ATTD (Acceptance Test Driven Development). Il s’agit de rédiger les tests d’acceptation avant le développement d’une User Story (ou, au moins, les tests d’acceptation les plus significatifs) de manière à guider les développements au plus près des attentes des utilisateurs. Avec les méthodes agiles, la notion de test d’acceptation évolue en insistant sur les aspects de documentation du système et de support à la communication entre les différents intervenants.

Le Behavior Driven Developement (BDD)

Le BDD (Behavior-Driven-Development) est une approche proposée par Dan North dans son article Introducing BDD. Le BDD est en fait une évolution de la notion de test d’acceptation en agilité : le BDD se fonde sur le constat qu’il est plus pertinent de raisonner en terme de description de comportement du système qu’en terme de test. Le test n’est qu’un formalisme pour mesurer les écarts entre une expression de besoin et un produit.

L’approche BDD oblige à revoir la notion de test et d’expression de besoins. Le BDD s’appuie sur les méthodes agiles et reprend la notion de critères d’acceptation d’une User Story. Ces critères devraient correspondre à des exemples d’utilisation du système. En utilisant un formalisme pour la rédaction de ces exemples, ils deviennent un support à la communication entre tous les intervenants, qu’ils soient développeurs, utilisateurs, experts fonctionnels. Dan North propose de suivre un formalisme simple : Given, When, Then.

Given some initial context,
When an event occurs,
Then ensure some outcomes.

Soit en français :

Etant donné un contexte initial,
Quand un événement survient,
Alors on s'assure de certains résultats

En utilisant ce formalisme, les scénarios deviennent facilement communicables entre les développeurs, les experts fonctionnels et toutes les parties-prenantes. Ces scénarios deviennent un support à la discussion et à la compréhension des fonctionnalités à réaliser. Avec le BDD, la spécification du système est constituée par l’ensemble de ces scénarios.

De plus, en utilisant ce formalisme, il est possible de concevoir des outils capable d’analyser les scénarios et de les exécuter. On parle alors de spécification exécutable. Ainsi, on obtient la possibilité de valider plus rapidement le système par l’exécution de programme de test et on conserve une rédaction en langage naturel, facilement partageable à l’ensemble des intervenants.

Note

Gojko Adzic présente cette nouvelle façon de spécifier un système dans son ouvrage Specification by Examples

Plusieurs frameworks ont été proposés pour aider à réaliser une automatisation des scénarios BDD : FitNesse, JBehave (développé par Dan North lui-même) et Cucumber. Cependant, il ne faut pas voir le BDD comme une approche technique. Il s’agit d’organiser le développement logiciel différemment en repensant, d’une part, le lien entre expression de besoin et validation et, d’autre part, en cherchant à établir une communication constante entre les développeurs et les experts fonctionnels en leur fournissant en langage commun.