ZF2.4 花费很长时间 运行 启用代码覆盖的 phpunit

ZF2.4 takes to long to run phpunit with code coverage enabled

我在代码覆盖速度方面遇到问题。

我正在使用 ZF2 2.4 和 composer 安装的十几个模块。 当我 运行 测试没有代码覆盖时,5 分钟内得到结果。在 Jenkins 中,完整构建需要 15 分钟。

启用代码覆盖率后,整个构建时间从 0:00 到 5:30 a.m..

查看结果,我发现服务/存储库/控制器类 的测试平均每次需要 2.10 分钟。有什么可怕的。

我是tdd开发的新手,可以达到100%的代码覆盖率,系统有3个模块和10个实体。

我发现的唯一问题是我已经掌握了创建mock,然后无法mock所有应用服务,例如Repository / Service / Controller实时添加,读取,更新和删除测试数据库.

由于我的时间很短,我的主要问题是问题是否真的是模拟不正确,因为如果代码覆盖使用读取哪些文件夹的元信息,当你开始进入时应该会震惊Vendor 文件夹、Doctrine 等

所以这可能是主要问题?没有模拟银行的关系?

以我目前的技术知识,mocks 会有很大的不同,但在我工作的地方,直到今天还没有人使用过 mock,我正在努力革新。

原理已经应用了网上帖子中描述的所有技术以及Whosebug中的其他问题,请问有什么新技术可以加快代码覆盖率吗?

有一本手册着重于完整解释如何加快 PHP 的代码覆盖率?完整的解释?

感谢收听。

编辑:

Codeception 套件模块配置:

namespace: ColumnNotNull
actor: Tester
paths:
    tests: test
    log: build/coverage
    data: test/_data
    helpers: test/_support
settings:
    strict_xml: true
    bootstrap: _bootstrap.php
    colors: true
    memory_limit: 1024M
coverage:
    whitelist:
          include:
              - src/*
          exclude:
              - src/ColumnNotNull/Fixture/*
              - src/ColumnNotNull/Module.php*
    blacklist:
          include:
              - build/*
              - data/*
              - language/*
              - public/*
              - schema/*
              - test/*
              - view/*
              - src/ColumnNotNull/Fixture/*

代码接收单元套件模块配置:

class_name: UnitTester
modules:
    enabled: [Asserts, UnitHelper, Db]
    config:
      Db:
          dsn: 'mysql:dbname=pibernews;host=localhost'
          user: 'piber'
          password: 'secret'
          dump: data/column-not-null.mysql.sql
coverage:
    enabled: true
    remote_enable : false

Codeception 项目套件

include:
  - module/Column
  - module/ColumnImage
  - module/ColumnNotNull
paths:
  log: build
settings:
  colors: true

使用 codeception,我可以 运行 来自不同模块的多个测试以及合并结果。

是一个项目,三个模块。通过验收和功能测试。验收 + 功能 运行 需要 15 分钟,代码覆盖单元需要五个小时。

没有代码覆盖需要 10 分钟 运行 所有单元测试。这是可以接受的。但我想减少代码覆盖时间,因为五个小时是不可接受的。

编辑 2:

<?php
// This is global bootstrap for autoloading
include 'unit/GearBaseTest/ZendServiceLocator.php';

$zendServiceLocator = new \GearBaseTest\ZendServiceLocator();

_bootstrap.php 文件

<?php
namespace GearBaseTest;

use Zend\Loader\AutoloaderFactory;
use Zend\Mvc\Service\ServiceManagerConfig;
use Zend\ServiceManager\ServiceManager;
use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase;

class ZendServiceLocator
{
    public function __construct()
    {
        $this->chroot();

        $zf2ModulePaths = array(
            dirname(dirname(realpath(__DIR__ . '/../../')))
        );

        if (($path = $this->findParentPath('vendor'))) {
            $zf2ModulePaths[] = $path;
        }

        if (($path = $this->findParentPath('module')) !== $zf2ModulePaths[0]) {
            $zf2ModulePaths[] = $path;
        }

        $this->initAutoloader();

        $env = getenv('APP_ENV') ?  : 'testing';


        $applicationConfig = include \GearBase\Module::getProjectFolder().'/config/application.config.php';

        $config = array(
            'module_listener_options' => array(
                'module_paths' => $zf2ModulePaths,
                'config_glob_paths' => array(
                    sprintf('config/autoload/{,*.}{global,%s,local}.php', $env)
                )
            ),
            'modules' => $applicationConfig['modules']
        );


        $serviceLocator = new ServiceManager(new ServiceManagerConfig());
        $serviceLocator->setService('ApplicationConfig', $config);
        $serviceLocator->get('ModuleManager')->loadModules();
        $this->serviceLocator = $serviceLocator;
    }

    public function getServiceManager()
    {
        return $this->getServiceLocator()->get('ServiceManager');
    }

    public function chroot()
    {
        $rootPath = dirname($this->findParentPath('module'));
        chdir($rootPath);
    }

    protected function findParentPath($path)
    {
        $dir = __DIR__;
        $previousDir = '.';
        while (! is_dir($dir . '/' . $path)) {
            $dir = dirname($dir);
            if ($previousDir === $dir) {
                return false;
            }
            $previousDir = $dir;
        }
        return $dir . '/' . $path;
    }

    public function getEntityManager()
    {
        if (!isset($this->entityManager)) {
            $this->entityManager = $this->getServiceLocator()
            ->get('doctrine.entitymanager.orm_default');
        }
        return $this->entityManager;
    }

    public function getServiceLocator()
    {
        return $this->serviceLocator;
    }

    public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
    {
        if (!isset($this->serviceLocator)) {
            $this->serviceLocator = $serviceLocator;
        }
        return $this->serviceLocator;
    }

    protected function initAutoloader()
    {
        $vendorPath = $this->findParentPath('vendor');

        $zf2Path = getenv('ZF2_PATH');

        if (! $zf2Path) {
            if (defined('ZF2_PATH')) {
                $zf2Path = ZF2_PATH;
            } elseif (is_dir($vendorPath . '/ZF2/library')) {
                $zf2Path = $vendorPath . '/ZF2/library';
            } elseif (is_dir($vendorPath . '/zendframework/zendframework/library')) {
                $zf2Path = $vendorPath . '/zendframework/zendframework/library';
            }
        }

        if (! $zf2Path) {
            throw new RuntimeException(
                'Unable to load ZF2. Run `php composer.phar install` or' . ' define a ZF2_PATH environment variable.'
            );
        }

        if (file_exists($vendorPath . '/autoload.php')) {
            include $vendorPath . '/autoload.php';
        }
        include $zf2Path . '/Zend/Loader/AutoloaderFactory.php';

        AutoloaderFactory::factory(array(
            'Zend\Loader\StandardAutoloader' => array(
                'autoregister_zf' => true,
                'namespaces' => array(
                    __NAMESPACE__ => __DIR__ . '/' . __NAMESPACE__
                )
            )
        ));
    }
}

ZendServiceLocator.php抓取器。

您只需要将模块文件夹列入白名单即可。