PHP ZF2 Unit Tests submission method is very slow

I need to test a large site written in ZF2. There are 443 tests and about 10,000 statements. Testing using the code takes 6 hours! I think I found the problem: in the controller tests, I use the submit method from AbstractHttpControllerTestCase. The execution time of the sending method increases after each test (from a split second to tens of seconds).

I am using ZF 2.1.3, PHPUnit 3.7, PHP_CodeCoverage 1.2, Xdebug v2.2.1, PHP 5.4.7.

My shipping method:

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 :: dispatch is a method from AbstractHttpControllerTestCase.

Test example:

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

Please, help. Thanks.


Update:

I use process isolation and tests done after about 15 minutes (no code coverage), but I get an error in the test that are marked as missing:

 PHPUnit_Framework_Exception: PHP Fatal error: Uncaught exception 'Exception' with message 'Serialization of 'Closure' is not allowed' in -:44 
+6
source share
1 answer

Both Zend\ServiceManager and Zend\EventManager heavy use of closure. You cannot serialize the entire instance of the application and expect it to work, as this basically means that you are trying to serialize service factories and event listeners defined as closures.

The solution could be to use the Bootstrap.php test as one of the DoctrineORMModule that does not store the application instance in memory. Here's a simplified example:

 require_once __DIR__ . '/../vendor/autoload.php'; $appConfig = require __DIR__ . '/TestConfiguration.php'; \YourModuleTest\Util\ServiceManagerFactory::setConfig($appConfig); unset($appConfig); 

( TestConfiguration should look like the standard mvc application configuration )

You will also need a ServiceManagerFactory . An example implementation can be found here and 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; } } 

Now, wherever you want in your tests, you can:

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

With this setting, you can run tests in isolation.

On the other hand, you first need to focus on real unit tests, since ZF2 really makes it easy to create complex objects. You must also properly configure coverage filters so that code unrelated to it is not processed (which can be time consuming).

In addition, reusing an instance of the mvc application is incorrect, since the helpers are not stateless, which makes it difficult to reuse them.

+2
source

All Articles