2013-03-13 11 views
6

Ho bisogno di testare un grande sito scritto in ZF2. C'è 443 test e circa 10000 asserzioni. Il test con la copertura del codice richiede 6 ore! Penso di aver trovato il problema: nei test del controller, utilizzo un metodo di invio da AbstractHttpControllerTestCase. Il tempo di esecuzione del metodo di spedizione aumenta dopo ogni test (da frazioni di secondo a decine di secondi).PHP ZF2 Test dell'unità metodo di invio molto lento

Uso ZF 2.1.3, PHPUnit 3.7, PHP_CodeCoverage 1.2, Xdebug v2.2.1, PHP 5.4.7.

mio metodo la spedizione:

public function dispatch($url, $method = HttpRequest::METHOD_GET, $params = array()) 
{ 
    $s = microtime(true); 

    parent::dispatch($url, $method, $params); 

    $end = microtime(true) - $s; 
    echo 'dis: '.$end."\n"; 

    return $this->getApplication()->getMvcEvent()->getResult(); 
} 

parent :: la spedizione è il metodo da AbstractHttpControllerTestCase.

Campione di prova:

$result = $this->dispatch('/archive/finance/older'); 

$this->assertControllerName('skycontent\controller\article'); 
$this->assertActionName('archive'); 
$this->assertParamValue('older', true); 
$this->assertParamValue('category', 'finance'); 

$vars = (array) $result->getVariables(); 

$this->assertArrayHasKey('archivePosts', $vars); 

prega di aiuto. Grazie.


Aggiornamento:

Io uso l'isolamento e test effettuati in circa 15 minuti (senza copertura del codice) processo, ma ottengo l'errore nel test che sono contrassegnati come saltato:

PHPUnit_Framework_Exception: PHP Fatal error: Uncaught exception 'Exception' with message 'Serialization of 'Closure' is not allowed' in -:44 
+0

Hai provato a eseguire ogni test separatamente? E 'dispatch()' è in ['AbstractControllerTestCase'] (https://github.com/zendframework/Component_ZendTest/blob/master/PHPUnit/Controller/AbstractControllerTestCase.php # L239) ('Zend \ Test \ PHPUnit \ Controller') – hakre

+0

Funziona! Molto più veloce, circa 15 minuti, ma ottengo errori nel test che vengono saltati: – Kudlaty

+0

PHPUnit_Framework_Exception: PHP Errore irreversibile: eccezione non rilevata 'Eccezione' con messaggio 'Serializzazione di' Chiusura 'non consentita' in -: 44 Traccia stack: # 0 - (44): serialize (matrice) # 1 - (348): __phpunit_run_isolated_test() # 2 {main} – Kudlaty

risposta

2

Entrambi Zend\ServiceManager e Zend\EventManager fare uso intensivo di closures. Non è possibile serializzare un'intera istanza dell'applicazione e aspettarsi che funzioni, poiché in pratica significherebbe tentare di serializzare le fabbriche di servizi e gli ascoltatori di eventi definiti come chiusure.

La soluzione potrebbe essere quella di utilizzare un test Bootstrap.php come the one of DoctrineORMModule, che non mantiene un'istanza dell'applicazione in memoria. Ecco un esempio semplificato:

require_once __DIR__ . '/../vendor/autoload.php'; 

$appConfig = require __DIR__ . '/TestConfiguration.php'; 

\YourModuleTest\Util\ServiceManagerFactory::setConfig($appConfig); 

unset($appConfig); 

(la TestConfiguration dovrebbe apparire come un standard mvc application's config)

è necessario anche il ServiceManagerFactory. È possibile trovare l'implementazione di esempio here e here.

namespace YourModuleTest\Util; 

class ServiceManagerFactory 
{ 
    /** 
    * @var array 
    */ 
    protected static $config; 

    /** 
    * @param array $config 
    */ 
    public static function setConfig(array $config) 
    { 
     static::$config = $config; 
    } 

    /** 
    * Builds a new service manager 
    * Emulates {@see \Zend\Mvc\Application::init()} 
    */ 
    public static function getServiceManager() 
    { 
     $serviceManager = new ServiceManager(new ServiceManagerConfig(
      isset(static::$config['service_manager']) 
       ? static::$config['service_manager'] 
       : array() 
     )); 

     $serviceManager->setService('ApplicationConfig', static::$config); 
     $serviceManager->setFactory(
      'ServiceListener', 
      'Zend\Mvc\Service\ServiceListenerFactory' 
     ); 

     /** @var $moduleManager \Zend\ModuleManager\ModuleManager */ 
     $moduleManager = $serviceManager->get('ModuleManager'); 
     $moduleManager->loadModules(); 

     return $serviceManager; 
    } 
} 

Ora, dove vuoi nei test, è possibile:

$serviceManager = \YourModuleTest\Util\ServiceManagerFactory::getServiceManager(); 
$application = $serviceManager->get('Application'); 

$application->bootstrap(); 

// ... 

Con questa configurazione, è possibile eseguire i test in isolamento.

Dall'altro lato, è necessario concentrarsi innanzitutto sui test di unità reali, poiché ZF2 semplifica davvero come è possibile comporre oggetti complessi. Dovresti anche impostare correttamente i filtri di copertura in modo che il codice non correlato non venga gestito (potrebbe consumare molto tempo).

Inoltre, il riutilizzo dell'istanza dell'applicazione mvc è sbagliato, poiché gli helper non sono stateless, il che rende difficile riutilizzarli.

+0

Grazie mille per queste eccellenti spiegazioni !!! –