diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 0ae0b5c4cb..f4de0fb2b9 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -196,6 +196,65 @@ jobs:
- name: Run tests with PHPUnit
run: php ./phpunit --testsuite end-to-end --order-by depends,random
+ end-to-end-tests-with-coverage-driver:
+ name: End-to-End Tests with Coverage Driver
+
+ needs:
+ - unit-tests
+
+ runs-on: ${{ matrix.os }}
+ timeout-minutes: 5
+
+ env:
+ PHP_EXTENSIONS: none, ctype, curl, dom, json, libxml, mbstring, openssl, pdo, phar, tokenizer, xml, xmlwriter
+ PHP_INI_VALUES: zend.assertions=1, error_reporting=-1, log_errors_max_len=0, display_errors=On
+
+ strategy:
+ fail-fast: false
+ matrix:
+ os:
+ - ubuntu-latest
+ - windows-latest
+
+ php-version:
+ - "8.3"
+ - "8.4"
+ - "8.5"
+
+ steps:
+ - name: Configure Git to avoid issues with line endings
+ if: matrix.os == 'windows-latest'
+ run: git config --global core.autocrlf false
+
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ ref: ${{ github.event.pull_request.head.sha || github.sha }}
+
+ - name: Use local branch
+ shell: bash
+ run: |
+ BRANCH=$([ "${{ github.event_name }}" == "pull_request" ] && echo "${{ github.head_ref }}" || echo "${{ github.ref_name }}")
+ git branch -D $BRANCH 2>/dev/null || true
+ git branch $BRANCH HEAD
+ git checkout $BRANCH
+
+ - name: Install PHP with extensions
+ uses: shivammathur/setup-php@v2
+ with:
+ coverage: xdebug
+ php-version: ${{ matrix.php-version }}
+ extensions: ${{ env.PHP_EXTENSIONS }}
+ ini-values: ${{ env.PHP_INI_VALUES }}
+ tools: none
+
+ - name: Install dependencies with Composer
+ run: php ./tools/composer install --no-ansi --no-interaction --no-progress
+
+ - name: Run tests with PHPUnit
+ run: php ./phpunit --testsuite end-to-end-with-coverage-driver --order-by depends,random
+
code-coverage:
name: Code Coverage
@@ -203,6 +262,7 @@ jobs:
needs:
- end-to-end-tests
+ - end-to-end-tests-with-coverage-driver
runs-on: ubuntu-latest
timeout-minutes: 10
diff --git a/phpunit.xml b/phpunit.xml
index 9d543c2e8f..8702c8c6df 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -47,6 +47,10 @@
tests/end-to-end/self-direct-indirect/_files
tests/end-to-end/testdox/_files
+
+
+ tests/end-to-end-with-coverage-driver/warn-when-opcache-enabled
+
diff --git a/src/Runner/CodeCoverage.php b/src/Runner/CodeCoverage.php
index e84a5fc5fb..1576151f1a 100644
--- a/src/Runner/CodeCoverage.php
+++ b/src/Runner/CodeCoverage.php
@@ -40,6 +40,7 @@
use SebastianBergmann\CodeCoverage\Test\TestSize\TestSize;
use SebastianBergmann\CodeCoverage\Test\TestStatus\TestStatus;
use SebastianBergmann\Comparator\Comparator;
+use SebastianBergmann\Environment\Runtime;
use SebastianBergmann\Timer\NoActiveTimerException;
use SebastianBergmann\Timer\Timer;
@@ -124,6 +125,14 @@ public function init(Configuration $configuration, CodeCoverageFilterRegistry $c
$this->codeCoverage()->excludeUncoveredFiles();
}
+ $runtime = new Runtime;
+
+ if ($runtime->isOpcacheActive()) {
+ EventFacade::emitter()->testRunnerTriggeredPhpunitWarning(
+ 'Code coverage might produce unreliable results when OPCache is enabled',
+ );
+ }
+
if ($codeCoverageFilterRegistry->get()->isEmpty()) {
if (!$codeCoverageFilterRegistry->configured()) {
EventFacade::emitter()->testRunnerTriggeredPhpunitWarning(
diff --git a/tests/end-to-end-with-coverage-driver/warn-when-opcache-enabled/src/Greeter.php b/tests/end-to-end-with-coverage-driver/warn-when-opcache-enabled/src/Greeter.php
new file mode 100644
index 0000000000..081835d281
--- /dev/null
+++ b/tests/end-to-end-with-coverage-driver/warn-when-opcache-enabled/src/Greeter.php
@@ -0,0 +1,18 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TestFixture\CoverageWithOpcacheEnabled;
+
+final class Greeter
+{
+ public function greet(): string
+ {
+ return 'Hello world!';
+ }
+}
diff --git a/tests/end-to-end-with-coverage-driver/warn-when-opcache-enabled/src/autoload.php b/tests/end-to-end-with-coverage-driver/warn-when-opcache-enabled/src/autoload.php
new file mode 100644
index 0000000000..c66cf5e50f
--- /dev/null
+++ b/tests/end-to-end-with-coverage-driver/warn-when-opcache-enabled/src/autoload.php
@@ -0,0 +1,11 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+require_once __DIR__ . '/Greeter.php';
diff --git a/tests/end-to-end-with-coverage-driver/warn-when-opcache-enabled/tests/GreeterTest.php b/tests/end-to-end-with-coverage-driver/warn-when-opcache-enabled/tests/GreeterTest.php
new file mode 100644
index 0000000000..c17d46abe6
--- /dev/null
+++ b/tests/end-to-end-with-coverage-driver/warn-when-opcache-enabled/tests/GreeterTest.php
@@ -0,0 +1,25 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace PHPUnit\TestFixture\CoverageWithOpcacheEnabled;
+
+use PHPUnit\Framework\Attributes\CoversClass;
+use PHPUnit\Framework\Attributes\RunInSeparateProcess;
+use PHPUnit\Framework\Attributes\Ticket;
+use PHPUnit\Framework\TestCase;
+
+#[CoversClass(Greeter::class)]
+final class GreeterTest extends TestCase
+{
+ public function testGreets(): void
+ {
+ $this->assertSame('Hello world!', (new Greeter)->greet());
+ }
+
+}
diff --git a/tests/end-to-end-with-coverage-driver/warn-when-opcache-enabled/warn-when-opcache-enabled.phpt b/tests/end-to-end-with-coverage-driver/warn-when-opcache-enabled/warn-when-opcache-enabled.phpt
new file mode 100644
index 0000000000..df3eb2cd53
--- /dev/null
+++ b/tests/end-to-end-with-coverage-driver/warn-when-opcache-enabled/warn-when-opcache-enabled.phpt
@@ -0,0 +1,42 @@
+--TEST--
+https://github.com/sebastianbergmann/php-code-coverage/issues/1022
+--INI--
+opcache.enable_cli=1
+opcache.jit=disable
+--ENV--
+XDEBUG_MODE=coverage
+--SKIPIF--
+run($_SERVER['argv']);
+--EXPECTF--
+PHPUnit %s by Sebastian Bergmann and contributors.
+
+Runtime: %s
+Configuration: %s
+
+. 1 / 1 (100%)
+
+Time: %s, Memory: %s MB
+
+There was 1 PHPUnit test runner warning:
+
+1) Code coverage might produce unreliable results when OPCache is enabled
+%A