CircleCI에서 PHPUnit 병렬 실행
phpunit
)은 여러 파일 이름을 받아 실행할 수 없습니다.circleci tests glob "tests/**/*Test.php" | circleci tests split
# => インスタンスに割り当てられたテストファイル名のリスト (スペース区切)
# => そのままでは phpunit で実行できない...
그래서, 파일명의 리스트를 인수에 있어서, 그 테스트를 실행하기 위한
phpunit.xml
( phpunit-partial.xml
) (을)를 생성하는 툴을 작성해 대응했습니다.phpunit-xml-gen.php
phpunit-xml-gen.php<?php
$files = array_slice($argv, 1);
$xml = new DOMDocument();
$xml->load(__DIR__ . '/phpunit.xml');
$testsuite = $xml->createElement('testsuite');
$testsuite->setAttribute('name', 'partial');
foreach ($files as $file) {
$testsuite->appendChild($xml->createElement('file', $file));
}
$testsuites = $xml->createElement('testsuites');
$testsuites->appendChild($testsuite);
$phpunit = $xml->getElementsByTagName('phpunit')->item(0);
$phpunit->replaceChild($testsuites, $phpunit->getElementsByTagName('testsuites')->item(0));
$xml->save(__DIR__ . '/phpunit-partial.xml');
exit(0);
<?php
$files = array_slice($argv, 1);
$xml = new DOMDocument();
$xml->load(__DIR__ . '/phpunit.xml');
$testsuite = $xml->createElement('testsuite');
$testsuite->setAttribute('name', 'partial');
foreach ($files as $file) {
$testsuite->appendChild($xml->createElement('file', $file));
}
$testsuites = $xml->createElement('testsuites');
$testsuites->appendChild($testsuite);
$phpunit = $xml->getElementsByTagName('phpunit')->item(0);
$phpunit->replaceChild($testsuites, $phpunit->getElementsByTagName('testsuites')->item(0));
$xml->save(__DIR__ . '/phpunit-partial.xml');
exit(0);
phpunit.xml
의 <testsuites />
요소내를, 건네받은 파일명을 실행하는 <testsuite />
로 옮겨놓아, phpunit-partial.xml
를 생성한다. phpunit.xml
에서 생성되므로 실행 파일 이외의 다른 설정을 인계합니다. phpunit
를 실행하는 스크립트로 해도 좋았지만, 런타임에 옵션을 건네주고 싶기 때문에 그것은 그만두었다. 이것을 다음과 같은 느낌으로 실행하면(요
phpunit.xml
)$ echo tests/FooTest.php tests/BarTest.php | xargs php ./phpunit-xml-gen.php
이러한 느낌의
phpunit-partial.xml
가 생성됩니다. 이 파일을 phpunit
의 -c
( --configuration
) 옵션에 전달하면 모든 테스트 파일 만 실행할 수 있습니다.phpunit-partial.xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="partial">
<file>tests/FooTest.php</file>
<file>tests/BarTest.php</file>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./app</directory>
</whitelist>
</filter>
<php>
<env name="APP_ENV" value="testing"/>
</php>
</phpunit>
CircleCI 설정
.circleci/config.ymljobs:
phpunit:
parallelism: 4
steps:
- run:
command: |
circleci tests glob "tests/Feature/**/*Test.php" "tests/Unit/**/*Test.php" | circleci tests split --split-by=timings | xargs php ./phpunit-xml-gen.php
php ./vendor/bin/phpunit \
--verbose \
--log-junit tmp/test-reports/phpunit/logfile.xml \
--coverage-clover tmp/coverage-${CIRCLE_NODE_INDEX}.xml \
--configuration phpunit-partial.xml
- store_test_results:
path: tmp/test-reports
- persist_to_workspace:
root: /var/www/html
paths:
- tmp/coverage-*.xml
store_test_results

JUnit XML 형식의 파일을 CircleCI에 저장하도록 설정하면 테스트 파일의 실행 시간으로부터 좋은 느낌으로 각 인스턴스로 나누어 준다고 합니다. 설정하면 위와 같이 Test Summary가 표시됩니다.
PHPUnit의 경우 --log-junit
옵션으로 생성 할 수 있으므로 store_test_results
로 저장하고 테스트 할당 명령 인수에 --split-by=timings
를 전달합니다.
php ./vendor/bin/phpunit \
--log-junit tmp/test-reports/phpunit/logfile.xml # ← これ
circleci tests split --split-by=timings
커버리지

테스트를 실행한 인스턴스 내에서 생성되는 커버리지의 결과는 해당 인스턴스에서 실행한 테스트의 분만 반영됩니다.
Coveralls와 같은 서비스를 사용하는 경우 모든 인스턴스의 테스트 실행이 완료될 때까지 기다려야 합니다.
PHPUnit의 경우 phpunit
를 실행할 때 생성되는 적용 범위의 파일 이름을 인스턴스별로 구분하여 persist_to_workspace
/attach_workspace
에서 좋은 느낌으로 수집하십시오.
php ./vendor/bin/phpunit \
--coverage-clover tmp/coverage-${CIRCLE_NODE_INDEX}.xml # ← これ
.circleci/config.ymljobs:
report:
steps:
- attach_workspace:
at: /var/www/html
- run:
# NOTE: require $COVERALLS_REPO_TOKEN
command: |
php ./vendor/bin/php-coveralls \
--verbose \
--json_path=tmp/coveralls-upload.json \
--coverage_clover=tmp/coverage-*.xml
workflow는 이런 느낌.
.circleci/config.ymlworkflows:
version: 2
build-test-deploy:
jobs:
- build
- phpunit:
requires:
- build
- report:
requires:
- phpunit
참고
jobs:
phpunit:
parallelism: 4
steps:
- run:
command: |
circleci tests glob "tests/Feature/**/*Test.php" "tests/Unit/**/*Test.php" | circleci tests split --split-by=timings | xargs php ./phpunit-xml-gen.php
php ./vendor/bin/phpunit \
--verbose \
--log-junit tmp/test-reports/phpunit/logfile.xml \
--coverage-clover tmp/coverage-${CIRCLE_NODE_INDEX}.xml \
--configuration phpunit-partial.xml
- store_test_results:
path: tmp/test-reports
- persist_to_workspace:
root: /var/www/html
paths:
- tmp/coverage-*.xml
php ./vendor/bin/phpunit \
--log-junit tmp/test-reports/phpunit/logfile.xml # ← これ
circleci tests split --split-by=timings
php ./vendor/bin/phpunit \
--coverage-clover tmp/coverage-${CIRCLE_NODE_INDEX}.xml # ← これ
jobs:
report:
steps:
- attach_workspace:
at: /var/www/html
- run:
# NOTE: require $COVERALLS_REPO_TOKEN
command: |
php ./vendor/bin/php-coveralls \
--verbose \
--json_path=tmp/coveralls-upload.json \
--coverage_clover=tmp/coverage-*.xml
workflows:
version: 2
build-test-deploy:
jobs:
- build
- phpunit:
requires:
- build
- report:
requires:
- phpunit
Reference
이 문제에 관하여(CircleCI에서 PHPUnit 병렬 실행), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/takeru0757/items/2bf3f06e210e450488be텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)