Valid XHTML     Valid CSS2    

DECRA : Décomposition, Conception et Réalisation d'Applications

Cours 7 : Tests et documentations des applications

Table des matières cliquable

  1. De la ligne de commandes au formulaire et aux tests

  2. Principes pour une documentation efficace

  3. Notion de qualité logicielle

1. De la ligne de commandes au formulaire et aux tests

2.1 Ligne de commandes et tests

La ligne de commandes et les interfaces graphiques ne sont pas antinomiques. Les menus et interfaces graphiques sont incomparables lorsqu'il s'agit de découvrir les possibilités d'un logiciel mais ils ont deux gros défauts : ils s'utilisent via le clavier et la souris, ce qui les rend difficilement automatisables et ils sont visuels, ce qui fait qu'en général ils ne produisent aucun fichier de résultat pour conserver une trace de ce qui a été fait. De plus ils ne permettent pas toujours simplement de résoudre des problèmes simples, comme par exemple trouver les cinq derniers fichiers .txt écrits dans un répertoire donné à l'aide d'un explorateur de fichiers graphique ou de compter le nombre de fichiers .awk ou .php dans le répertoire courant et ses sous-répertoires, comme le permettrait la commande


          find . | grep "\.awk$\|\.php$" | wc -l
     

Un développeur doit donc savoir choisir quand utiliser la ligne de commandes et quand passer par une interface, quitte à réaliser une interface pour accéder plus rapidement aux commandes, par exemple s'il faut mettre à disposition l'application pour des utilisateurs moins expérimentés. Si on admet qu'on doit tester une fonction paramétrée, par exemple, il est clair que recenser tous les cas d'utilisation et les mettre dans un script permet de vérifier que tous les cas sont traités. A titre illustratif, reprenons la conversion d'une valeur de pouces en centimètres en ligne de commandes (comme ici) ou par page Web via Javascript (). Si nous décidons de tout coder en PHP plutot qu'en REXX/REGINA et Javascript, il est clair qu'il y a deux parties distinctes : la saisie et la conversion. Admettons un instant que la conversion doit se faire via la fonction convCmPouces(valeur,unite).

Voici une première version de code très incomplète, fichier conv1.php :


     <?php # fichier conv1.php
     
     function convCmPouces($valeur,$unite) {
     
       if ($unite=="pouces") {
          return($valeur*2.54) ;
       } else {
          return($valeur/2.54) ;
       } ; # fin si
     
     } ; # fin de fonction convCmPouces
     
     ?>
     

Si on décide de mettre en place des tests de conversion, le minimum est vérifier que les conversions dans les deux sens sont correctes, via par exemple le programme PHP suivant nommé testConv1.php :


     <?php # fichier testConv1.php
     
     # test minimal de la fonction nommée convCmPouces() définie dans le fichier conv1.php
     # ce fichier est à exécuter en ligne de commandes
     
     error_reporting(E_ALL | E_NOTICE ) ;
     include("conv1.php") ;
     
     $pouces = 10 ;
     $cm     = convCmPouces($pouces,"pouces") ;
     echo "\n$pouces pouces correspondent à $cm centimètres.\n" ;
     
     $cm     = 10 ;
     $pouces = convCmPouces($cm,"cm") ;
     echo "\n$cm centimètres correspondent à $pouces pouces.\n" ;
     
     ?>
     

dont l'exécution aboutit aux sorties ci-dessous :


     
     10 pouces correspondent à 25.4 centimètres.
     
     10 centimètres correspondent à 3.9370078740157 pouces.
     

Pour disposer d'une fonction de conversion complète, il faut vérifier que toutes les valeurs sont correctes et transmises. Il est donc prudent ici de mettre des valeurs par défaut et de vérifier que le nom de l'unité est bien écrit. Ce que doit renvoyer la fonction en cas d'erreur est délicat. Nous prendrons ici -1 comme retour incorrect, ce qui sera facile à tester pour la partie saisie/vérification et qui reste une valeur numérique.

Voici donc une seconde version du code de la fonction, plus complet, fichier conv2.php :


     <?php # fichier conv2.php
     
     function convCmPouces($valeur="?",$unite="?") {
     
       if (($valeur=="?") or ($unite=="?")) { return (-1) ; }
     
       $valeur = strtr($valeur,",",".") ;
     
       if (!(($unite=="pouces") or ($unite=="cm"))) { return (-1) ; }
     
       if ($unite=="pouces") {
          return($valeur*2.54) ;
       } ; # fin si
     
       if ($unite=="cm") {
          return($valeur/2.54) ;
       } ; # fin si
     
       # si on arrive ici, c'est une erreur
     
        return (-1) ;
     
     } ; # fin de fonction convCmPouces
     
     ?>
     

Pour tester ce code, la liste des tests s'allonge donc car il faut prévoir et tester au moins 8 cas :

  1. un cas sans aucun paramètre ;

  2. un cas avec tous les paramètres corrects en nom et en valeur avec l'unité pouce ;

  3. un cas avec tous les paramètres corrects en nom et en valeur avec l'unité centimètre ;

  4. un cas avec le paramètre valeur absent ;

  5. un cas avec le paramètre unite absent ;

  6. un cas avec la valeur du paramètre valeur mal typée ;

  7. un cas avec la valeur du paramètre unite mal typée ;

  8. un cas avec des valeurs des paramètres utilisant beaucoup de décimales.

Un fichier qui réalise ces tests ressemblera donc au fichier testConv2.php :


     <?php # fichier testConv2.php
     
     # tests de la fonction nommée convCmPouces() définie dans le fichier conv2.php
     # ce fichier est à exécuter en ligne de commandes
     
     error_reporting(E_ALL | E_NOTICE ) ;
     
     include("conv2.php") ;
     
     $numTest = 0 ;
     
     # 1. cas sans aucun paramètre
     
     $numTest++ ; echo "Test $numTest, retour : " ;
     echo convCmPouces()."\n\n" ;
     
     # 2. cas avec tous les paramètres corrects en nom et en valeur avec l'unité pouce ;
     
     $numTest++ ; echo "Test $numTest, retour : " ;
     echo convCmPouces(10,"pouces")."\n\n" ;
     
     # 3. cas avec tous les paramètres corrects en nom et en valeur avec l'unité centimètre ;
     
     $numTest++ ; echo "Test $numTest, retour : " ;
     echo convCmPouces(10,"cm")."\n\n" ;
     
     # 4. cas avec le paramètre valeur absent ;
     
     $numTest++ ; echo "Test $numTest, retour : " ;
     echo convCmPouces("cm")."\n\n" ;
     
     # 5. cas avec le paramètre unite absent ;
     
     $numTest++ ; echo "Test $numTest, retour : " ;
     echo convCmPouces(10)."\n\n" ;
     
     # 6. cas avec la valeur du paramètre valeur mal typée ;
     
     $numTest++ ; echo "Test $numTest, retour : " ;
     echo convCmPouces("dix","pouces")."\n\n" ;
     
     # 7. cas avec la valeur du paramètre unite mal typée ;
     
     $numTest++ ; echo "Test $numTest, retour : " ;
     echo convCmPouces(10,2.54)."\n\n" ;
     
     # 8. cas avec des valeurs des paramètres utilisant beaucoup de décimales.
     
     echo convCmPouces(1.23456789,"pouces")."\n\n" ;
     
     ?>
     

Le résultat de ces tests est alors :


     Test 1, retour : -1
     
     Test 2, retour : 25.4
     
     Test 3, retour : 3.9370078740157
     
     Test 4, retour : -1
     
     Test 5, retour : -1
     
     Test 6, retour : 0
     
     Test 7, retour : -1
     
     3.1358024406
     
     

Désormais la fonction convCmPouces(valeur,unite) est fiable... quoique... si on utilise un troisième paramètre, par exemple un paramètre de langue pour afficher en français ou en anglais ?


     $gh> php -a
     
     Interactive mode enabled
     
     php > include("conv2.php") ;
     
     php > echo  convCmPouces(10,"cm","FR")."\n" ;
     3.9370078740157
     
     php > exit
     

Nous n'irons pas plus loin pour cet exemple, mais il serait sans doute "évolué" de ne pas renvoyer -1 comme retour incorrect dans tous les cas de figure, mais plutôt -1 pour l'absence de paramètre, -2 pour une erreur sur le paramètre unite, -3 pour une erreur sur le paramètre valeur... De même, le paramètre de langue pour afficher en français ou en anglais serait un plus, comme sans doute un quatrième paramètre donnant le nombre de décimales à utiliser au niveau du retour. Nous laissons au lecteur le soin d'implémenter et de tester tout cela, par exemple avec PHPUnit, décrit aussi ici et que nous utiliserons en T.P.

2.2 Formulaire et tests

Lorsque la fonction de conversion est considérée comme terminée, il est possible de la compléter en ligne de commandes, avec un programme PHP qui récupère les paramètres en ligne de commande via $argc et qui les lui transmet, soit sous forme d'un alias ou d'un script BASH accessible via la variable d'environnement PATH, pour éviter d'avoir à taper la commande php et le chemin d'accès au fichier. Nous laissons là encore au lecteur le soin de réaliser cet alias ou ce script, de mettre l'alias dans le fichier .bashrc ou .bash_profile car nous allons nous intéresser à la page Web associée à la fonction.

La réalisation classique d'une page Web avec un formulaire correspond sans doute à du code XHTML 1.0 Strict standard, comme pour la page conv_f1.html


     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
     
     <!-- fichier conv_f1.html -->
     
     <html xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr">
     
     <head>
       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
       <link rel="stylesheet" type="text/css" href="std.css"  title="gh" />
       <title> formulaire de conversion pouces/centimètres</title>
     </head>
     
     <body class="beige_jpg">
     
     <blockquote>
     
        <p>&nbsp;</p>
        <p class='align_right'>
           <a href="http://validator.w3.org/check?uri=referer"><img src="valid.png" height="31" width="88"  alt="Valid XHTML" /></a>
           &nbsp;&nbsp;&nbsp;
           <a href='http://jigsaw.w3.org/css-validator/validator?uri=http%3A%2F%2Fforge.info.univ-angers.fr%2F%7Egh%2Fstd.css'><img src="css.gif" height="31" width="88"  alt="Valid CSS2" /></a>
        </p>
     
        <table cellpadding='50' class='bgcolor_white' width='100%'  summary='cadre général'><tr><td class='bgcolor_white'>
     
        <h1>Saisies pour la conversion pouces/centimètres</h1>
     
        <form action='conv_res3.php' method='get' >
     
        <p>
            Quelle valeur faut-il convertir&nbsp;?&nbsp;&nbsp;&nbsp;<input type='text' id='valeur' name='valeur' value='10' size='10'  />
        </p>
     
     
        <p>
            Choisissez l'unité&nbsp;&nbsp;&nbsp;
            <select id='unite' name='unite' >
              <option value='pouces' selected='selected'> pouces </option>
              <option value='cm'> cm </option>
            </select>
        </p>
     
     
        <p>
            Cliquez ensuite sur le bouton
            <input type='submit'  value='envoyer' class='bouton_fin nou orange_pastel' />
            pour obtenir le résultat.
        </p>
     
        </form>
        </td></tr></table>
     
        <p>&nbsp;</p>
        <p>&nbsp;</p>
        <p><a href="http://www.info.univ-angers.fr/~gh/"><img src="return.gif" alt="retour gH" /></a>&nbsp;&nbsp;&nbsp;Retour &agrave; la page principale de &nbsp;<span class='coulGH'>(gH)</span></p>
        <p>&nbsp;</p>
     
     </blockquote>
     
     </body>
     </html>
     
     

mais il est certainement plus "propre" de passer par des fonctions de haut niveau en PHP comme avec notre collection de fonctions pour le PHP conceptuel, soit la page conv_f2.php :


     <?php #-- fichier conv_f2.php
     
     # formulaire pour une conversion pouces/centimètres
     
     include("std7.php") ; # bibliothèque de fonctions pour le "PHP conceptuel"
     debutPage("formulaire de conversion pouces/centimètres","strict") ;
     debutSection() ;
     
     h1("Saisies pour la conversion pouces/centimètres") ;
     
     form("conv_res4.php") ;
     
      p() ;
        echo "Quelle valeur faut-il convertir&nbsp;?" ;
        nbsp(3) ;
        echo input_text("valeur",10 );
      finp() ;
     
      p() ;
        echo "Choisissez l'unité" ;
        nbsp(3) ;
        listeSelectFromTxt("unite","pouces cm") ;
      finp() ;
     
      p() ;
        echo "Cliquez ensuite sur le bouton " ;
        echo input_submit("envoyer","","bouton_fin nou orange_pastel") ;
        echo " pour obtenir le résultat." ;
      finp() ;
     finform() ;
     
     
     finSection() ;
     finPage() ;
     ?>
     

La page de résultats, séparée ici de la page du formulaire, ne doit pas se contenter d'appeler la fonction de conversion sans vérififcation, comme avec le code de la page conv_res3.php


     <?php # fichier conv_res3.php
     
     # fichier minimal de résultat pour la conversion pouces/centimètres
     
     include("std7.php")  ; # bibliothèque de fonctions pour le "PHP conceptuel"
     include("conv2.php") ; # fichier qui contient la fonction de conversion convCmPouces()
     
     debutPage("formulaire de conversion pouces/centimètres","strict") ;
     debutSection() ;
     
     h1("Résultat de la conversion pouces/centimètres") ;
     
     p() ;
      nbsp(5) ;
      $valeur = $_GET["valeur"] ;
      $unite  = $_GET["unite"] ;
      $autreU = "pouces" ;
      if ($unite=="pouces") { $autreU = "cm" ; } ;
      $resConv = convCmPouces($valeur,$unite) ;
      echo "à $valeur $unite correspondent $resConv $autreU." ;
     finp() ;
     
     finSection() ;
     finPage() ;
     
     ?>
     

(car le résultat est incorrect si la zone d'entrée est vide, ou caractère, ou, plus grave, s'il contient 3,2) mais elle doit aussi être explicite au niveau des erreurs comme ci-dessous, avec le fichier conv_res4.php utilisé par le deuxième formulaire :


     <?php # fichier conv_res4.php
     
     # fichier de résultat pour la conversion pouces/centimètres
     
     include("std7.php")  ; # bibliothèque de fonctions pour le "PHP conceptuel"
     include("conv2.php") ; # fichier qui contient la fonction de conversion convCmPouces()
     
     debutPage("formulaire de conversion pouces/centimètres","strict") ;
     debutSection() ;
     
     # si le champ valeur n'est pas transmis, c'est une erreur
     
     if (!isset($_GET["valeur"])) {
       h1("Vous n'avez pas fourni de valeur à convertir. Stop.") ;
       finSection() ; finPage() ; exit(-1) ;
     } ; # fin si
     
     # si l'unité n'est pas indiquée, c'est une erreur
     
     if (!isset($_GET["unite"])) {
       h1("Vous n'avez pas indiqué de quelle unité il s'agit. Stop.") ;
       finSection() ; finPage() ; exit(-1) ;
     } ; # fin si
     
     # si le champ valeur est transmis mais qu'il n'est pas rempli, c'est une erreur
     
     $valeur = $_GET["valeur"] ;
     
     if ($valeur=="") {
       h1("Vous n'avez pas rempli le champ valeur. Stop.") ;
       finSection() ; finPage() ; exit(-1) ;
     } ; # fin si
     
     # si l'unité est transmise mais qu'elle est vide, c'est une erreur
     
     $unite  = $_GET["unite"] ;
     
     if ($valeur=="") {
       h1("Vous n'avez pas donné de valeur au champ unite. Stop.") ;
       finSection() ; finPage() ; exit(-1) ;
     } ; # fin si
     
     # on convertit silencieusement la virgule en point
     
     $valeur = strtr($valeur,",",".") ;
     
     # si la valeur ne correspond pas à un nombre, c'est une erreur
     
     if (!is_numeric(trim($valeur))) {
     # if (!preg_match("/^[0.9]+\\.?[0.9]*/",trim($valeur))) {
       h1("Vous n'avez pas fourni un nombre à convertir. Stop.") ;
       finSection() ; finPage() ; exit(-1) ;
     } ; # fin si
     
     # si l'unité n'est pas pouces ou cm, c'est une erreur
     
     if (!(($unite=="pouces") or ($unite=="cm"))) {
       h1("Unité invalide, utilisez \"cm\" ou \"pouces\". Stop.") ;
       finSection() ; finPage() ; exit(-1) ;
     } ; # fin si
     
     ## arrivé, en principe, tout va bien et on peut convertir
     
     
     h1("Résultat de la conversion pouces/centimètres") ;
     
     p() ;
      nbsp(5) ;
      $autreU = "pouces" ;
      if ($unite=="pouces") { $autreU = "cm" ; } ;
      $resConv = convCmPouces($valeur,$unite) ;
      echo "à $valeur $unite correspondent $resConv $autreU." ;
     finp() ;
     
     finSection() ;
     finPage() ;
     
     ?>
     

On pourrait se demander pourquoi la page Web doit tester les réponses alors que la fonction de conversion l'avait déjà fait. Il y a au moins deux réponses à cela :

  • Une page Web doit dire clairement ce qui va et ce qui ne va pas. Fournir une valeur de -1 pour une valeur incorrecte n'est pas acceptable pour un utilisateur de la page.

  • La page Web peut aussi être utilisée en mode GET directement, sans passer par le formulaire, comme par exemple avec ce lien. Il est clair que dans ce cas la page renvoyée doit être elle-aussi correcte, propre et explicite.

2.3 Fusionner le formulaire et l'action via AJAX

Il est clair que le nombre de tests et les messages d'erreur sont proportionnels à l'arité des fonctions. C'est pourquoi plutôt que des développer des tests à la main pour chaque exemple, il vaut mieux passer par des bibliothèques de tests. Dans le cas de PHP, HTML et Javascript, il est de plus certainement plus correct de tout gérer sur une seule page. Ce qui oblige à passer par la technologie AJAX.

Pour fusionner la page du formulaire et du résultats, nous allons commencer par rajouter un paramètre standalone à la page de résultats afin de ne produire que le corps du résultat si ce paramètre vaut 0, ou s'il ne vaut pas 1, ce qui est un peu la même chose...


     <?php # fichier conv_res5.php
     
     # fichier de r&eacute;sultat pour la conversion pouces/centim&egrave;tres
     # pr&eacute;vu pour AJAX, on renvoie toute la page si le param&egrave;tre standalone
     # n'est pas d&eacute;fini ou s'il vaut explicitement 0
     
     include("std7.php")  ; # biblioth&egrave;que de fonctions pour le "PHP conceptuel"
     include("conv2.php") ; # fichier qui contient la fonction de conversion convCmPouces()
     
     $standalone = 1 ;
     
     # si le champ standalone n'est pas transmis, ce n'est pas un probl&egrave;me
     # s'il est transmis, toute valeur autre que 0 signfie 1
     
     if (isset($_GET["standalone"])) {
        $standalone = $_GET["standalone"] ;
        if ($standalone!="0") {  $standalone = 1 ; } ;
     } ; # fin si
     
     # en mode standalone, on affiche le d&eacute;but de page avec html/head/body
     
     if ($standalone==1) {
       debutPage("formulaire de conversion pouces/centim&egrave;tres","strict") ;
       debutSection() ;
     } ;  # fin si
     
     # si le champ valeur n'est pas transmis, c'est une erreur
     
     if (!isset($_GET["valeur"])) {
       h1("Vous n'avez pas fourni de valeur &agrave; convertir. Stop.") ;
       finSection() ; finPage() ; exit(-1) ;
     } ; # fin si
     
     # si l'unit&eacute; n'est pas indiqu&eacute;e, c'est une erreur
     
     if (!isset($_GET["unite"])) {
       h1("Vous n'avez pas indiqu&eacute; de quelle unit&eacute; il s'agit. Stop.") ;
       finSection() ; finPage() ; exit(-1) ;
     } ; # fin si
     
     # si le champ valeur est transmis mais qu'il n'est pas rempli, c'est une erreur
     
     $valeur = $_GET["valeur"] ;
     
     if ($valeur=="") {
       h1("Vous n'avez pas rempli le champ valeur. Stop.") ;
       finSection() ; finPage() ; exit(-1) ;
     } ; # fin si
     
     # si l'unit&eacute; est transmise mais qu'elle est vide, c'est une erreur
     
     $unite  = $_GET["unite"] ;
     
     if ($valeur=="") {
       h1("Vous n'avez pas donn&eacute; de valeur au champ unite. Stop.") ;
       finSection() ; finPage() ; exit(-1) ;
     } ; # fin si
     
     # on convertit silencieusement la virgule en point
     
     $valeur = strtr($valeur,",",".") ;
     
     # si la valeur ne correspond pas &agrave; un nombre, c'est une erreur
     
     if (!is_numeric(trim($valeur))) {
     # if (!preg_match("/^[0.9]+\\.?[0.9]*/",trim($valeur))) {
       h1("Vous n'avez pas fourni un nombre &agrave; convertir. Stop.") ;
       finSection() ; finPage() ; exit(-1) ;
     } ; # fin si
     
     # si l'unit&eacute; n'est pas pouces ou cm, c'est une erreur
     
     if (!(($unite=="pouces") or ($unite=="cm"))) {
       h1("Unit&eacute; invalide, utilisez \"cm\" ou \"pouces\". Stop.") ;
       finSection() ; finPage() ; exit(-1) ;
     } ; # fin si
     
     ## arriv&eacute;, en principe, tout va bien et on peut convertir
     
     
     h2("R&eacute;sultat de la conversion pouces/centim&egrave;tres") ;
     
     p() ;
      nbsp(5) ;
      $autreU = "pouces" ;
      if ($unite=="pouces") { $autreU = "cm" ; } ;
      $resConv = convCmPouces($valeur,$unite) ;
      echo "&agrave; $valeur $unite correspondent $resConv $autreU." ;
     finp() ;
     
     # en mode standalone, on affiche la fin de page
     
     if ($standalone==1) {
       finSection() ;
       finPage() ;
     } ;  # fin si
     
     ?>
     

Il est possible de tester la page compléte en mode standalone=1 ici et la version "juste le résultat" . On remarquera que l'absence du paramètre standalone renvoie la page compléte afin de rester compatible avec les autres formulaires.

Ensuite, on inclut une zone de réponse dans la page Web, masquée par défaut, qu'on révèle lorsque l'utilisateur demande la conversion, comme avec la page suivante nommée conv_f6.php :


     <?php #-- fichier conv_f6.php
     
     # formulaire pour une conversion pouces/centimètres en mode AJAX
     
     include("std7.php") ; # bibliothèque de fonctions pour le "PHP conceptuel"
     debutPage("formulaire de conversion pouces/centimètres","strict","","conv_f7.js") ;
     debutSection() ;
     
     h1("Saisies pour la conversion pouces/centimètres") ;
     
     form("conv_res4.php","get","onsubmit='conversion() ; return false'" ) ;
     
      p() ;
        echo "Quelle valeur faut-il convertir&nbsp;?" ;
        nbsp(3) ;
        echo input_text("valeur",10 );
      finp() ;
     
      p() ;
        echo "Choisissez l'unité" ;
        nbsp(3) ;
        listeSelectFromTxt("unite","pouces cm") ;
      finp() ;
     
      p() ;
        echo "Cliquez ensuite sur le bouton " ;
        echo input_submit("envoyer","","bouton_fin nou orange_pastel") ;
        echo " pour obtenir le résultat." ;
      finp() ;
     finform() ;
     
     # pour AJAX, la zone de résultats, masquée :
     
     sdl() ;
     
     div("cadre invisible","resultats") ;
       pvide() ;
     findiv() ;
     
     finSection() ;
     finPage() ;
     ?>
     

Le code Javascript associé, est disponible dans le fichier conv_f7.js :


     // * ######################################################### */
     
     function conversion() {
     
     // * ######################################################### */
     
     
         var laValeur = "valeur="+document.getElementById("valeur").value
         var sonUnite = "unite="+document.getElementById("unite").value
         var url      = "conv_res5.php"
     
         // pour debug :
     
         // alert(laValeur+" & "+sonUnite)
     
         var xhr;
         try {  xhr = new ActiveXObject('Msxml2.XMLHTTP');   }
     
         catch (e) {
     
                try {   xhr = new ActiveXObject('Microsoft.XMLHTTP');    }
     
                catch (e2) {
     
                  try {  xhr = new XMLHttpRequest();     }
     
                  catch (e3) {  xhr = false;   }
     
                }
     
         } // fin du catch
     
         xhr.onreadystatechange  = function()  {
     
            if (xhr.readyState  == 4) {
     
               if (xhr.status  == 200) {
     
                   // on transmet tout le fichier
     
                   document.getElementById("resultats").innerHTML =   "<blockquote>" + xhr.responseText + "</blockquote>" ;
     
               } else {
     
                   document.getElementById("resultats").innerHTML=  "<h1>Error code " + xhr.status + "</h1>" ;
     
               } ; // fin de xhr.status  == 200
     
            } ; // fin de xhr.readyState  == 4
     
            // on affiche la zone de résultats
     
            document.getElementById("resultats").setAttribute("class","cadre visible") ;
     
         } ; // fin de fonction xhr.onreadystatechange
     
     
         xhr.open("GET", url+"?standalone=0&"+laValeur+"&"+sonUnite,  true);
         xhr.send(null);
     
     } // * fin de fonction conversion */
     
     // * ######################################################### */
     

Là encore, pour généraliser ce genre de pratique, il vaut mieux passer par une bibliothèque de fonctions Javascript, comme par exemple JQuery ou Prototype.

Il doit être clair à tout un chacun que les tests proposés ici sont élémentaires, rudimentaires et très «artisanaux». Si on écrit notamment des classes d'objets, il faut certainement un outil logiciel capable d'automatiser des tests. Pour PHP, un bon choix semble être phpUnit dont la documentation existe aussi en français, à l'adresse fr/phpUnit, avec un tutorial disponible sur openclassrooms. Pour Python/Django, la documentation pour les tests, en français, est ici. Ruby/Rails n'est pas en reste, bien sûr. Voir par exemple rails-testing.

Si vous n'avez aucune connaissance sur les tests logiciels (tests unitaires, tests d'intégration...) le mieux est de commencer par les pages Wiki, en français et en anglais. Vous pouvez ensuite lire le PDF suivant de F. LEDOUX (copie locale) ainsi que les liens pratiques du test et recettes du test sans oublier selenium pour les tests en développement Web page Wiki FR et plus généralement les méthodes TDD et Agile.

Voici par exemple, issu de nos pages LTE comment tester en ligne de commandes avec Selenium que si on entre un mot de passe et une confirmation différentes, le navigateur affiche bien qu'il y a une erreur :


     # s'execute par : python3 testePageValide.py
     
     from selenium import webdriver
     from selenium.webdriver.common.keys import Keys
     import time
     import re
     
     page = "http://forge.info.univ-angers.fr/~gh/internet/Lte/login.php"
     browser = webdriver.Firefox()
     
     try :
        browser.get(page)
        browser.find_element_by_id("usernameSI").clear();
        browser.find_element_by_id("passwordSI").clear();
        browser.find_element_by_id("confirm_passwordSI").clear();
        browser.find_element_by_id("usernameSI").clear();
        browser.find_element_by_id("usernameSI").send_keys("a");
        browser.find_element_by_id("passwordSI").send_keys("b");
        browser.find_element_by_id("confirm_passwordSI").send_keys("c");
        browser.find_element_by_name("SI").submit()
        time.sleep(2)
        jsCode  = ' errorZoneSI = window.document.getElementById("errorZoneSI") ; '
        jsCode += ' res1 = /Invalid name/.test(errorZoneSI.value) ; '
        jsCode += ' res2 = /Invalid password/.test(errorZoneSI.value) ; '
        jsCode += ' res3 = /Confirm password does not match password/.test(errorZoneSI.value) ; '
        jsCode += ' return( res1 && res2 && res3 ) ; '
        res = browser.execute_script(jsCode)
        if (res) :
           print(" tests Champs SI invalides OK ")
        else :
           print(" NON pour tests Champs SI invalides (2)")
        # fin de si
     except :
        print(" page NON pour tests Champs SI invalides (1)")
     
     browser.quit()
     

2. Principes pour une documentation efficace

Il ya une différence entre documenter une application et documenter un langage. Documenter un langage (ou une nouvelle version de langage) est sans doute plus simple, car c'est «juste» fournir des références, des exemples, des tutoriels, comme par exemple les manuels des compilateurs version 7.2.0 du GNU. Une nouvelle version de langage, disons Python 3.6 apporte bien sûr son lot de nouveautés mais le langage est en gros le même, avec ses rubriques usuelles, comme le manuel de référence du langage et les pages dédiées aux bibliothèques standards, telles celles liées à XML.

          non su

Lorsqu'une application est complexe, un manuel ne suffit pas à tout expliciter. Ainsi la version 9.4 de SAS comporte de nombreux "applicatifs" ou "produits" présentés et détaillés dans une vingtaine de manuels mais aussi accessibles via un long index. Si le site principal de la documentation est complet, il est aussi "monstrueux". On pourra s'en convaincre en cherchant la documentation sur les descripteurs d'un SAS Data Set puisqu'il faut successivement cliquer sur

  1. Learning SAS Programming ;

  2. SAS Language Reference: Concepts ;

  3. SAS File Concepts ;

  4. SAS Dat Sets ;

  5. Descriptor Information for a SAS Data Set.

          non su

Une documentation n'est pas forcément lisible par n'importe qui. Ainsi, dans la partie de la documentation de SAS version 8 dédiée aux procédures de base et statistiques, pour la procédure univariate, section STATEMENT, la valeur de α est liée aux limites de l'intervalle de confiance de la distribution normale et le lien correspondant renvoie à la page zte-comp qui n'est pas un parangon de lisibilité. C'est pourquoi en plus du guide référence, SAS fournit des guides utilisateurs comme son fameux SAS/STAT User's Guide pour la version 8. On pourra essayer de dénombrer les guides de la version 9.1.3 via la page index_913 afin de comprendre pourquoi certaines applications ne se laissent pas aisément maitriser.

Pour une application comme un «framework» de développement, le point d'entrée se doit certainement d'être un tutoriel, comme par exemple les fameux railstutorial et django tutorial. Si le tutoriel est bien écrit, il doit comporter du code prêt à l'emploi, des copies d'écran du résultat à obtenir, ou des exécutions en ligne de commandes, comme ici. Mais ce n'est pas suffisant : on doit aussi trouver des guides de référence comme ici et des rubriques spécialisées, comme la page action_controller_overview (compréhensible dès lors qu'on connait le motif d'architecture logicielle nommé MVC).

Si une application requiert une installation particulière, la documentation associée ne doit pas se contenter d'être sybilline comme pour postgresql 9.3, elle doit fournir des copies d'écran comme pour oracle sun ultra 27.

          non su          non su

On peut d'une certaine façon considérer les services du NCBI comme une application. La documentation en est très riche, car il y a :

Pour conclure, on peut certainement affirmer qu'une documentation bien faite et efficace se doit de tout comporter, du coté de l'utilisateur comme du coté du développeur. Ce qui inclut au moins les divers éléments déjà indiqués, à savoir :

Coté Utilisateur Coté Développeur
  • un manuel d'installation,

  • des rubriques d'aide en interne,

  • des rubriques d'aide en externe,

  • un tutoriel, des vidéos,

  • un manuel d'utilisation,

  • un index alphabétique des fonctionnalités,

  • une Foire Aux Questions...

  • un manuel du programmeur (PDF/HTML...),

  • une encyclopédie alphabétique des classes des objets,

  • un manuel de référence de l'architecture de l'application,

  • un log des bugs recensés et corrigés,

  • un log des versions et des mises à jour,

  • un manuel des tests associés à l'application,

  • un système de gestion des versions "à la git" ou "à la SVN"...

 

3. Notion de qualité logicielle

Pour conclure, nous vous conseillons de lire les pages WIKI liées à ce que les anglais nomment «Software Quality for Software Architecture» communément traduit par qualité logicielle des architectures logicielles. A défaut de tout saisir, cela vous permettra d'enrichir votre vocabulaire de mots de plus de trois syllabes, dont :

 

          non su


     Termes techniques longs du vocabulaire issu de la qualité logicielle
     ---------------------------------------------------------------------
     
           autonomie de contrôle
           compatibilité ascendante
           compatibilité descendante
           composabilité informationnelle
           conformité des fonctionnalités
           convivialité
           degré de cohérence
           dématérialisation
           efficacité
           extensibilité
           fiabilité
           interopérabilité extrinsèque
           interopérabilité intrinsèque
           intégrité globale
           intégrité référentielle
           maintenabilité
           portabilité
           réutilisabilité
           simplicité de vérification
           transparence
           validité fonctionnelle
           vérifiabilité
     

       retour au plan de cours  

 

Code-source PHP de cette page.

 

retour gH    Retour à la page principale de   (gH)