2010-11-24 38 views
18

tengo el siguiente caso de prueba:Problema con PHPUnit Proveedores de datos e

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); 
    } 

} 

Cuando corro en PHPUnit, me sale:

PHPUnit 3.4.14 by Sebastian Bergmann. 

.......... 

Time: 0 seconds, Memory: 5.75Mb 

OK (1 tests, 0 assertions) 

prueba falla, pero no es así. He intentado tener:

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

Pero consigo:

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

me trataron declarando que static (como dice el manual), pero todavía no hay diferencia.

Recuerdo haberlo trabajado de manera similar anteriormente, pero podría estar equivocado. ¿Qué me estoy perdiendo?

Gracias de antemano por su ayuda.

PHPUnit 3.4.14 (tomado de PEAR) en PHP 5.3.3

+0

1 pruebas, ** 0 ** aserciones. Su prueba ni siquiera fue llamada. Apuesto a que el problema no está en el proveedor de datos. – zerkms

+0

De hecho, si elimino el elemento @dataProvider, aparece un error porque testAddStream() requiere un parámetro. Si elimino el parámetro por completo, la prueba falla como debería. – netcoder

+0

Tengo un problema al usar PHPUnit en Zend Studio, donde si registro un espacio de nombres con Zend_Autoloader, usar @dataProvider hace que (intente) cargar el nombre de la prueba como una clase. Voy a establecer probabilidades de que estos 2 problemas estén relacionados. – Duncan

Respuesta

27

Actualización secundaria: Está bien utilizar métodos de instancia como proveedor desde la versión 3.2 (o en algún lugar). Eche un vistazo a los comentarios


El proveedor debe tener este aspecto.

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

En primer lugar: El método debe ser estática

Los matriz s son importantes. No es tan difícil de entender. La matriz externa tiene un valor para cada iteración a la que se debe llamar la prueba. Aquí la prueba acaba de ser llamada una vez. Los arreglos internos son los parámetros (en orden) con los que se invoca la prueba. Su prueba espera exactamente un parámetro, por lo que las matrices internas siempre necesitan exactamente un valor. Otro pequeño ejemplo

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); 
} 

Aquí testAdd es ejecutado 3 veces, una por cada segundo nivel array, y recibirá los valores del interior array s. Puede observar que la prueba fallará y le proporcionará un mensaje en el que la iteración del conjunto de datos (aquí n. ° 3, porque 5 + 5 no es 6;)) la aserción falló.

+0

Eso fue lo que parece. Había intentado 'estático', había intentado arreglos, también había intentado arreglos de matrices (la solución real), pero debo haber hecho algo mal, porque funciona ahora. ¡Gracias un montón! – netcoder

+14

¿Me falta algo? ¿Por qué tiene que ser estático? El [Manual de PHPUnit también usa métodos regulares] (http://www.phpunit.de/manual/3.4/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.data-providers) – Gordon

+1

Hmm ... Tienes razón. Así que tal vez está bien, si no es estático;) Parece que cambió con 3.3. Al menos el ejemplo en 3.2 es diferente;) – KingCrunch

-1

eliminar el parámetro de testAddStream función pública ($ logger) y vuelve a intentarlo. No creo que PHPUnit invoque una prueba que requiera parámetros que no pueda pasar.

+0

Si elimino el parámetro, la prueba se ejecuta y falla como debería. El objetivo del bloque @dataProvider es pasar los parámetros a una prueba, como se demostró [en el manual] (http://www.phpunit.de/manual/3.2/en/writing-tests-for-phpunit.html). – netcoder

+0

Ah, ya veo. Su función de proveedor de datos debe ser pública y estática. Consulte esta publicación en el manual: "Un método de proveedor de datos debe ser público y estático y devolver una matriz de matrices o un objeto que implemente la interfaz de iterador y ceda una matriz para cada paso de iteración. Para cada matriz que sea parte de la colección se llamará al método de prueba con los contenidos de la matriz como sus argumentos ". –

+0

@Macy: Desafortunadamente, lo intenté también (estático, no estático, devolver matriz, devolver objeto ...) y aún así el mismo resultado ... – netcoder

5

Tuve el mismo problema, y ​​fue resuelto, cuando eliminé el constructor vacío, que se generó automáticamente. No estoy seguro de por qué esto resuelve el problema. Tampoco tenía ningún método de prueba llamado como la clase. El método de proveedor no necesita ser estático, hasta ahora mi prueba se ejecuta sin estática.Pero también corren cuando hago el método proveedor de estática

+1

¡Muchas gracias! Eliminar __construct realmente ayuda. – barbushin

+7

También encontré que puedes usar __construct, pero no olvides llamar a parent :: _construir así: public function __construct ($ name = NULL, array $ data = array(), $ dataName = '') { \t // ... \t \t parent :: __ construct ($ name, $ data, $ dataName); \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) 
     ); 
    } 
} 

es el conjunto completo de código

0

También he encontrado que no se puede encadenar directamente a los proveedores de datos:

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); 
    } 

} 

Al parecer, las llamadas PHPUnit todas las funciones de proveedor antes de ejecutar cualquier prueba, por lo que ni siquiera puede usar funciones de proveedor separadas para enviar datos de resultados de prueba a otras pruebas. Lo mejor que puede hacer es simular:

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

He aquí que he logrado un patrón para lograr dependencias de prueba para dataProviders! De esta manera, puede encadenar DataProviders.

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); 
    } 
} 

El segundo conjunto de datos falla 1 prueba para ilustrar.

+0

* Por favor * no incluya el enlace de su sitio web en sus respuestas de esta manera. El enlace no está * directamente * relacionado con la pregunta, por lo que su aspecto aquí parece spam. Lo estoy removiendo por ti. –

+0

¡algo seguro! sólo trato de ayudar –

Cuestiones relacionadas