• Aucun résultat trouvé

Lors de la génération de tests selon une certaine stratégie pour la validation et la vérifi-cation d’un système1, il faut se poser deux questions fondamentales : “Qu’est-ce qu’on veut

tester ?” et “Quand est-ce qu’on s’arrête de tester ?”. C’est en répondant à ces questions que nous pourrons définir les critères selon lesquels on pourra attester de l’absence d’erreurs dans le logiciel par la génération de tests pertinents. Nous pourrons ainsi valider le compor-tement fonctionnel du système selon un certain niveau de confiance par l’évaluation de la qualité de la campagne de test. Dans cette section, nous détaillerons les activités de test présentées dans le chapitre 1, puis nous présenterons quelques méthodes de résolution de problèmes d’optimisation combinatoires, outils essentiels pour la génération automatique de tests.

3.2.1 Déterminer les points à vérifier à partir d’objectifs de test

Le test exhaustif sur toutes les entrées possible du système étant impossible, une solution raisonnable est d’effectuer une campagne de test contenant un ensemble de tests réduit mais significatif permettant de trouver le nombre maximum d’erreurs ou de comportements non-conformes aux exigences dans le logiciel [79]. Pour générer des tests significatifs, il faut définir clairement quelles erreurs on souhaite détecter dans le logiciel, c’est-à-dire définir des objectifs de tests. Des objectifs de tests classiques pour la certification de logiciels embarqués sont par exemple :

• chaque exigence doit être testée au moins une fois,

• chaque opération doit être testée pour des valeurs de fonctionnement normal, resp. anormal, au moins une fois,

• la campagne de test doit atteindre la couverture des exigences par les critères de couverture MCDC, etc.

Les objectifs de tests permettent de déterminer les points précis que nous voulons atteindre dans le système pour vérifier la présence ou l’absence d’erreurs, auxquels nous associons un comportement attendu, c’est l’oracle de test. Ces objectifs peuvent être plus ou moins précis selon le niveau de description des fonctionnalités et les contraintes relatives à la certification du logiciel. La validation du système est donc limitée à un nombre fini d’objectifs de tests motivés par la recherche d’erreurs potentielles présentes dans le logiciel. Cependant, cette méthodologie permet d’associer à un objectif de test défini de façon précise et non-ambiguë des liens de traçabilité forts entre un test généré et l’exigence qui en est la source.

3.2.2 Déterminer les stimulations pour atteindre des points du système

La génération de tests se découpe donc en deux parties ; nous avons d’abord étudié la détermination des points du système à valider par le test. Nous nous intéressons

mainte-nant au problème de la génération de stimulations numériques fiables à partir des com-portement attendus identifiés précédemment. Déterminer une séquence de stimulations permettant d’atteindre un point spécifique du système revient à un problème de recherche de chemin dans un espace de configuration [80, 81]. C’est un problème difficile dû à la taille de cet espace, et à l’hétérogénéité des fonctionnalités décrites dans les exigences (booléennes/numériques, combinatoires/séquentielles, linéaires/non-linéaires) [82, 62].

Combiner une analyse de la propagation des erreurs de calcul pour pouvoir déterminer des stimulations numériques de manière fiable avec une analyse structurelle des états et transitions du système permettant d’atteindre le comportement attendu à observer dans le logiciel est un problème difficile [81], aussi bien pour des tests générés de façon automatique que manuelle. Le document de recommandations pour la certification de logiciels embarqués DO178–C [1] prévoit donc de remplacer la génération de certains tests par des activités de relecture et d’analyse (voir figure 1.3).

On peut donc envisager de développer un outil de génération automatique de tests exécutant plusieurs actions. À partir d’une spécification fonctionnelle formalisée traduire (à la main) des exigences textuelles et d’objectifs de tests décrits dans ce même formalisme, l’outil détermine les points du système correspondant, c’est-à-dire les comportements attendus. La deuxième étape est de générer les stimulations correspondantes permettant d’atteindre la configuration souhaitée dans le système pour vérifier les comportements attendus. L’outil peut s’arrêter avant d’avoir atteint le critère d’adéquation si l’une des deux étapes de génération de test est trop difficile à calculer, du moment qu’il informe l’utilisateur précisément sur les tests qui n’ont pas été générés.

3.2.3 Vérifier la qualité des tests

Cette dernière notion de fiabilité d’une campagne de test peut être quantifiée grâce au critère d’adéquation d’un ensemble de tests à une spécification fonctionnelle. Si on considère un ensemble d’exigences fonctionnelles E , on peut alors définir l’ensemble des programmesψ non-équivalents implémentés à partir de E, ce qui signifie que ces pro-grammes sont développés différemment et ne présentent potentiellement pas les mêmes fonctionnalités. Un ensemble de tests T est dit adéquat [83] pour le système d’exigences E relativement àψ si pour chaque programme P ∈ ψ, P ne passe pas la campagne de test pour au moins un point de test, alors T a découvert une erreur dans P par rapport à E [83]. Si l’ensemble de programmesψ implémentés à partir de E est fini, alors E possède un ensemble de tests adéquat.

Définition 5 (Critère d’adéquation des tests [79, 84]). Un critère d’adéquation des tests est

En général, le critère d’adéquation des tests est un ensemble de règles dérivées des objectifs de test ; il est alors satisfait lorsque tous les objectifs de tests sont remplis par au moins un cas de test2. Dans la section 1.2.1 nous avons définis si des critères recommandés d’évaluation de la qualité d’une campagne de tests pour la certification. L’ensemble de ces critères, correspondent aux objectifs de tests, forment donc le critère d’adéquation des tests. Ainsi le but de la génération d’une campagne de test est de remplir le critère d’adéquation associé avec un nombre nécessaire et suffisant de tests, soit de remplir tous les objectifs de tests déterminés pour valider les fonctionnalités des exigences avec un minimum de tests. La génération de tests peut être apparentée à un problème d’optimisation [81].

3.2.4 Résoudre des problèmes d’optimisation combinatoire

Programmation par contraintes La programmation par contraintes [85] est un

para-digme de programmation dans lequel les relations entre les inconnues d’un problème, c’est-à-dire les variables, sont décrites sous la forme de contraintes, c’est-à-dire de relations entre les variables limitant leurs domaines de définition. Le problème est de trouver des valeurs pour les variables satisfaisant la contrainte, ou toutes les contraintes du modèle. Un ensemble de valeurs associées aux variables sont dites cohérentes si elles forment une solu-tion des contraintes. La recherche de solusolu-tions est effectuée par des solveurs de contraintes, dont la tâche consiste à éliminer les valeurs inconsistantes. La résolution de contraintes pour la génération de tests numériques est utilisée dans plusieurs outils de génération de tests pour la vérification et validation de logiciels critiques. On compte notamment l’outil GaTel [86], développé par la Commissariat à l’énergie atomique (CEA) se basant sur une représentation en Lustre d’une spécification du logiciel, et manipulant des variables booléennes et entières. On remarque également le cadre applicatif FPCS [87] qui propose de générer des tests pour des intervalles à partir d’un programme annoté. Les tests visent à vérifier les intervalles où le comportement du programme pourrait ne pas être conforme à un modèle manipulant des nombres réels.

Satisfaisabilité modulo théories (SMT) Un problème SAT (pour satisfaisabilité),

s’expri-mant grâce à une formule de logique propositionnelle, s’attache à déterminer s’il existe une configuration des variables propositionnelles satisfaisant ce problème, c’est-à-dire rendant la formule vraie [88]. Un problème SMT est une généralisation du problème SAT à la logique du premier ordre, étendue avec des symboles de fonction et de prédicat particu-liers, formant des théories. Un problème SMT peut donc décrire, par exemple, la théorie de l’arithmétique linéaire sur les entiers (LIA) ou la théorie des tableaux (Array). La tech-nique SMT repose sur des procédures de décision, soit des petits algorithmes de preuve

pour décider de la satisfaisabilité de formules pour les théories élémentaires données en exemple ci-dessus [89]. Combiné à la programmation par contrainte, un problème SMT peut également permettre une représentation formelle précise des nombres à virgule flot-tante [90]. Il existe tout un éventail de solveurs SMT permettant de montrer l’existence d’une configuration satisfaisant le problème, certains dédiés à des problèmes spécifiques et d’autres plus généralistes. Pour optimiser l’utilisation d’un solveur SMT, il est important de bien analyser le problème que l’on souhaite résoudre ainsi que la structure de données adéquate. Les problèmes SMT peuvent être utilisés dans le cadre de la preuve de circuits électroniques, ou pour les problèmes de coloration de graphes [91]. La complexité de ce genre de problème croît de façon exponentielle avec l’augmentation de la taille des données. La principale difficulté liée à la résolution de problèmes de décision à l’aide de solveurs SMT est la scalabilité [88].