在使用 SQLite 数据库时并行化功能测试
Parallelize functional tests while using a SQLite database
我在我的 Symfony2 项目中添加了许多测试,但现在有 53 个测试和 176 个断言,大约需要一分钟。我正在努力减少这个时间,因为如果我启用代码覆盖率报告,它需要 15 分钟。
$ phpunit -c app/phpunit.xml.dist PHPUnit 4.3.5 by Sebastian Bergmann.
Configuration read from app/phpunit.xml.dist
.....................................................
Time: 59.1 seconds, Memory: 361.00Mb
OK (53 tests, 176 assertions)
我已经配置 LiipFunctionalTestBundle correctly to use a SQLite database in the test
environment (this is recommended by LiipFunctionalTestBundle):
app/config/config_test.yml
doctrine:
dbal:
default_connection: default
connections:
default:
driver: pdo_sqlite
path: %kernel.cache_dir%/test.db
并且我添加了 DoctrineFixturesBundle 的固定装置。
如果两个或多个 phpunit 实例在同一个 SQLite 文件中写入和读取数据,现在我必须创建 tests suites or groups to launch several instances of PHPUnit. But I'm seeing a future problem: how can tests can be parallelized (for example with paratest)?
我可以 Pass a variable to PhpUnit 更改 kernel.cache_dir
值并为每个 phpunit 实例创建一个 cache
目录。但它不能从命令行完成,所以如果我选择这个解决方案,我将不得不创建几个 phpunit.xml.dist
。我正在寻找更方便的解决方案。
我通过创建与测试文件一样多的缓存目录找到了解决方法。
我定义了 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>…</file>
</testsuite>
…
<testsuite name="Group8">
<file>../src/AcmeBundle/Tests/Controller/AdminControllerTest.php</file>
</testsuite>
</testsuites>
</phpunit>
我创建了一个 phpunit.sh 脚本,它使用 export
(按照 David Harkness 的建议,以便为每个测试定义特定路径套房:
#!/bin/bash
function test() {
testsuite=
export CACHE_PATH="$testsuite"
OUTPUT=$(phpunit -c app/phpunit.xml.dist --testsuite $testsuite)
RETURN=$?
if [ $RETURN -eq 0 ]
then
echo -e -n "3[01;32m● OK\t3[00m 3[01;35m$testsuite3[00m"
tail=$(echo "$OUTPUT" | tail -n 3)
echo -e "\t\"$tail\"" | tr '\n' '\t' | tr -s '\t'
echo ""
else
echo -e "3[01;31m❌ ERROR3[00m 3[01;35m$testsuite3[00m (3[01;34m$RETURN3[00m)3[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 数据库的路径,它也会重新创建整个缓存
- 它将使用 space 并且需要时间为每个 rest 文件创建一个缓存,如果你不使用 RAM 作为缓存,我建议你避免这种情况(我的解决方案是删除 在 app/ 中缓存 并创建一个符号链接:
ln -s /run/shm/project/cache cache
,测试速度更快,因为缓存是在 RAM 中完成的,而不是在硬盘驱动器上)
有一个 bundle 可以促进与 symfony 的并行测试运行。它也可以与常规数据库一起使用,而不仅仅是 sqlite。不幸的是,它还会为每个测试文件显示一个 PHPUnit 结果。但它只会启动与你的处理器实际可以同时执行的一样多的并行测试,而且它似乎也解决了缓存问题。
我在我的 Symfony2 项目中添加了许多测试,但现在有 53 个测试和 176 个断言,大约需要一分钟。我正在努力减少这个时间,因为如果我启用代码覆盖率报告,它需要 15 分钟。
$ phpunit -c app/phpunit.xml.dist PHPUnit 4.3.5 by Sebastian Bergmann.
Configuration read from app/phpunit.xml.dist
.....................................................
Time: 59.1 seconds, Memory: 361.00Mb
OK (53 tests, 176 assertions)
我已经配置 LiipFunctionalTestBundle correctly to use a SQLite database in the test
environment (this is recommended by LiipFunctionalTestBundle):
app/config/config_test.yml
doctrine:
dbal:
default_connection: default
connections:
default:
driver: pdo_sqlite
path: %kernel.cache_dir%/test.db
并且我添加了 DoctrineFixturesBundle 的固定装置。
如果两个或多个 phpunit 实例在同一个 SQLite 文件中写入和读取数据,现在我必须创建 tests suites or groups to launch several instances of PHPUnit. But I'm seeing a future problem: how can tests can be parallelized (for example with paratest)?
我可以 Pass a variable to PhpUnit 更改 kernel.cache_dir
值并为每个 phpunit 实例创建一个 cache
目录。但它不能从命令行完成,所以如果我选择这个解决方案,我将不得不创建几个 phpunit.xml.dist
。我正在寻找更方便的解决方案。
我通过创建与测试文件一样多的缓存目录找到了解决方法。
我定义了 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>…</file>
</testsuite>
…
<testsuite name="Group8">
<file>../src/AcmeBundle/Tests/Controller/AdminControllerTest.php</file>
</testsuite>
</testsuites>
</phpunit>
我创建了一个 phpunit.sh 脚本,它使用 export
(按照 David Harkness 的建议,以便为每个测试定义特定路径套房:
#!/bin/bash
function test() {
testsuite=
export CACHE_PATH="$testsuite"
OUTPUT=$(phpunit -c app/phpunit.xml.dist --testsuite $testsuite)
RETURN=$?
if [ $RETURN -eq 0 ]
then
echo -e -n "3[01;32m● OK\t3[00m 3[01;35m$testsuite3[00m"
tail=$(echo "$OUTPUT" | tail -n 3)
echo -e "\t\"$tail\"" | tr '\n' '\t' | tr -s '\t'
echo ""
else
echo -e "3[01;31m❌ ERROR3[00m 3[01;35m$testsuite3[00m (3[01;34m$RETURN3[00m)3[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 数据库的路径,它也会重新创建整个缓存
- 它将使用 space 并且需要时间为每个 rest 文件创建一个缓存,如果你不使用 RAM 作为缓存,我建议你避免这种情况(我的解决方案是删除 在 app/ 中缓存 并创建一个符号链接:
ln -s /run/shm/project/cache cache
,测试速度更快,因为缓存是在 RAM 中完成的,而不是在硬盘驱动器上)
有一个 bundle 可以促进与 symfony 的并行测试运行。它也可以与常规数据库一起使用,而不仅仅是 sqlite。不幸的是,它还会为每个测试文件显示一个 PHPUnit 结果。但它只会启动与你的处理器实际可以同时执行的一样多的并行测试,而且它似乎也解决了缓存问题。