3

我在我的 Symfony2 项目中添加了许多测试,但现在有 53 个测试和 176 个断言大约需要一分钟。我试图减少这个时间,因为如果我启用代码覆盖率报告,它需要 15 分钟。

$ phpunit -c app/phpunit.xml.dist PHPUnit 4.3.5 由 Sebastian Bergmann 编写。
从 app/phpunit.xml.dist 读取配置
.......................... .............
时间:59.1 秒,内存:361.00Mb
OK(53 次测试,176 次断言)

我已正确配置LiipFunctionalTestBundle以在环境中使用 SQLite 数据库test(这是LiipFunctionalTestBundle推荐的):

app/config/config_test.yml

doctrine:
    dbal:
        default_connection: default
        connections:
            default:
                driver:   pdo_sqlite
                path:     %kernel.cache_dir%/test.db

我已经用DoctrineFixturesBundle添加了固定装置。

现在我必须创建测试套件来启动几个 PHPUnit 实例。但是我看到了一个未来的问题:如果两个或多个 phpunit 实例在同一个 SQLite 文件中写入和读取数据,如何并行化测试(例如使用paratest )?

我可以将变量传递给 PhpUnit以更改kernel.cache_dir值并cache为每个 phpunit 实例创建一个目录。但它不能从命令行完成,所以如果我选择这个解决方案,我将不得不创建几个phpunit.xml.dist. 我正在寻找更方便的解决方案。

4

2 回答 2

1

我通过创建与测试文件一样多的缓存目录找到了解决方法。

我定义了 8 个测试套件来适应我的 CPU 的 8 个内核:

<!-- app/phpunit.xml.dist -->
<?xml version="1.0" encoding="UTF-8"?>

<phpunit
    backupGlobals = "false"
    …
>
    …
    <testsuites>
        <testsuite name="Group1">
            <file>../src/AcmeBundle/Tests/Command/CommandTest.php</file>
            <file>…&lt;/file>
        </testsuite>
        …
        <testsuite name="Group8">
            <file>../src/AcmeBundle/Tests/Controller/AdminControllerTest.php</file>
        </testsuite>
    </testsuites>
</phpunit>

我创建了一个phpunit.sh脚本,它使用export(正如大卫哈克尼斯所建议的那样,以便为每个测试套件定义一个特定的路径:

#!/bin/bash

function test() {
    testsuite=$1
    export CACHE_PATH="$testsuite"
    OUTPUT=$(phpunit -c app/phpunit.xml.dist --testsuite $testsuite)
    RETURN=$?
    if [ $RETURN -eq 0 ]
    then
        echo -e -n "\033[01;32m●  OK\t\033[00m \033[01;35m$testsuite\033[00m"
        tail=$(echo "$OUTPUT" | tail -n 3)
        echo -e "\t\"$tail\"" | tr '\n' '\t' | tr -s '\t'
        echo ""
    else
        echo -e "\033[01;31m❌  ERROR\033[00m \033[01;35m$testsuite\033[00m (\033[01;34m$RETURN\033[00m)\033[00m"
        echo "-----"
        echo "$OUTPUT"
        echo "-----"
    fi
}

for testsuite in $(seq 1 8)
do
    tester "Group$testsuite" &
done

# http://unix.stackexchange.com/questions/231602/how-to-detect-that-all-the-child-processes-launched-in-a-script-ended/231608#231608
wait

echo "Done"

如果一切正常,成功的测试套件会以绿色标记显示,并且 phpunit 的输出将被截断以保持较小的输出。如果有错误会显示出来。

然后我将其添加到app/AppKernel.php

/**
 * @see http://symfony.com/fr/doc/2.3/cookbook/configuration/override_dir_structure.html#surcharger-le-repertoire-cache
 */
public function getCacheDir()
{
    $cachePath = getenv('CACHE_PATH');

    if (
        ($this->environment == 'test')
        &&
        (! empty($cachePath))
    ) {
        return(parent::getCacheDir().'/'.$cachePath.'/');
    }

    # else

    return parent::getCacheDir();
}

这段代码将告诉 Symfony 在缓存文件夹中创建一个子目录,这意味着 PHPUnit 的多个实例不会使用相同的 SQLite 文件。


虽然它有效,但这个解决方案并不完美,并且有一些缺点:

  • 即使我只想更改 SQLite 数据库的路径,它也会重新创建整个缓存
  • 它将占用空间并花费时间为每个剩余文件创建一个缓存,如果您不将 RAM 用作缓存,我建议您避免这种情况(我的解决方案是删除cacheapp/创建符号链接:ln -s /run/shm/project/cache cache,测试更快,因为缓存在 RAM 中完成,而不是在硬盘上)
于 2015-09-15T13:21:54.283 回答
0

有一个可以促进 symfony 的并行测试运行。它也可以与常规数据库一起使用,而不仅仅是 sqlite。不幸的是,它还为每个测试文件显示一个 PHPUnit 结果。但它只会在您的处理器实际可以同时执行的同时启动尽可能多的测试,而且它似乎也解决了缓存问题。

于 2016-03-28T12:44:45.487 回答