Infocurci - programmatore Php Roma
Infocurci - programmatore Php Roma
Benvenuti nel sito "faster than 98% of all tested websites" (tools.pingdom.com) senza cookie e senza pubblicitĂ      

Php : Unit test con CodeIgniter

Un pratico esempio per l'esecuzione di Unit Test attraverso CodeIgniter. Il famoso framework, giunto alla versione 3, mette a disposizione una libreria di semplice utilizzo e facilmente estendibile.

Php

Come sempre, CodeIgniter agevola il nostro lavoro attraverso librerie di immediato utilizzo e facilmente estendibili. Creiamo subito una classe da usare esclusivamente a questo scopo. Nella cartella application/controllers inseriamo un file chiamato Test.php con questo contenuto:

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Test extends CI_Controller {

    public function index()
    {
        $this->load->library('unit_test');
       
        $elencoTest = array();
        $elencoTest[] = array('Alfredo',23);
        $elencoTest[] = array(23,'Alfredo');
        $elencoTest[] = array(23,null);
        $elencoTest[] = array(null,'Alfredo');
        $elencoTest[] = array(null,23);
        foreach($elencoTest as $test){
            $testEseguito = $this->prova($test[0],$test[1]);
            $this->unit->run($testEseguito, 'is_string', 'Check string','Variabili: '.$test[0].';'.$test[1]);
            $this->unit->run($testEseguito, 'is_boolean', 'Check boolean','Variabili: '.$test[0].';'.$test[1]);
        }
        echo $this->unit->report();
    }
   
    public function prova($nome,$punti)
    {

        if(!is_string($nome)){
            return false;
        }
        if(!is_int($punti)){
            return false;
        }
        return "Punteggio di $nome: $punti punti.";
    }
}

 

La funzione prova() non fa altro che ricevere due parametri e concatenarli in una stringa. Tuttavia viene eseguito un controllo preventivo delle variabili per evitare di elaborare parametri incoerenti: dobbiamo passare alla funzione una stringa ed un intero.

Qui impariamo una importante lezione sugli Unit Test: per funzionare bene, devono avere a che fare con un frammento che ritorni un valore facilmente definibile. La funzione prova() ritorna un booleano false in caso di parametri errati, una stringa in caso di parametri corretti. E' sbagliato pensare che un Unit Test possa individuare errori in funzioni scritte male... una funzione scritta male ritorna valori inaffidabili e di conseguenza diventa inattendibile anche il test.

La funzione index(), richiamata di default, si occupa cosi di lanciare gli unit test. Apriamo il nostro browser (l'indirizzo sarà nomesito/test) cosi da lanciare la classe Test e la funzione di default e scopriamo cosa accade.

Un vero e proprio log dei nostri test! Ma parte del merito di questo approfondito log va dato anche al modo con cui abbiamo richiamato gli Unit test. All'inizio della funzione index() abbiamo inizializzato un array $elencoTest con una serie di valori da passare man mano alla funzione prova() cosi da eseguire appunto i test.
Abbiamo inserito diversi valori: una stringa ed un intero (ciò che è richiesto dalla funzione); un intero ed una stringa; dei valori null.
Ovviamente l'utilizzo di un array non è essenziale, però ci consente di richiamare gli unit test all'interno di un ciclo ed evitare cosi di scrivere diverso codice superfluo.

Infatti la funzione

$this->unit->run(()

riceve 4 parametri:

  • il valore da testare (nel nostro caso, il valore ritornato dal richiamo della funzione prova())
  • il test da eseguire (is_string, is_boolean ecc... L'elenco completo lo trovate nella documentazione ufficiale)
  • il nome del test (un nome arbitrario che ci servirà per riconoscere il test nel log)
  • le note (come il nome, si tratta di un parametro personalizzato e facoltativo, utile per decifrare meglio i risultati nel log)

Nel mio caso, grazie all'array, ho potuto usare le due variabili di ciascun test sia per richiamare la funzione prova(), sia per inserirle nelle note cosi da aver subito chiaro cosa è che ha prodotto un test corretto o errato.

Gli unit test, oltre a rilevare gli errori dei vari frammenti del nostro codice ed agevolarne gli aggiornamenti, hanno anche un'utilità didattica.

Provate ad esempio a cambiare la funzione prova() inserendo questo snippet

$nome = (string)$nome;
$punti = (int) $punti;

che esegue un casting delle variabili. La funzione diventa cosi:

public function prova($nome,$punti)
    {
        $nome = (string)$nome;
        $punti = (int) $punti;
        if(!is_string($nome)){
            return false;
        }
        if(!is_int($punti)){
            return false;
        }
        return "Punteggio di $nome: $punti punti.";
    }

Prima di eseguire il test, chiedete a voi stessi quale è il risultato atteso... e solo dopo lanciate il test. Il casting di una stringa si comporta esattamente come avevate ipotizzato?

 

Tutorial pubblicato il 05/01/2016