2012-05-22 4 views
8

Ho un test in cui un test viene eseguito più volte tramite un @dataProvider e un altro test che @depends sul primo metodo. Tuttavia, quando ho chiamato var_dump su ciò che dovrebbe essere passato al secondo test, mi dà un solido NULL, che non mi aspettavo.Posso usare @depends per dipendere da un test usando @dataProvider?

In altre parole: cosa dovrebbe fare questo:

<?php 
class DevicesTest extends PHPUnit_Framework_TestCase 
{ 
    /** 
    * @dataProvider registerDataProvider 
    */ 
    public function testRegister($device, $supposedResult) 
    { 
     //do a bunch of tests 
     return array($device, $supposedResult); 
    } 

    public function registerDataProvider() 
    { 
     return array(array("foo", "foo")); 
    } 

    /** 
    * @depends testRegister 
    */ 
    public function testSaveDevicePreferences($deviceArr) 
    { 
     $this->assertNotEmpty($deviceArr); 
    } 
} 
?> 

risposta

5

Normalmente @dataProvider è usato quando si desidera eseguire un test più volte con set di dati diversi per ciascuno. Esiste per evitare di scrivere codice di looping nel test e consentire a set di dati diversi di passare o fallire individualmente.

Come ho detto nei miei commenti, credo che PHPUnit utilizzerà sia @dependso@dataProvider, e dal vostro esempio la mia ipotesi è che la seconda vince. Un'altra possibilità è che i test con i fornitori di dati non possano essere usati come dipendenze perché PHPUnit non sa quale test-plus-dataset scegliere.

Poiché registerDataProvider restituisce un singolo set di dati, è possibile richiamarlo facilmente dal test stesso. Ciò consentirebbe a @depends di funzionare nel secondo test senza il @dataProvider. Supponendo che testRegister ha la necessità di modificare $device e/o $supposedResult, questo dovrebbe funzionare:

class DevicesTest extends PHPUnit_Framework_TestCase { 
    public function testRegister() { 
     list($device, $supposedResult) = $this->registerDataProvider(); 
     //do a bunch of tests 
     //register a device in the DB 
     return array($device, $supposedResult); 
    } 

    public function registerDataProvider() { 
     return array("foo", "foo"); 
    } 

    /** 
    * @depends testRegister 
    */ 
    public function testSaveDevicePreferences($data) { 
     list($device, $supposedResult) = $data; 
     // do stuff dependent on testRegister() 
     $this->assertEquals($device, $supposedResult); 
    } 
} 

Se queste variabili non hanno bisogno di essere modificato dal primo test, si può semplicemente chiamare registerDataProvider da entrambi i test. Si noti che PHPUnit non separerà un array restituito da un dipendente su un test in argomenti al test dipendente come fa il meccanismo del provider di dati. Questo perché non sa che la matrice restituita è più argomenti rispetto a un singolo argomento.

+0

Vedere https://github.com/sebastianbergmann/phpunit/issues/183#issuecomment-816066 per una spiegazione su questo comportamento – pedromanoel

+0

I dati di '@ dataProvider' vengono prima, che i dati provenienti da '@ depends'. È così che funziona per me. –

-1

ho scoperto che no, questo non è possibile. Tuttavia, leggermente adattando il testclass, ho raggiunto sostanzialmente il medesimo risultato, tuttavia, il rapporto dipendente sembra essere perso dal fatto che se il primo test fallisce, il secondo corre felicemente:

<?php 
class DevicesTest extends PHPUnit_Framework_TestCase 
{ 
    /** 
    * @dataProvider registerDataProvider 
    */ 
    public function testRegister($device, $supposedResult) 
    { 
     //do a bunch of tests 
     //register a device in the DB 
     return array($device, $supposedResult); 
    } 

    public function registerDataProvider() 
    { 
     return array(array("foo", "foo")); 
    } 

    /** 
    * @depends testRegister 
    * @dataProvider registerDataProvider 
    */ 
    public function testSaveDevicePreferences($device, $supposedResult) 
    { 
     // do stuff dependent on testRegister() 
     $this->assertEquals($device, $supposedResult); 
    } 
} 
?> 
+0

sarei curioso come questo si comporta quando il metodo provider di dati restituisce un array con più di un array di parametri. Il metodo di prova dovrebbe essere chiamato una volta per ciascun array di parametri, ma le dipendenze di test sono progettate per dipendere da un singolo richiamo del metodo di test. –

+0

Si comporta in modo corretto, tuttavia, non appena viene modificato, il secondo test non viene saltato se il primo test fallisce. Inoltre, il secondo test dipende da alcune cose presenti nel database, che vengono inserite nel primo test.Il fatto che siano lì significa che il primo test viene eseguito prima del secondo. – Zsub

+0

I test vengono eseguiti nell'ordine in cui sono dichiarati. PHPUnit non li riordina in base al grafico delle dipendenze. Poiché il secondo test utilizza lo stesso fornitore di dati, riceve i suoi dati da quel metodo piuttosto che il test da cui dipende. La mia scommessa è che PHPUnit cerca '@ dataProvider' prima di' @ depends' e quindi puoi rimuovere la dipendenza senza alcun effetto. –

9

Nella versione corrente di PHPUnit (5.4 a oggi), è possibile.

Secondo il documentation:

Se una prova riceve input sia da un metodo @dataProvider e da uno o più test si @depends su argomenti, dal fornitore di dati verrà prima di quelli da dipendeva -solo test. Gli argomenti dei test dipendenti dipenderanno per ogni set di dati.

Ecco come apparirebbe in pratica:

<?php 

class DataProviderAndDependsCombinationTest extends AbstractUnittest{ 

    public function dataProviderForSomething() 
    { 
     return array(
      array(
       'someProvidedValue', 
       'someOtherProvidedValue' 
      ) 
     ); 
    } 

    public function testToDependOn() 
    { 
     $this->assertTrue(true); 
     return 'someDependedValue'; 
    } 

    /** 
    * @dataProvider dataProviderForSomething 
    * @depends testToDependOn 
    */ 
    public function testSomething($someProvidedValue, $someOtherProvidedValue, $someDependedValue) 
    { 
     $this->assertSame('someProvidedValue', $someProvidedValue); 
     $this->assertSame('someOtherProvidedValue', $someOtherProvidedValue); 
     $this->assertSame('someDependedValue', $someDependedValue); 
    } 
} 
+0

Esattamente. Questo dovrebbe essere accettato per lo stato attuale. –

+0

Non proprio quello che la domanda stava ponendo riguardo però. OP ha '@ dataProvider' sul test da cui dipende, non sul test che dipende da un altro (come qui). – Luke