2013-03-13 21 views
6

Muszę przetestować dużą witrynę napisaną w ZF2. Jest 443 test i około 10000 asercji. Testowanie z pokryciem kodu trwa 6 godzin! Myślę, że znalazłem problem: W testach kontrolera używam metody wysyłki z AbstractHttpControllerTestCase. Czas realizacji metody wysyłki wzrasta po każdym teście (od ułamków sekund do dziesiątek sekund).PHP ZF2 Unit Testy metoda wysyłki bardzo powolna

Używam ZF 2.1.3, PHPUnit 3.7, PHP_CodeCoverage 1.2, Xdebug v2.2.1, PHP 5.4.7.

Moja metoda wysyłkowy:

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

rodzic :: dispatch jest metoda z AbstractHttpControllerTestCase.

Przykładowy test:

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

Proszę o pomoc. Dzięki.


Aktualizacja:

używam izolacji i badań wykonanych w ciągu około 15 minut (bez pokrycia kodu) proces, ale mam błąd w teście, które są oznaczone jako pominięty:

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

Czy próbowałeś przeprowadzić każdy test w izolacji? Natomiast 'dispatch()' znajduje się w ['AbstractControllerTestCase'] (https://github.com/zendframework/Component_ZendTest/blob/master/PHPUnit/Controller/AbstractControllerTestCase.php # L239) ('Zend \ Test \ PHPUnit \ Controller') – hakre

+0

To działa! Znacznie szybciej, około 15 minut, ale dostaję błąd w teście, który jest pomijany: – Kudlaty

+0

PHPUnit_Framework_Exception: PHP Błąd krytyczny: nieprzechwycony wyjątek "Wyjątek" z komunikatem "Serializacja" zamknięcia "jest niedozwolony" in:: 44 Ślad stosu: # 0 - (44): serialize (Array) # 1 - (348): __phpunit_run_isolated_test() # 2 {główny} – Kudlaty

Odpowiedz

2

Both Zend\ServiceManager i Zend\EventManager intensywnie korzystają z closures. Nie można serializować całej instancji aplikacji i oczekiwać, że to zadziała, ponieważ w zasadzie oznacza to, że próbuje się serializować fabryki usług i detektory zdarzeń zdefiniowane jako zamknięcia.

Rozwiązaniem może być użycie testu Bootstrap.php, takiego jak the one of DoctrineORMModule, który nie zachowuje instancji aplikacji w pamięci. Oto uproszczony przykład:

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

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

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

unset($appConfig); 

(TestConfiguration powinien wyglądać standard mvc application's config)

też potrzebują ServiceManagerFactory. Przykładowe wdrożenie można znaleźć pod numerami here i 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; 
    } 
} 

Teraz, gdziekolwiek chcesz w badaniach można:

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

$application->bootstrap(); 

// ... 

Przy tej konfiguracji można uruchomić testy w izolacji.

Po drugiej stronie należy najpierw skupić się na rzeczywistych testach jednostkowych, ponieważ ZF2 naprawdę upraszcza sposób komponowania złożonych obiektów. Powinieneś również poprawnie skonfigurować filtry zasięgu, aby niepowiązany kod nie był obsługiwany (może to pochłonąć dużo czasu).

Również ponowne użycie instancji aplikacji mvc jest nieprawidłowe, ponieważ pomocnicy nie są bezpaństwowcami, co utrudnia ich ponowne użycie.

+0

Wielkie dzięki za te doskonałe wyjaśnienia !!! –

Powiązane problemy