2017-07-03 1 views
1

Un PHPUnit data provider allows the return of an iterator, mais lors de l'utilisation d'un AppendIterator, seul le dernier itérateur ajouté est utilisé. Est-ce que je mets les choses dans l'erreur ou est-ce que AppendIterators ne peut pas être utilisé comme fournisseur de données PHPUnit?Fournisseur de données phpunit et AppendIterator?

fichier de test:

<?php 

use PHPUnit\Framework\TestCase; 

class AppendIteratorTest extends TestCase 
{ 
    /** 
    * @dataProvider getAppendIterator 
    */ 
    public function testAppendIterator($item) { 
     echo PHP_EOL."test> $item".PHP_EOL; 
    } 

    public function getAppendIterator() { 
     $iterator = new AppendIterator(); 
     $iterator->append(new ArrayIterator([[0], [1]])); 
     $iterator->append(new ArrayIterator([[2], [3]])); 
     $iterator->append(new ArrayIterator([[4], [5]])); 

     foreach($iterator as $i) { 
      echo 'foreach> '.print_r($i, true); 
     } 

     return $iterator; 
    } 
} 

sortie du fichier de test:

$ vendor/bin/phpunit --debug AppendIteratorTest.php 
     foreach> Array 
    (
     [0] => 0 
    ) 
    foreach> Array 
    (
     [0] => 1 
    ) 
    foreach> Array 
    (
     [0] => 2 
    ) 
    foreach> Array 
    (
     [0] => 3 
    ) 
    foreach> Array 
    (
     [0] => 4 
    ) 
    foreach> Array 
    (
     [0] => 5 
    ) 
    PHPUnit 6.2.3 by Sebastian Bergmann and contributors. 


    Starting test 'AppendIteratorTest::testAppendIterator with data set #0 (4)'. 
    R 
    test> 4 

    Starting test 'AppendIteratorTest::testAppendIterator with data set #1 (5)'. 
    R                 2/2 (100%) 
    test> 5 


    Time: 24 ms, Memory: 4.00MB 

    There were 2 risky tests: 

    1) AppendIteratorTest::testAppendIterator with data set #0 (4) 
    This test did not perform any assertions 

    2) AppendIteratorTest::testAppendIterator with data set #1 (5) 
    This test did not perform any assertions 

    OK, but incomplete, skipped, or risky tests! 
    Tests: 2, Assertions: 0, Risky: 2. 

Répondre

0

Suis-je mal la configuration des différentes ou peut AppendIterators pas être utilisé en tant que fournisseurs de données PHPUnit?

Sorte de faux. -fournisseurs de données PHPUnit prennent en charge toute array ou Traversable (AppendIterator est un Traversable). Cela fonctionne donc (vous pouvez le voir car vous n'obtenez pas d'erreur).

Cependant, il existe un détail (moins connu) avec les fournisseurs de données: Chaque jeu de données peut avoir un nom. Le nom est la clé de la matrice fournie -ou- dans le cas d'un Traversable la valeur de Iterator::key(). Pour les ArrayIterator qui sont les clés de tableau.

Voici votre code avec les touches rendu visible que PHP les crée implicitement:

$iterator->append(new ArrayIterator([0 => [0], 1 => [1]])); 
    $iterator->append(new ArrayIterator([0 => [2], 1 => [3]])); 
    $iterator->append(new ArrayIterator([0 => [4], 1 => [5]])); 

Dans vos clés elle sera toujours 0 et 1. Comme vous avez les clés en double, les derniers seront « gagnant ». C'est le résultat que vous voyez.

Autant qu'une explication de ce qui se passe.

Une solution pourrait alors être:

$iterator->append(new ArrayIterator([0 => [0], 1 => [1]])); 
    $iterator->append(new ArrayIterator([2 => [2], 3 => [3]])); 
    $iterator->append(new ArrayIterator([4 => [4], 5 => [5]])); 

Il n'y a pas Iterator par défaut en PHP qui renuméroter les clés, aussi je n'ai pas dans Iterator Garden (IndexingIterator se rapproche, Borgers exemples sont en baisse, Nikic iter lib's reindex peut le faire, ...) une ligne rapide dans votre cas céderait REINDEXer:

public function getAppendIterator() { 
    $iterator = new AppendIterator(); 
    $iterator->append(new ArrayIterator([[0], [1]])); 
    $iterator->append(new ArrayIterator([[2], [3]])); 
    $iterator->append(new ArrayIterator([[4], [5]])); 

    $index = 0; 
    foreach ($iterator as $i) { 
     yield $index++ => $i; 
    } 
} 

ici, le $index compteur est utilisé comme clé dans l'instruction yield. Cela rend votre fournisseur de données de retour un Generator qui est un Traversable nouveau. Phpunit peut alors le gérer.

Le problème est similaire lorsque vous disposez de plusieurs méthodes de fournisseur de données qui renvoient des ensembles de données avec des clés de chaîne. Toutes les clés de chaîne doivent être uniques sinon les données fournies seront à nouveau écrasées. En interne, les ensembles de données de chaque fournisseur de données sont transformés en tableau de manière explicite.J'espère que cela répond à votre question et vous aide également à créer le fournisseur de données que vous recherchez.

+0

MERCI @hakre! Maintenant que j'ai lu votre réponse, c'est tout à fait logique. – Shawn