Skip to topic | Skip to bottom
Home
Linfo
Linfo.ProjetDev2012TestsUnitairer1.3 - 25 Nov 2013 - 09:40 - PhilippeReneviertopic end

Start of topic | Skip to actions

Projet de développement - SimpleTest - les tests unitaires en Php

Eclipse

L'éclipse version php est accessible via le path : /usr/local/eclipse/eclipse-php-3.0.2/eclipse
Placez votre workspace dans votre dossier ~/www (directement ou dans un sous-dossier).
Ne pas utiliser le plugin git d'eclipse (c'est comme croiser les effluves, c'est mal).

Ainsi vos projets seront accessible via une url du type :
http://www-mips.unice.fr/~<"login">/<"workspace">/<"nom de projet">/<"chemin vers le fichier php">

La version de php sur www-mips est : PHP Version 5.2.6-1
Parmi les bibliothèques disponibles il y a : CURL (pour les url), GD (pour la manip d'image), json, xml, etc.

Pour une base mysql : demander à Philippe Renevier Gonin.
Le serveur est euterpe.unice.fr (/phpmyadmin pour l'interface web).

SimpleTest

La page officielle de SimpleTest est http://www.simpletest.org/ . \De là vous pouvez télécharger ce framework de test unitaire en php, qui vous permettra de faire du test unitaire de fonctions / méthodes / classes, mais aussi pour faire des tests de navigation (simulation d'un navigateur)

il y a une page pour débuter : http://www.simpletest.org/en/start-testing.html

Dans les sous pages de http://simpletest.org/en/overview.html , on retrouve l'api (insérée dans la doc), c'est à dire toutes les fonctions utilisables pour tester le code.

Dans les sous pages de http://simpletest.org/en/first_test_tutorial.html , on retrouve des exemples (mais pas tout l'api)

Exemple d'utilisation

l'exemple : un site sur le cinéma

Un exemple de tests et leur code php (via les .txt) sont accessibles dans ce dossier test.

Le site en lui même est visible sur le serveur www-mips.unice.fr.

Il demande une connexion par mot de passe : vous pouvez utiliser Lewis / Raymond / mdp comme login.

configuration

Tous les fichiers tests (reconnaissables par leur extension .test.php) commencent par inclure le fichier ParamTest.inc : require_once('ParamTest.inc');

Celui-ci permet d'ajouter SimpleTest à l'include_path de Php : Php saura rertouver les fichiers de SimpleTest pour exécuter les tests. Ce qui suit est à faire si vous ne pouvez pas modifier le fichier de configuration php.ini (variable include_path à compléter) : set_include_path(get_include_path() . PATH_SEPARATOR . "../../simpletest");

Dans cette exemple, le dossier simpletest (qui comprend tous les fichiers nécessaires à l'exécution des tests) se situe dans le dossier parent du dossier parent de l'endroit où sont les fichiers de tests.

Finalement le ficher ParamTest.inc contient une classe ParamTest qui ne contient qu'un champ static (utilisable ainsi ParamTest::$host) pour définir l'adresse du site ainsi testé. Cela permettra de faire vos tests de navigation sur n'importe quel serveur (localhost, www-mips.unice.fr, etc.)

1er exemple de test unitaire

testUnit.test.php : ce test unitiare permet de vérifier qu'une "énumération" ne contient que ce qu'elle doit contenir (ATTENTE, DEMANDE, ACCEPTE). Cette énumération ne doit contenir que 3 valeurs données. Il est donc vérifier que ces 3 valeurs sont dedans, qu'il n'y a que 3 valeurs, et aussi qu'une autre valeur (ACK) n'est pas dedans.

2ième exemple de test unitaire

testUnit.Data_People.test.php : ce test unitaire permet de vérifier que la modification de la date de mort d'une personne se fait correctement.

Ce test ne passe pas.

Seule une année sur 4 chiffres est voulue. Le test comprend deux fois les mêmes tests ("toto", 1985, 45), mais le fait de deux façons. La première est "manuelle" et par copier/coller. La seconde est un peu plus automatique, il faut remplir deux tableaux : $values pour les valeurs initiales, $expected pour les valeurs attendues après le setMort. La deuxième version est plus complète en terme de valeurs testées.

Voici le code de la méthode, elle ne respecte pas les spécifications (années sur 4 chiffres), mais pire, si on passe en paramètre n'importe quoi, la valeur affectée sera 0 (résultat de la conversion d'une chaine de caractère qui n'est pas un nombre en int) :

   public function setMort( $mort) {
      if (is_int($mort)) $this->mort = (int) $mort;
      else {
            $cast = (int) $mort;
            if ($cast >= -1) $this->mort = $cast;
            
            
         }
   }

exemple de test de navigation

navigationFilm.test.php : ce test de navigation vérifie qu'on ne peut pas accéder à une page sans être connecté et que si on se connecte dans la foulé, on sera redirigé vers la page initialement voulue.

Le test définie dans la méthode testRedirectionConnexion le fait pour une page. Le test définie dans la méthode testRedirectionConnexionDeconnexion le fait pour toutes les pages du tableau $values et en plus test la déconnexion.

lancer tous les tests

global.test.php : cette collection de test permet d'inclure tous les fichiers .test.php (à l'exception de lui-même) et donc de lancer tous les tests en une seule fois.

Notez que pour accéder aux fichiers, le test TestAll utilise la variable global $dir afin d'assurer le positionnement de la lecture du fichier au bon niveau de la hiérarchie des fichiers.

La méthode getSize permet juste d'obtenir le bon nombre de fichier test passé (en ne se comptant pas soi-même).

Exemples Spécifiques dans les formulaires : Patch pour prise en compte de type d'input HTML5, Radio Button et Upload

Les tests illustratifs sont test_checkbox_radio.php et test_UploadManager.php disponibles (en ligne et en version txt) à http://deptinfo.unice.fr/~renevier/exemplesPhp/ExempleSimpletest/

prise en compte de nouveaux types d'input

Pour prendre en compte des types d'input autre que 'submit', 'image', 'checkbox', 'radio', 'text', 'hidden', 'password' ou 'file', il faut aller modifier la méthode protected function createInputTag($attributes) de la classe SimpleTagBuilder dans le fichier tag.php de SimpleTest. Voici ce que cela peut donner en ajouter les input de type "date" et "email", qui seront alors testable comme des inputs de type "text" :

 function createTag($name, $attributes) {
        static $map = array(
                'a' => 'SimpleAnchorTag',
                'title' => 'SimpleTitleTag',
                'base' => 'SimpleBaseTag',
                'button' => 'SimpleButtonTag',
                'textarea' => 'SimpleTextAreaTag',
                'option' => 'SimpleOptionTag',
                'label' => 'SimpleLabelTag',
                'form' => 'SimpleFormTag',
                'frame' => 'SimpleFrameTag');
        $attributes = $this->keysToLowerCase($attributes);
        if (array_key_exists($name, $map)) {
            $tag_class = $map[$name];
            return new $tag_class($attributes);
        } elseif ($name == 'select') {
            return $this->createSelectionTag($attributes);
        } elseif ($name == 'input') {
            return $this->createInputTag($attributes);
        }
        return new SimpleTag($name, $attributes);
    }

tests avec les radio buttons (test_checkbox_radio.php)

Pour tester la valeur (initiale ou non), il faut utiliser $this->assertField('nom_de_l_input', val ) avec

  • la valeur de l'attribut "name" commun à tous les inputs de type radio
  • val qui peut être "false" s'il n'y a pas de valeur choisie, sinon array("valeur_choisie"). La valeur testée est bien à mettre dans un tableau...

Pour simuler le clic sur un radio button, il faut utiliser $this->setField('nom_de_l_input', "valeur_choisie");

tests avec les checkboxes (test_checkbox_radio.php)

C'est semblable aux cas des radios buttons, sauf qu'il peut y avoir plusieurs valeurs. Dans ce cas, il passer en second paramètre (assertField ou setField) un tableau contenant plusieurs valeurs. Par exemple : $this->assertField('lecheck', array('valeur1', 'valeur2', 'valeur3'));

tests d'upload (input de type file) (test_UploadManager.php)

Le test ne doit pas porter que sur le transfert du fichier, mais s'il a été bien renommé, qu'il est au bon endroit, etc. Ces tests s'écrivent comme les autres, notamment avec setField pour modifier la valeur. Il y a cependant 4 particularités :

  • Ces tests mettent en jeu à la fois la partie "backend" pour le traitement des fichiers reçus, mais aussi une partie "frontend" pour la réception des fichiers. Cette réception ne peut pas être simulées (les fonction is_uploaded_file et move_uploaded_file ne fonctionnent qu'avec des fichiers téléchargés). Aussi, pour des raisons conceptuelles (la réception est une partie "controleur", le traitement est une partie "modèle / métier"), il est vivement conseiller de bien séparer l'implémentation entre la partie qui reçoit et celle qui traite. Celle qui traite peut être testée avec un UnitTestCase (test de fonctionnalité), celle qui reçoit devra être testée avec un WebTestCase.
  • Il faut alors indiquer le chemin (sur le disque dur "local") du fichier à uploader.
  • Le dossier dans lequel est le script qui exécute le test est donné par dirname($_SERVER['SCRIPT_FILENAME']), ensuite à vous de préciser le chemin vers les fichiers sources.
  • Il faut écrire une page web de test, ce qui permet aussi de tester des valeurs de retour de fonctions appelées (avec assertText par exemple).

Notons aussi que dans cet exemple, UploadManager est implémenté comme un singleton.

Exemple Spécifique : tester le contenu d'une variable de session

Le test illustratif test test_session_php disponible (en ligne et en version txt) à http://deptinfo.unice.fr/~renevier/exemplesPhp/ExempleSimpletest/

Pour pouvoir "tester" le contenu d'une variable de $_SESSION, il faut pouvoir accéder à cette variable. Pour cela, il faut disposer du même identificateur de session (cookie PHPSESSID). Or, dans votre test unitaire, vous allez avoir une session pour le test lui même, et celui-ci va créer des "navigateur" pour simuler les accès aux pages. Ce sont ces "navigateurs" qui auront la session qui serait à tester.

Chaque fonction de test (nommée test...) du webTestCase commence avec un nouveau "navigateur" interne à SimpleTest.

Pour récupérer la même session, il faut avoir le même identifiant :

// on recupère l'id de session du navigateur interne à SimpleTest
session_id($this->getCookie("PHPSESSID"));
// on lance ou relance la session, avec un supreswarning pour le pas avoir le message : "on ne peut plus envoyé le cookie"
@session_start();
// ensuite on peut tester ce qu'il y a dans la variable de session
$this->assertEqual($_SESSION["cpt"], $total);

Tester avec un BD

Pour vos tests, il est préférable d'avoir une BD de test, car :

  • ainsi, vous ne pourrissez pas la base de données en production, i.e., ce que les internautes peuvent voir...
  • ainsi, vous contrôlez intégralement ce que la BD contient.

Comment faire pour changer de BD ? Une solution possible est de donner l'accès à la BD via un Singleton (instance unique) paramétrable, dont les paramètres sont par défaut ceux de la BD de production.

Exemple :

class Connexion {
    // les paramètres de connexion   
    private $host      = "localhost";
    private $user      = "root";
    private $pass      = "";
    private $dbname    = "halloffame";
    

    // l'instance unique
    private static $connexion;
    

    /**
     * @var PDO
     */
    private $bdd;

    /**
     * etc. s'il y d'autres champs de classe
     */

 
    /**
     * pour creer l'unique instance de ce singleton
     * @ignore
     */
    private function Connexion($host, $dbname, $user, $pass)
    {
        try{
           $this->host = $host;
           $this->dbname = $dbname;
           $this->user = $user;
           $this->pass = $pass;
                $this->bdd = new PDO("mysql:host={$this->host};dbname={$this->dbname};charset=UTF-8", $this->user, $this->pass);
        }
        // Catch any errors
        catch(PDOException $e){
           // traiter l'erreur de connexion à la BD
        }
    }
    
    /**
     * Pour obtenir l'instance de connexion à la bd
     * l'encodage pourrait aussi être mis en paramètre..
     * @param host : serveur pour se connecter
     * @param dbname : nom de la base de donnée sur le serveur
     * @param user : nom de l'utilisateur
     * @param pass : et son mot de passe
     */
    public static function getConnexion($host="serveurdeproduction", $dbname = "nomdeproduction", $user="...", $pass="..."){
       if(self::$connexion == null){
          self::$connexion = new Connexion($host, $dbname, $user, $pass);
       }
       return self::$connexion;
    }

   /**
     * pour la suite, à vous de choisir entre renvoyer l'objet pdo ou fournir des méthodes d'accès (proposer des méthodes query, etc.)
     */
    

}

Dans le code du site, l'utilisation sera Connexion::getConnexion() mais dans les tests cela sera : Connexion::getConnexion($host_test, $db_test, $user_test, $pss_test)

Vous pourrez ainsi peupler, vider, modifier la BD de test...
to top


You are here: Linfo > ProjetInfo201213 > ProjetDev2012TestsUnitaire

to top

Copyright © 1999-2018 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding WIKIDeptinfo? Send feedback