• Aucun résultat trouvé

Discussion du résultat de l’application de notre algorithme sur le cas d’étude 85

3.1 Introduction

Dans le chapitre précédent nous avons présenté les tests logiciels et les différentes techniques de tests. Nous avons également présenté le langage de modélisation unifié UML et plus précisément le diagramme de séquences. Ensuite nous avons présenté le Model-Based Testing (MBT), son efficacité pour tester des systèmes, et les différentes approches existantes du MBT avec les avantages et les inconvénients de chacune. Nous avons également présenté la problématique liée aux approches existantes du MBT, notre nouvelle approche et sa position par rapport à ces approches du MBT.

Dans ce chapitre, nous détaillons notre contribution qui introduit une nouvelle mé-thodologie pour rendre le MBT plus accessible aux sociétés.

Notre méthodologie se positionne entre la phase de conception et la phase de test dans un cycle de développement en V d’un système. Elle a pour objectif de générer un modèle d’usage. Toutefois, le modèle d’usage généré doit être facile à maintenir et doit être factorisé (sans beaucoup de duplication des états et des transitions). Pour cela, nous devons trouver une solution pour ne pas dupliquer les transitions tant que c’est possible tout en gardant le modèle généré fonctionnellement valide par rapport à la spécification et ainsi on aura un nombre réduit d’états. En d’autres termes, pour un message m, si il existe dans le modèle d’usage une transition avec le label m (créée suite à la transforma-tion d’un message m) nous devons utiliser cette transitransforma-tion si c’est possible tout en gardant le modèle d’usage conforme par rapport à la spécification fonctionnelle du SUT. L’utilisa-teur pourra intervenir sur certains choix de factorisation pour orienter la génération du modèle.

Comme représenté dans2.3, le test est l’une des phases les plus coûteuses dans un cycle de développement. Le MBT est une méthode qui optimise cette phase. Il consiste à générer automatiquement des tests de validation à partir d’un modèle de test, décrivant certains aspects fonctionnels du système sous test (SUT) [UL07]. Le MBT est une tech-nique rentable [SMJU10] et permet de réduire les efforts et le temps consacrés à tester un système en générant automatiquement des scripts de tests. Cependant, il reste très peu utilisé dans le monde industriel. Les causes majeures de ce faible succès résident d’une part dans la difficulté de gérer et de maintenir un nouveau modèle dédié aux tests et d’autre part dans la nécessité d’un changement de processus de développement.

Pour rendre le MBT plus accessible, notre méthodologie consiste à construire d’une manière semi-automatique un modèle d’usage d’un système en utilisant des modèles de spécification et de conception existants de ce système quels que soient leurs niveaux de détails.

Ces modèles peuvent être décrits dans des formats tels que UML [OMG05] et SySML [SYS20] et des cas de test existants. Dans cette thèse on applique notre méthodologie sur

la génération d’un modèle d’usage, compatible avec le modèle d’usage MaTeLo, à partir d’un ensemble de diagrammes de séquences. Ensuite les cas de tests sont générés auto-matiquement à partir de ce modèle en utilisant l’outil de MBT MaTeLo.

La Figure 3.1 présente les étapes de transformation des diagrammes de séquences jusqu’à la génération des cas de tests. Notre méthodologie prend en entrée un ensemble de diagrammes de séquences. Après application de notre méthodologie sur cet ensemble de diagrammes de séquences, on obtient en sortie un modèle d’usage compatible avec le modèle d’usage de MaTeLo. Ensuite, nous utiliserons l’outil MaTeLo pour charger ce modèle et générer les cas de tests.

FIGURE3.1 – Étapes de génération de modèle d’usage

Une entrée d’un système sous test ne permet pas toujours de prédire son comporte-ment. En effet, cela dépend de l’état du SUT lors de l’application d’un événecomporte-ment. Deux événements sont gérés différemment par le SUT en fonction de l’ensemble des entrées précédentes du SUT. Par exemple, l’appui sur la pédale d’accélération d’une voiture ne sera pas la même si la voiture est démarrée ou en arrêt. Pour factoriser deux messages, d’un diagramme de séquences, équivalents et pour créer un modèle d’usage valide (confor-mément à un document de spécification) de manière pertinente, nous devons gérer l’his-torique des événements précédents sur le SUT, c’est ce qu’on appelle le context.

La Figure3.2présente notre méthodologie permettant de générer un modèle de test optimisé, facile à maintenir et conforme aux spécifications fonctionnelles, à partir d’un

ensemble de diagrammes de séquences, quels que soient leurs niveaux de détails. Notre méthodologie est composée de deux contributions majeures (Figure3.2) :

FIGURE3.2 – Méthodologie développée

— Contribution 1 (C1) : Enrichissement du modèle d’usage MaTeLo par la notion du context afin de pouvoir générer un modèle d’usage à partir d’un ensemble de dia-grammes de séquences d’une façon pertinente, valide et avec le minimum de du-plications possibles.

— Contribution 2 (C2) : Un algorithme pour générer un modèle d’usage à partir d’un ensemble de diagrammes de séquences.

Notre méthodologie prend en entrée un ensemble de diagrammes de séquences et produit en sortie un modèle d’usage factorisé et compatible avec le modèle d’usage Ma-TeLo. Elle est composée de trois étapes (Figure3.2) :

— Pour chaque diagramme de séquences à transformer, uniquement les informations utiles pour le test fonctionnel sont sélectionnées (1)

— Chaque diagramme de séquences est transformé et intégré dans le modèle d’usage (2)

— Le modèle d’usage est factorisé tout en gardant sa validité en appliquant la notion du context (3)

3.2 Introduction de la notion du context

Selon le modèle d’usage de MaTeLo présenté dans2.5.1.1, lorsque le processus est dans un état particulier du modèle, l’historique des événements précédents sur le SUT est ignoré. Ainsi, quel que soit le chemin parcouru pour atteindre cet état, il peut être

considéré comme équivalent à n’importe quel autre chemin pour l’exécution ultérieure du système.

D’autre part, un chemin de modèle est associé à un ensemble d’entrées ordonnées utilisées comme stimulation sur le SUT. En supposant que certains ensembles d’entrées ne sont pas similaires à d’autres, il devient nécessaire de dupliquer un état spécifique (identifié par un événement de transition précédent commun) dans autant d’états que de "situations" qui peuvent être ensuite considérées comme équivalentes du point de vue du comportement futur.

Par exemple, considérons le cas de la triple saisie d’un code PIN erroné d’une carte bancaire dans une machine ATM. Pour modéliser manuellement ce cas, on ne peut pas insérer un seul état après une transition associée à l’action "setPin" sans tenir compte de l’historique des entrées précédentes. Dans ce cas, nous devons savoir si nous avons déjà fait (sans succès intermédiaire) 0, 1 ou 2 tentatives sans succès. Il faut donc séparer l’état après "setInvalidPin" en 3 états différents. La solution d’un tel cas est illustrée dans la Fi-gure3.3. Mais dans beaucoup de cas de modélisation, ce n’est pas si évident (surtout si l’utilisateur peut faire d’autres actions entre "setInvalidPin") pour avoir un modèle com-plet de chaque cas d’utilisation.

FIGURE3.3 – Duplication d’états

Si nous voulons réduire le nombre d’états, pour avoir un modèle factorisé tout en gar-dant le modèle fonctionnellement valide, et être capable de «rediriger» la génération en fonction d’une situation particulière, nous proposons la notion du context. La notion du context peut être considérée comme une représentation abstraite d’un état interne du SUT. Si cet état interne est connu, alors le comportement futur du système est connu lorsqu’une nouvelle stimulation (un ensemble d’entrées) est reçue par le SUT. Le com-portement du système signifie ici la sortie produite par le SUT.

mémoriser le contexte en fonction de tous les facteurs particuliers. Les différentes valeurs prises par chacune de ces variables de contexte sont identifiées dans un ensemble fini de valeurs ou de caractéristiques. À tout moment, il n’y a qu’une seule valeur "active" pour une variable de contexte donnée. Chaque variable de contexte a une valeur active au début du test et cette valeur varie pendant la génération en fonction des stimulations effectuées.

Considérons C={C1, . . . , Cn} l’ensemble de variables de contexte. Vi une valeur de l’en-semble {Vi, . . . , Vn} de valeurs possibles de la variable de contexte Ci. Pour chaque variable de contexte Ci, nous définissons un ensemble de relations Ri. Une relation Ri définit une relation entre une valeur initiale d’une variable de contexte et sa nouvelle valeur lorsque le SUT reçoit une entrée Ik. Chaque relation Ri est évaluée à chaque nouvelle étape lors de la génération d’un cas de test. L’ensemble des variables de contexte peut être considéré comme un ensemble de graphiques indépendants qui évoluent lorsque de nouvelles sti-mulations sont générées dans le modèle d’usage. Le contexte actuel peut être connu en examinant chaque état pris dans les différents graphiques de contexte.

Pour utiliser cette information, nous ajoutons un nouvel objet dans le modèle d’usage de MaTeLo permettant le routage de la génération des cas de tests en fonction du contexte. Nous appelons ce nouvel objet «transition conditionnelle» (Figure 3.4). La transition conditionnelle peut connecter un état «source» à plusieurs états «cible». Il y a un mutateur au centre de cette transition conditionnelle. La transition entrante dans le com-mutateur est appelée «tronc». Chaque transition sortante de ce comcom-mutateur est appelée «branche». Le commutateur permet de spécifier pour chaque branche la valeur d’un en-semble de variables de contexte afin de sélectionner cette branche. Lorsque le processus de génération est au niveau du commutateur, la branche ayant la condition valide sera sé-lectionnée. Le commutateur sera configuré pour avoir toujours une et une seule branche possible à tout moment. Souvent une seule variable de contexte est pertinente à un mo-ment donné.

Considérons notre exemple de la figure3.3, nous pouvons réduire les états en créant une entrée du SUT nb_tentatives qui représente le nombre de tentatives erronées effec-tuées. On initialise la valeur de cette entrée nb_tentatives à 1. Ensuite on crée une variable de contexte tentatives_possible, utilisée pour indiquer si on peut effectuer d’autres ten-tatives de saisie de code PIN. Le type de cette variable de contexte tenten-tatives_possible est boolean, donc les valeurs possibles de cette variable sont {true, false}. On initialise la valeur de cette variable de contexte à true (vrai).

Par la suite, on crée une relation Rt ent at i vesqui indique que lorsque la valeur de l’en-trée nb_tentatives est supérieure à 3, la valeur de la variable de contexte tentatives_pos-sible devient false.

re-FIGURE3.4 – Transition conditionnelle

lie les états A et B. Le tronc de cette transition conditionnelle sera nommé "Set invalid PIN". Sur ce tronc on associe une fonction de traitement d’incrémentation (disponible dans MaTeLo) permettant d’incrémenter la valeur de l’entrée nb_tentatives à chaque fois qu’on passe par cette transition. Cette transition conditionnelle possédera deux branches :

— Une branche "Blocked Card" qui a comme état cible l’état B.

— Une branche "T" (sans nom) qui a comme état cible l’état A.

Ensuite, on configure le commutateur de la façon suivante :

— Si la valeur de la variable de contexte tentatives_possible est true, alors la branche "T" est sélectionnée.

— Si la valeur de la variable de contexte tentatives_possible est false, alors la branche "Blocked Card" est sélectionnée.

Le résultat est visible dans la figure3.5. Avec la notion du context, nous allons pou-voir factoriser le modèle d’usage généré, pour apou-voir un modèle facile à maintenir tout en le gardant valide par rapport à la spécification du SUT. Suite à l’enrichissement du modèle d’usage MaTeLo avec les transitions conditionnelles, la formalisation mathéma-tique du modèle MaTeLo, présentée dans2.5.1.1, peut être présenté par le tuple : M = {S, si, sf, V, F, P, T, E, C, R, Tc} où :

— C : L’ensemble des variables de contextes

— R : L’ensemble des relations des variables de contextes

FIGURE3.5 – Exemple d’une transition de conditionnelle

3.3 Algorithme de transformation

Pour rappel, notre objectif est de générer un modèle d’usage à partir d’un ensemble de diagrammes de séquences. Ce modèle d’usage doit être fonctionnellement valide par rapport au SUT et facilement maintenable.

Comme présenté dans la section2.6.1.2, un diagramme de séquences UML contient des messages et optionnellement des fragments. Il peut être mathématiquement forma-lisé par le tuple SD= {A, L, Ms, F} où :

— A : L’ensemble des acteurs principaux et secondaires. Dans notre travail, nous nous intéressons uniquement aux acteurs principaux.

— L= {L0, ..., Ln} : L’ensemble des lignes de vies.

— Ms= {m0, ..., mn} : L’ensemble des messages. ∀ mi∈ Msavec 0<=i<=n, mi={l abel , Ls, Ld} avec label présente le label de mi, Lsprésente la ligne de vie de départ de mi et Ld présente la ligne de vide d’arrivéede mi

— F : L’ensemble des fragments

On considère un modèle d’usage intermédiaire Mu, compatible avec le modèle d’usage MaTeLo. Muest présenté par le tuple : Mu= {S, si, sf, scT, C, R, Tc} où :

— S = {s0, ..., sn} : Un ensemble fini d’états

— si: L’état initial unique

— sc : L’état courant. Cet état pointe soit sur l’état si soit sur un état sn∈ S .Par défaut sc = si

— T = {t0, ..., tn} : Un ensemble fini de transitions. ∀ ti∈ T avec 0<=i<=n, ti= {l abel , ssour ce, sd est i nat i on} avec label présente le label de ti, ssour ceprésente l’état source de ti et sd est i nat i onprésente l’état destination de ti

— C : L’ensemble des variables de contextes

— R : L’ensemble des relations des variables de contextes

— Tc : L’ensemble des transitions conditionnelles

Notre algorithme prend en entrée un ensemble de diagrammes de séquences {SD} et génère automatiquement un modèle d’usage Mu(cf.3.6).

FIGURE3.6 – Algorithme de génération d’un modèle d’usage

Il est composé de trois phases :

— Phase d’Identification : C’est la première phase de notre algorithme qui consiste à identifier les données pertinentes pour la création d’un modèle de test fonctionnel. Dans cette thèse, nous sommes intéressés par les tests fonctionnels (boîte noire), donc seuls les messages de et vers l’acteur principal sont sélectionnés. Chaque frag-ment, tel que "ALT", "LOOP" et "OPT", est également considéré si il contient un message ayant comme ligne de vie l’acteur principal.

— Phase de Transformation : C’est la deuxième phase de notre algorithme qui consiste à transformer chaque message et chaque fragment identifiés dans la phase d’iden-tification. L’utilisateur peut intervenir lors de cette phase pour diriger la génération en indiquant si deux messages peuvent être considérés "équivalents" et donc si ils peuvent être factorisés.

— Phase de Factorisation : Cette troisième phase consiste à factoriser, si possible, deux messages. La factorisation doit être appliquée de façon à pouvoir garder le modèle de test fonctionnellement valide. Pour cela la notion du context, présentée précédemment, sera utilisée.

Notre algorithme traite les diagrammes de séquences un par un, et pour chacun d’entre eux il applique ses trois phases.

Notre algorithme débute par la création d’un modèle d’usage contenant uniquement un état initial siet un état final sf comme représenté dans la figure3.7. Ce modèle d’usage par défaut est présenté par Mu={si, sf}.

FIGURE3.7 – Modèle d’usage initial

Ensuite, pour chaque diagramme de séquences SD à transformer :

— L’utilisateur sélectionne un état de Muqu’il souhaite utiliser comme état de départ pour la transformation et l’insertion du premier message du SD. En d’autres termes, l’utilisateur sélectionne un état snde Muet qui est considéré comme état courant du Mu, sc pointe vers sn. sc évolue après chaque transformation et insertion d’un message de SD dans Mu. Notons que lorsque le sous ensemble S de Mu est vide, c’est l’état si qui est utilisé comme état courant du Mu, sc pointe vers si, et dans ce cas l’utilisateur n’est pas invité à sélectionner un état courant.

— Nous parcourons le contenu de SD et nous appliquons les phases de notre algo-rithme.

— A la fin de la transformation de SD, tous les états n’ayant pas de transition sortante seront liés à sf du Mu en créant des transitions sans label. Ces transitions servent uniquement pour créer un modèle valide où chaque état du modèle doit être acces-sible, directement ou indirectement, à partir de si et sf. Ces transitions ne seront pas considérées comme des étapes de tests lors de la génération des cas de tests.

Nous présentons par la suite les trois phases de notre algorithme.

3.3.1 Phase d’identification

Cette phase consiste à identifier les messages et les fragments pertinents pour la créa-tion d’un modèle de test. Dans ce travail nous sommes intéressés par le test fonccréa-tionnel (boîte noire) voir section2.3.1.3, donc on sélectionne uniquement les messages qui ont un lien (départ ou arrivée) avec une ligne de vie des acteurs principaux (utilisateurs) LAc t eur. En d’autres termes, pour un SD donné, on sélectionne tous les mi={l abel , Ls, Ld} ∈ Msoù Ls= LAc t eur ou Ld = LAc t eur.

On sélectionne également chaque fragment, tel que "ALT", "LOOP" et "OPT", conte-nant un message ayant un lien avec une ligne de vie des acteurs principaux. Ensuite, pour chaque élément, message ou fragment, sélectionné dans cette phase, nous appliquons la phase de transformation.

Considérons l’exemple du diagramme de séquences représenté dans la figure3.8.

FIGURE3.8 – Phase d’identification

La formalisation mathématique de ce diagramme est SD= {A, L, Ms, F} où :

— A= {A1, A2} présente l’ensemble des acteurs principaux

— L= {LA1, LA2, LS1, LS2, LS3} présente l’ensemble des lignes de vies, Où

— LA1est la ligne de vie attachée à l’acteur principal Acteur1

— LA2est la ligne de vie attachée à l’acteur principal Acteur2

— LS1est la ligne de vie attachée au système Systeme1

— LS2est la ligne de vie attachée au système Systeme2

— LS3est la ligne de vie attachée au système Systeme3

— Ms= {m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16} pré-sente l’ensemble de messages, où :

— m1 = {a1, LA1, LS1} — m2 = {a2, LS1, LS2} — m3 = {a3, LS2, LS3} — m4 = {r 1, LS3, LS2} — m5 = {r 2, LS2, LS1} — m6 = {r 3, LS1, LA1}

— m7 = {a4, LA1, LS2} — m8 = {r 4, LS2, LA1} — m9 = {a4, LA2, LS1} — m10 = {a6, LS1, LS2} — m11 = {r 5, LS2, LS1} — m12 = {r 6, LS1, LA2} — m13 = {a8, LS1, LS2} — m14 = {r 8, LS2, LS1} — m15 = {a9, LA1, LS1} — m16 = {r 9, LS1, LA1}

— F = {ALT, LOOP}, présente l’ensemble des fragments. On remarque que dans cet exemple l’opérateur ALT ne contient aucun message m où m.Ls ou m.Ld est égale à LA1ou LA2

Après application de la phase d’identification sur ce SD, on obtient le diagramme de séquences SDuprésenté dans la figure3.9. SDu contiendra uniquement une ligne de vie attachée à l’acteur principal, LA, et une ligne de vie attachée au système LS.

La formalisation mathématique de SDuest : SDu= {Au, Lu, Msu, Fu} où :

— Au= {Ac t eur } présente un acteur principal qui représente les deux acteurs Acteur1 et Acteur2 de A

— Lu= {LA, LS} présente l’ensemble des lignes de vies

— Msu= {m1, m6, m7, m8, m9, m12, m15, m16} présente l’ensemble des messages, où — m1 = {a1, LA, LS} — m6 = {r 3, LS, LA} — m7 = {a4, LA, LS} — m8 = {r 4, LS, LA} — m9 = {a4, LA, LS} — m12 = {r 6, LS, LA} — m15 = {a9, LA, LS} — m16 = {r 9, LS, LA} — Fu= {LOOP}

Les messages {m2, m3, m4, m5, m10, m11, m13, m14} sont ignorés car il n’ont pas de liens avec les lignes de vies LA1 ou LA2. Le même raisonnement s’applique pour le frag-ment ALT qui ne contient aucun message possédant un lien avec les lignes de vies LA1ou LA2

FIGURE3.9 – Application de la Phase d’identification

3.3.2 Phase de transformation

Cette phase consiste à transformer et intégrer un message ou un fragment dans le modèle d’usage. Elle est composée de deux étapes, une étape pour la transformation des messages et une étape pour la transformation des fragments.

L’utilisateur pourra intervenir pendant cette phase pour diriger la génération. Nous pouvons aussi imaginer la création de stratégie de génération de modèle d’usage où l’uti-lisateur définit quelques règles à respecter lors de la génération (ex : toujours factoriser des messages m en considérant le context) . Ces stratégies permettent de rendre la géné-ration automatique sans aucune intervention de l’utilisateur au moment de la génégéné-ration d’un modèle d’usage.

On considère deux messages "simples" (non liés à une opération) d’un diagramme de séquences équivalents, si ils possèdent le même nom et ils ont la même ligne de vie de départ et d’arrivée. On considère deux messages "opérations" (liés à une opération du diagramme de classe) d’un diagramme de séquences équivalents si ils possèdent la même signature de méthode (nom, classe conteneur et même nombre et types de paramètres) et ils ont la même ligne de vie de départ et d’arrivée. On traite les messages "simples" et