2012-01-23 4 views
6

Sto cercando di aggiungere un assert personalizzato per PHPUnit, dopo this tutorial, per convalidare i numeri complessi restituiti sotto forma di stringa (ad esempiophpunit personalizzato afferma aiuto necessario

"-123 + 456i"

dal metodo che sto testando) con una precisione definita per entrambi i componenti reali e immaginari. Ho messo una classe Complex.php per analizzare la stringa nelle parti reale e immaginaria, e mettere insieme la seguente classe asserzione come complexAssert.php:

require_once 'PHPUnit/Framework/Assert.php'; 
include_once getcwd().'/custom/Complex.php'; 

class complexAssert extends PHPUnit_Framework_Assert { 

    public function assertComplexEquals($expected, $actual, $message = '', $delta = 0) 
    { 
     $expectedComplex = new Complex($expected); 
     $actualComplex = new Complex($actual); 

     if (!($actualComplex->getReal() >= ($expectedComplex - $delta) && 
      $actualComplex->getReal() <= ($expectedComplex + $delta))) { 
      return $this->fail($message); 
     } 

     if (!($actualComplex->getImaginary() >= ($expectedComplex - $delta) && 
      $actualComplex->getImaginary() <= ($expectedComplex + $delta))) { 
      return $this->fail($message); 
     } 

    } 
} 

Il mio script di test di unità:

require_once getcwd().'/custom/complexAssert.php'; 
require_once 'testDataFileIterator.php'; 

class EngineeringTest extends PHPUnit_Framework_TestCase 
{ 
    /** 
    * @dataProvider providerIMSUM 
    */ 
    public function testIMSUM() 
    { 
     $args = func_get_args(); 
     $expectedResult = array_pop($args); 
     $result = call_user_func_array(array('PHPExcel_Calculation_Engineering','IMSUM'),$args); 
     $this->assertComplexEquals($expectedResult, $result); 
    } 

    public function providerIMSUM() 
    { 
     return new testDataFileIterator('rawTestData/Calculation/Engineering/IMSUM.data'); 
    } 
} 

I test delle unità hanno funzionato senza errori (ma non sono riusciti) quando stavo semplicemente facendo un assertEquals ... ma ora ho aggiunto l'inclusione e ho cambiato il mio nuovo assert, si blocca affermando che non può chiamare il metodo indefinito assertComplexEquals ().

Qualcuno ha avuto successo estendendo la phpunit con asserzioni personalizzate e può vedere cosa sto facendo male?

+0

Si potrebbe meglio seguire il http://www.phpunit.de/manual/current/en/extending-phpunit.html#extending-phpunit.custom-assertions – zerkms

+2

, benché non correlato a questo problema, si potrebbe voler usare '__DIR__' (PHP 5.3 +) o 'dirname (__ FILE __)' piuttosto che de in attesa sulla directory di lavoro corrente che può cambiare durante l'esecuzione del programma. –

+0

@David Harkness: Scommetto che nel suo caso 'getcwd()! = __DIR__' – zerkms

risposta

0

Alla fine, ho scelto di non prolungare esistente afferma, ma modificare mia logica asserzione complesso per restituire un semplice booleano, che potrebbe quindi essere testato utilizzando assertTrue() e con un messaggio di errore che può essere recuperato con un semplice getMessage() per la visualizzazione nei risultati di phpunit. Per essere onesti, ci si sente molto più semplice da usare in questo modo

include_once __DIR__.'/Complex.php'; 

class complexAssert { 

    private $_errorMessage = ''; 

    public function assertComplexEquals($expected, $actual, $delta = 0) 
    { 
     $expectedComplex = new Complex($expected); 
     $actualComplex = new Complex($actual); 

     if ($actualComplex->getReal() < ($expectedComplex->getReal() - $delta) || 
      $actualComplex->getReal() > ($expectedComplex->getReal() + $delta)) { 
      $this->_errorMessage = 'Mismatched Real part: ' . 
            $actualComplex->getReal() . 
            ' !== ' . 
            $expectedComplex->getReal(); 
      return FALSE; 
     } 

     if ($actualComplex->getImaginary() < ($expectedComplex->getImaginary() - $delta) || 
      $actualComplex->getImaginary() > ($expectedComplex->getImaginary() + $delta)) { 
      $this->_errorMessage = 'Mismatched Imaginary part: ' . 
            $actualComplex->getImaginary() . 
            ' !== ' . 
            $expectedComplex->getImaginary(); 
      return FALSE; 
     } 

     return TRUE; 
    } 

    public function getErrorMessage() { 
     return $this->_errorMessage; 
    } 
} 

Il mio script di test di unità:

// Custom assertion class for handling precision of Complex numbers 
require_once __DIR__.'/../../custom/complexAssert.php'; 
// Data Provider handler 
require_once 'testDataFileIterator.php'; 

class EngineeringTest extends PHPUnit_Framework_TestCase 
{ 
    /** 
    * @dataProvider providerIMSUM 
    */ 
    public function testIMSUM() 
    { 
     $args = func_get_args(); 
     $expectedResult = array_pop($args); 
     $result = call_user_func_array(array('PHPExcel_Calculation_Engineering','IMSUM'),$args); 
     $complexAssert = new complexAssert(); 
     $this->assertTrue($complexAssert->assertComplexEquals($expectedResult, $result, 1E-8), 
          $complexAssert->getErrorMessage()); 
    } 

    public function providerIMSUM() 
    { 
     return new testDataFileIterator('rawTestData/Calculation/Engineering/IMSUM.data'); 
    } 
} 

e il risultato phpunit registrato è abbastanza chiaro:

3) EngineeringTest::testIMSUB with data set #7 ('-12.34-5.67i', '-123.45-67.89', '#NUM!') 
Mismatched String: 111.11 !== #NUM! 
Failed asserting that false is true. 
1

Ovviamente l'unico modo per ottenere $this->someCustomAssertion ha funzionato è di estendere PHPUnit_Framework_TestCase e creare lì i metodi wrapper o chiamare staticamente le proprie asserzioni personalizzate.

Zend Framework, per esempio, solo estende PHPUnit_Framework_TestCase con metodi aggiuntivi (asserzioni)