2010-11-24 26 views
18

je le cas de test suivant:problème avec les fournisseurs PHPUnit et données

include_once('../Logger.php'); 

class LoggerTest extends PHPUnit_Framework_TestCase { 

    public function providerLogger() { 
     return new Logger; 
    } 

    /** 
    * @dataProvider providerLogger 
    */ 
    public function testAddStream($logger) { 
     $this->assertTrue(false); 
    } 

} 

Quand je lance dans PHPUnit, je reçois:

PHPUnit 3.4.14 by Sebastian Bergmann. 

.......... 

Time: 0 seconds, Memory: 5.75Mb 

OK (1 tests, 0 assertions) 

test échoue, mais il ne fonctionne pas. J'ai essayé d'avoir:

public function providerLogger() { 
    return array(new Logger); 
} 

Mais je reçois:

The data provider specified for LoggerTest::testAddStream is invalid. 

J'ai essayé déclarant static (comme dit le manuel), mais toujours pas de différence. Je me souviens d'avoir travaillé de la même manière auparavant, mais je peux me tromper. Qu'est-ce que je rate?

Merci d'avance pour votre aide.

PHPUnit 3.4.14 (extrait de PEAR) sur PHP 5.3.3

+0

1 tests, ** 0 ** assertions. Votre test n'a même pas été appelé. Je parie que le problème n'est pas dans le fournisseur de données. – zerkms

+0

En fait, si je supprime la chose @dataProvider, j'obtiens une erreur car testAddStream() nécessite un paramètre. Si je supprime complètement le paramètre, le test échoue comme il se doit. – netcoder

+0

J'ai un problème d'utilisation de PHPUnit dans Zend Studio. Si j'inscris un espace de noms avec Zend_Autoloader, l'utilisation de @dataProvider provoque (tente de) charger le nom du test en tant que classe. Je vais jeter la chance que ces 2 problèmes sont liés. – Duncan

Répondre

27

Mise à jour mineure: Il est possible d'utiliser des méthodes d'instance en tant que fournisseur depuis la version 3.2 (ou quelque part autour). Jetez un oeil sur les commentaires


Le fournisseur doit ressembler à ceci.

public static function providerLogger() { 
    return array(
     array(new Logger) 
    ); 
} 

Tout d'abord: La méthode doit être statique

Les tableaux s sont importants. Ce n'est pas si difficile à comprendre. Le tableau externe a une valeur pour chaque itération à laquelle le test doit être appelé. Ici, le test vient d'être appelé une fois. Les tableaux internes sont les paramètres (dans l'ordre) avec lesquels le test est appelé. Votre test attend exactement un paramètre, de sorte que les tableaux internes ont toujours besoin d'une seule valeur. Un autre petit exemple

public static function addTestProvider() { 
    return array(
     /* First + Second = third? */ 
     array(1,4,5), 
     array(3,3,6), 
     array(5,5,6) 
    ); 
) 
public function testAdd ($a, $b, $result) { 
    $this->assertEquals($result, $a + $b); 
} 

Ici testAdd est exécuté 3 fois, un pour chaque second niveau tableau, et il recevra les valeurs du tableau intérieur s. Vous pouvez remarquer que le test échouera et vous fournira un message dans lequel itération de l'ensemble de données (ici # 3, parce que 5 + 5 n'est pas 6;)) l'assertion a échoué.

+0

C'était comme ça. J'avais essayé 'static', j'avais essayé des tableaux, j'avais aussi essayé des tableaux de tableaux (la solution actuelle), mais j'ai dû faire quelque chose de mal, parce que ça marche maintenant. Merci beaucoup! – netcoder

+14

Ai-je oublié quelque chose? Pourquoi est-ce que ça doit être statique? Le [manuel PHPUnit utilise aussi des méthodes régulières] (http://www.phpunit.de/manual/3.4/fr/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers) – Gordon

+1

Hmm ... Tu as raison. Donc peut-être son ok, si ce n'est pas statique;) Il semble que cela a changé avec 3.3. Au moins l'exemple de 3.2 est différent;) – KingCrunch

-1

Supprimez le paramètre de la fonction publique testAddStream (enregistreur de $) et essayez à nouveau. Je ne crois pas que PHPUnit va invoquer un test qui nécessite des paramètres qu'il est incapable de transmettre.

+0

Si je supprime le paramètre, le test est exécuté et échoue comme il se doit. Le but du bloc @dataProvider est de passer des paramètres à un test, comme démontré [dans le manuel] (http://www.phpunit.de/manual/3.2/fr/writing-tests-for-phpunit.html). – netcoder

+0

Ah, je vois. Votre fonction dataprovider doit être publique et statique. Voir ce texte dans le manuel: "Une méthode de fournisseur de données doit être publique et statique et renvoyer un tableau de tableaux ou un objet qui implémente l'interface Iterator et fournit un tableau pour chaque étape de l'itération Pour chaque tableau faisant partie de la collection la méthode de test sera appelée avec le contenu du tableau comme arguments. " –

+0

@Macy: Malheureusement, j'ai aussi essayé (static, non-static, return array, return object ...) et toujours le même résultat ... – netcoder

5

J'ai eu le même problème, et il a été résolu, quand j'ai supprimé le constructeur vide, qui a été généré automatiquement. Je ne sais pas pourquoi cela résout le problème. Je n'avais pas non plus de méthode de test nommée comme la classe. La méthode du fournisseur n'a pas besoin d'être statique, jusqu'à présent, mon test fonctionne sans statique.Mais aussi courir quand je fais la méthode de fournisseur statique

+1

Merci beaucoup! Supprimer __construct aide vraiment. – barbushin

+7

J'ai également trouvé que vous pouvez utiliser __construct, mais n'oubliez pas d'appeler parent :: _ construct comme ceci: public function __construct ($ name = NULL, tableau $ data = array(), $ dataName = '') { \t // ... \t \t parent :: __ construct ($ nom, $ data, $ nom_de_la_fichier); \t} – barbushin

1
<?php 

require_once 'calculator.php'; 

/** 
* Calculator test case. 
*/ 
class CalculatorTest extends PHPUnit_Framework_TestCase { 

    /** 
    * @var Calculator 
    */ 
    private $Calculator; 

    /** 
    * Prepares the environment before running a test. 
    */ 
    protected function setUp() { 
     parent::setUp(); 
     // TODO Auto-generated CalculatorTest::setUp() 
     $this->Calculator = new Calculator(/* parameters */); 
    } 

    /** 
    * Cleans up the environment after running a test. 
    */ 
    protected function tearDown() { 
     // TODO Auto-generated CalculatorTest::tearDown() 
     $this->Calculator = null; 
     parent::tearDown(); 
    } 

    /** 
    * Constructs the test case. 
    */ 
    public function __construct() { 
     // TODO Auto-generated constructor 
    } 

    /** 
    * Tests Calculator->add() 
    * 
     * @dataProvider provider 
     */ 
    public function testAdd($a, $b, $c) { 
     // TODO Auto-generated CalculatorTest->testAdd() 
     //$this->markTestIncomplete ("add test not implemented"); 

     //$this->Calculator->add(/* parameters */); 
     $this->assertEquals($this->Calculator->add($a, $b), $c); 
    } 

    public static function provider() 
    { 
     return array(
      array(1, 1, 1), 
      array(1, 1, -1), 
      array(4, 2, 2), 
      array(1, 1, 1) 
     ); 
    } 
} 

est l'ensemble complet du Code

0

J'ai aussi constaté que vous ne pouvez pas enchaîner directement les fournisseurs de données:

class ProviderTest extends PHPUnit_Framework_TestCase { 

    public function provider() { 
     return array(array('test')); 
    } 

    /** 
    * @dataProvider provider 
    */ 
    public function providerTest1($test) { 
     $this->assertTrue($test); 
     return array(array($test)); 
    } 

    /** 
    * @dataProvider providerTest1 
    */ 
    public function providerTest2($test) { 
     $this->assertEquals('test', $test); 
    } 

} 

Apparemment, les appels PHPUnit toutes les fonctions du fournisseur avant d'exécuter des tests, de sorte que vous ne pouvez même pas utiliser des fonctions de fournisseur distinctes pour transmettre les résultats des tests à d'autres tests. Le mieux que vous pouvez faire est de simuler:

class ProviderTest extends PHPUnit_Framework_TestCase { 

    private $provider_data = array(); 

    public function provider() { 
     return array(array('test')); 
    } 

    /** 
    * @dataProvider provider 
    */ 
    public function testProvider1($test) { 
     $this->assertFalse(empty($test)); 
     array_push($this->provider_data, array($test)); 
    } 

    /** 
    * @depends testProvider1 
    */ 
    public function testProvider2($test = NULL) { 
     if(is_null($test)) { 
      // simulate a provider 
      foreach($this->provider_data as $row) { 
       call_user_func_array(array($this, __METHOD__), $row); 
      } 
     } else { 
      $this->assertEquals('test', $test); 
     } 
    } 

} 
-1

Voici, j'ai réalisé un modèle pour réaliser des dépendances de test pour les fournisseurs de données! De cette façon, vous pouvez enchaîner les fournisseurs de données.

class ProviderDependencyTest extends PHPUnit_Framework_TestCase 
{ 
    private static $dataSet; 

    public function provideData() 
    { 
     self::$dataSet = array(
        array(2,2,4), 
        array(1,0,2), 
        array(0,0,0) 
       ); 

     //use static storage so you don't have to call the dataProvider again 
     return self::$dataSet; 
    } 

    public function testProvideAdd() 
    { 
     $data = self::$dataSet; 

     $this->assertEquals(3,count($data[0])); 

     return $data[0]; 
    } 

    /** 
    * @depends testProvideAdd 
    */ 
    public function testAdd($data) 
    { 
     $sum = $data[0] + $data[1]; 

     $this->assertEquals($data[2], $sum); 

     return array($sum,$data[0],$data[1]); 
    } 

    /** 
    * @depends testAdd 
    */ 
    public function testSubtract($data) 
    { 
     $difference = $data[0] - $data[1]; 

     $this->assertEquals($data[2], $difference); 

     return array($difference,$data[0],$data[1]); 
    } 

    /** 
    * @depends testSubtract 
    */ 
    public function testMultiply($data) 
    { 
     $product = $data[0] * $data[2]; 

     $this->assertEquals($data[1], $product); 

     return $product; 
    } 

    /** 
    * @depends testMultiply 
    * 
    * @dataProvider provideData 
    */ 
    public function testMath($a,$b,$c) 
    { 
     //don't redo the first set of tests 
     if(array($a,$b,$c) == self::$dataSet[0]) 
     { 
      return; 
     } 

     $sum = $this->testAdd(array($a,$b,$c)); 
     $difference= $this->testSubtract($sum); 
     $product = $this->testMultiply($difference); 

     $this->assertInternalType('integer', $product); 
    } 
} 

Le 2ème jeu de données échoue à 1 test pour illustrer.

+0

* Veuillez ne pas inclure le lien de votre site Web dans vos réponses de cette manière. Le lien n'est pas * directement * lié à la question, donc son apparence ressemble à du spam. Je l'enlève pour toi. –

+0

chose sûre! juste essayer d'aider –