101 votes

Comment écrire des tests unitaires en PHP?

J'ai lu partout à quel point ils sont géniaux, mais pour une raison quelconque, je n'arrive pas à comprendre comment je suis supposé tester quelque chose. Est-ce que quelqu'un pourrait peut-être poster un exemple de code et comment il le testerait? Si ça ne vous dérange pas trop :)

37voto

Till Points 14673

Il y a un 3ème "cadre", qui est de loin plus facile à apprendre, même plus facile que de SimpleTest, il est appelé phpt.

Un apprêt peut être trouvé ici: http://qa.php.net/write-test.php

Edit: Viens de voir votre demande de code de l'échantillon.

Supposons que vous avez la fonction suivante dans un fichier appelé lib.php:

<?php
function foo($bar)
{
  return $bar;
}
?>

Vraiment simple et direct, le paramètre que vous transmettez, est renvoyé. Alors, regardons un test pour cette fonction, nous allons appeler le fichier de test foo.phpt:

--TEST--
foo() function - A basic test to see if it works. :)
--FILE--
<?php
include 'lib.php'; // might need to adjust path if not in the same dir
$bar = 'Hello World';
var_dump(foo($bar));
?>
--EXPECT--
string(11) "Hello World"

En un mot, nous fournissons le paramètre $bar valeur "Hello World" et nous var_dump() la réponse de l'appel à la fonction foo().

Pour exécuter ce test, utiliser: pear run-test path/to/foo.phpt

Cela nécessite un travail d'installation de POIRE sur votre système, ce qui est assez commun dans la plupart des circonstances. Si vous avez besoin de l'installer, je vous recommande d'installer la dernière version disponible. Dans le cas où vous avez besoin d'aide pour le configurer, n'hésitez pas à demander (mais de fournir un système d'exploitation, etc.).

32voto

okoman Points 2556

Vous pouvez utiliser deux cadres pour les tests unitaires. Simpletest et PHPUnit , que je préfère. Lisez les tutoriels sur la rédaction et l'exécution de tests sur la page d'accueil de PHPUnit. C'est assez facile et bien décrit.

Ici vous pouvez trouver un bon aperçu pour les tests unitaires avec Simpletest.

22voto

Preston Points 724

Le test unitaire n'est efficace que si vous modifiez votre style de codage pour l'adapter. Je vous recommande de parcourir le blog Google Testing , en particulier Cet article .

13voto

Kris Points 11892

J'ai roulé mon propre parce que je n'ai pas eu le temps d'apprendre à quelqu'un elses façon de faire les choses, cela a pris environ 20 minutes pour rédiger, de 10 à adapter pour les poster ici.

Unittesting est très utile pour moi.

c'est un peu long, mais il explique lui-même et il y a un exemple dans le bas.

/**
 * Provides Assertions
 **/
class Assert
{
    public static function AreEqual( $a, $b )
    {
    	if ( $a != $b )
    	{
    		throw new Exception( 'Subjects are not equal.' );
    	}
    }
}

/**
 * Provides a loggable entity with information on a test and how it executed
 **/
class TestResult
{
    protected $_testableInstance = null;

    protected $_isSuccess = false;
    public function getSuccess()
    {
    	return $this->_isSuccess;
    }

    protected $_output = '';
    public function getOutput()
    {
    	return $_output;
    }
    public function setOutput( $value )
    {
    	$_output = $value;
    }

    protected $_test = null;
    public function getTest()
    {
    	return $this->_test;
    }

    public function getName()
    {
    	return $this->_test->getName();
    }
    public function getComment()
    {
    	return $this->ParseComment( $this->_test->getDocComment() );
    }

    private function ParseComment( $comment )
    {
    	$lines = explode( "\n", $comment );
    	for( $i = 0; $i < count( $lines ); $i ++ )
    	{
    		$lines[$i] = trim( $lines[ $i ] );
    	}
    	return implode( "\n", $lines );
    }

    protected $_exception = null;
    public function getException()
    {
    	return $this->_exception;
    }

    static public function CreateFailure( Testable $object, ReflectionMethod $test, Exception $exception )
    {
    	$result = new self();
    	$result->_isSuccess = false;
    	$result->testableInstance = $object;
    	$result->_test = $test;
    	$result->_exception = $exception;

    	return $result;
    }
    static public function CreateSuccess( Testable $object, ReflectionMethod $test )
    {
    	$result = new self();
    	$result->_isSuccess = true;
    	$result->testableInstance = $object;
    	$result->_test = $test;

    	return $result;
    }
}

/**
 * Provides a base class to derive tests from
 **/
abstract class Testable
{
    protected $test_log = array();

    /**
     * Logs the result of a test. keeps track of results for later inspection, Overridable to log elsewhere.
     **/
    protected function Log( TestResult $result )
    {
    	$this->test_log[] = $result;

    	printf( "Test: %s was a %s %s\n"
    		,$result->getName()
    		,$result->getSuccess() ? 'success' : 'failure'
    		,$result->getSuccess() ? '' : sprintf( "\n%s (lines:%d-%d; file:%s)"
    			,$result->getComment()
    			,$result->getTest()->getStartLine()
    			,$result->getTest()->getEndLine()
    			,$result->getTest()->getFileName()
    			)
    		);

    }
    final public function RunTests()
    {
    	$class = new ReflectionClass( $this );
    	foreach( $class->GetMethods() as $method )
    	{
    		$methodname = $method->getName();
    		if ( strlen( $methodname ) > 4 && substr( $methodname, 0, 4 ) == 'Test' )
    		{
    			ob_start();
    			try
    			{
    				$this->$methodname();
    				$result = TestResult::CreateSuccess( $this, $method );
    			}
    			catch( Exception $ex )
    			{
    				$result = TestResult::CreateFailure( $this, $method, $ex );
    			}
    			$output = ob_get_clean();
    			$result->setOutput( $output );
    			$this->Log( $result );
    		}
    	}
    }
}

/**
 * a simple Test suite with two tests
 **/
class MyTest extends Testable
{
    /**
     * This test is designed to fail
     **/
    public function TestOne()
    {
    	Assert::AreEqual( 1, 2 );
    }

    /**
     * This test is designed to succeed
     **/
    public function TestTwo()
    {
    	Assert::AreEqual( 1, 1 );
    }
}

// this is how to use it.
$test = new MyTest();
$test->RunTests();

Ce sorties:

Test: TestOne a été un échec 
/**
* Ce test est conçu pour échouer
**/ (lignes:149-152; file:/Users/kris/Desktop/Testable.php)
Test: TestTwo a été un succès 

5voto

sofia Points 2499

Pour de simples tests ET de la documentation, php-doctest est très agréable, et c'est vraiment un moyen facile d'obtenir commencé puisque vous n'avez pas à ouvrir un fichier séparé. Imaginez la fonction ci-dessous:

/**
* Sums 2 numbers
* <code>
* //doctest: add
* echo add(5,2);
* //expects:
* 7
* </code>
*/
function add($a,$b){
    return $a + $b;   
}

Maintenant, si vous exécutez ce fichier à travers phpdt (ligne de commande de coureur de php-doctest) 1 test sera exécuté. Le doctest est contenue à l'intérieur de la < code > bloc. Doctest origine en python et est très bien pour donner utile et praticable exemples sur la façon dont le code est censé fonctionner. Vous ne pouvez pas l'utiliser exclusivement parce que le code lui-même serait la litière avec des cas de test, mais j'ai trouvé que c'est utile aux côtés des plus formelles tdd bibliothèque - je utiliser phpunit.

Cette 1ère réponse ici , il résume bien (ce n'est pas l'unité vs doctest ).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X