Skip to content

PHP-Parser interferes with testing code that uses (back|for)ward compatibility layers for ext/tokenizer #798

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jrfnl opened this issue Aug 19, 2020 · 17 comments

Comments

@jrfnl
Copy link
Contributor

jrfnl commented Aug 19, 2020

Q A
php-code-coverage version whichever version comes with PHPUnit releases
PHP version PHP 7.3 - 7.4 (confirmed, possibly more)
Driver Xdebug
Xdebug version (if used) 2.9.6
Installation Method BOTH: Composer / PHPUnit PHAR
Usage Method PHPUnit
PHPUnit version (if used) 9.3.x

When running PHPUnit with code coverage enabled the tests for PHPCSUtils and PHPCompatibility have started to semi-randomly break due to PHPUnit's use of PHP-Parser.

PHP-Parser breaks our tests as it interferes with globally defined PHP native constants by backfilling them.

The first few times a defined() for a PHP native token constant is called, the response is correct and as expected, but the third time that same defined() is called, the response will be true, even if the token constant is not defined in our stack and all subsequent tests relying on the defined() logic working will subsequently fail.

Related code in PHP-Parser:

vendor/nikic/php-parser/lib/PhpParser/Lexer.php:        if (!defined('T_NULLSAFE_OBJECT_OPERATOR')) {
vendor/nikic/php-parser/lib/PhpParser/Lexer.php:            \define('T_NULLSAFE_OBJECT_OPERATOR', -8);

Could it be that PHP Parser is loaded too early to prevent interference ?

For an extensive description of the problem, please see: https://gist.github.com/jrfnl/c6fad49bb7580b7b4371af3c68b122f7

Note: while this isn't a problem yet for PHP_CodeSniffer itself at this time as they don't support PHPUnit 9 yet, it will be in the near future. PHPCS itself should also be able to rely on whether or not tokens are defined in PHP to determine how to adjust a tokenized file (if necessary). So, the PHP native tokens being defined by PHP Parser will break coverage builds for PHPCS as well.

With graceful thanks to @derickr for helping me debug this as I initially though it was related to the use of the latest Xdebug version.

@sebastianbergmann
Copy link
Owner

If you use PHPUnit from a PHAR then no autoloading is used and all sourceode files of PHPUnit as well as its dependencies are loading during startup. This is to prevent problems that otherwise may occur when PHPUnit is used from a PHAR in a project that also install PHPUnit via Composer. If you install PHPUnit using Composer then regular, Composer-based autoloading is used.

In theory, we could be loading PHP-Parser too early when the PHAR is used. However, since you also experience the problem when PHPUnit is installed using Composer, I do not believe this to be the case. Furthermore, the code in PHP-Parser that invokes \define('T_NULLSAFE_OBJECT_OPERATOR', -8); is not outside a function or class, meaning it is not automatically run when the sourcecode file that contains it is loaded. So we should be able to rule out "loaded too early" as a cause for this issue.

Maybe @nikic has an idea what might be going on here.

@sebastianbergmann
Copy link
Owner

The first few times a defined() for a PHP native token constant is called, the response is correct and as expected, but the third time that same defined() is called, the response will be true

To clarify: by "[t]he first few times a defined() for a PHP native token constant is called" you mean calls to defined() from your code and by "the third time that same defined() is called" you also mean calls to defined() from your code but after PhpParser\Lexer::defineCompatibilityTokens() has been called. Right? If that is so, then there is no surprise that after PhpParser\Lexer::defineCompatibilityTokens() has been called that a token such as T_NULLSAFE_OBJECT_OPERATOR would exist when it did not exist before. That is the purpose of the PhpParser\Lexer::defineCompatibilityTokens() method.

However, I do not understand why PhpParser\Lexer::defineCompatibilityTokens() is even called by PHP-Parser when emulative lexing is not used.

I will leave this issue open although I do not believe there to be a problem in php-code-coverage. This looks like an issue of competing backward/forward compatibility layers, one in PHP-Parser and one in the code you're testing, Juliette, for dealing with token constants not defined in the version of PHP used.

@jrfnl
Copy link
Contributor Author

jrfnl commented Aug 20, 2020

@sebastianbergmann Thank you for taking a look.

To clarify: by "[t]he first few times a defined() for a PHP native token constant is called" you mean calls to defined() from your code and by "the third time that same defined() is called" you also mean calls to defined() from your code but after PhpParser\Lexer::defineCompatibilityTokens() has been called. Right?

Correct, though I have no idea when or why PhpParser\Lexer::defineCompatibilityTokens() is called, other than that I presume that is the call interfering.

This looks like an issue of competing backward/forward compatibility layers, one in PHP-Parser and one in the code you're testing, Juliette, for dealing with token constants not defined in the version of PHP used.

That's the whole point. How can I still test the (code coverage of the) code relating to the correct functioning of those compatibility layers in my code if the code of the test framework I use interferes ?

I can understand that for visualizing the code coverage, the tokenization of a file is used to determine which lines/tokens are "covered", but I would expect that to be done after my tests have finished running, not while my tests are running, which is what is causing the interference and why I used the loaded too early in the title of the issue.

@sebastianbergmann
Copy link
Owner

That's the whole point. How can I still test the (code coverage of the) code relating to the correct functioning of those compatibility layers in my code if the code of the test framework I use interferes ?

To be honest: I do not know. I understand that this is frustrating, but your use case might be an edge case that we are not able to accomodate.

I think that PHP-Parser is wrong about declaring those constants in PhpParser\Lexer::defineCompatibilityTokens() even if non-emulative lexing is used. But I do not know enough about PHP-Parser's internals to say this with certainty. This is something that probably only @nikic can shine a light on.

I can understand that for visualizing the code coverage, the tokenization of a file is used to determine which lines/tokens are "covered", but I would expect that to be done after my tests have finished running, not while my tests are running

A sourcecode file is processed after it has been "seen" by php-code-coverage for the first time. This processing included parsing it with PHP-Parser. We need to do this to find @codeCoverageIgnore annotations, for instance. This and similar information is needed as early as possible to discard code coverage data that we are not interested in as early as possible to reduce the amount of data that needs to be kept in memory as well as the amount of data that needs to be updated after each test.

@jrfnl
Copy link
Contributor Author

jrfnl commented Aug 20, 2020

For the time being, I've restricted our builds to use PHPUnit 9.2.x for code coverage, that will at least allow us to have passing builds again, so PRs can get merged.

I'll keep my fingers crossed that @nikic will have additional insights once he's back from his vacation.

@nikic If you do read your mail while on holiday: please enjoy your time off, this can wait until you're back.

@sebastianbergmann
Copy link
Owner

@nikic If you do read your mail while on holiday: please enjoy your time off, this can wait until you're back.

Hear, hear.

@sebastianbergmann
Copy link
Owner

@jrfnl Here is an idea you could try: configure the cache for static analysis results (either using the --coverage-cache <directory> CLI option for the PHPUnit test runner or using <coverage cacheDirectory="directory"> in PHPUnit's XML configuration file) and warm the cache using the --warm-coverage-cache CLI option before you run your tests. This should prevent php-code-coverage from running any PHP-Parser code while you're running the tests.

@sebastianbergmann sebastianbergmann changed the title PHP-Parser loaded too early causes userland tests to fail PHP-Parser interferes with testing code that uses (back|for)ward compatibility layers for ext/tokenizer Aug 24, 2020
@jrfnl
Copy link
Contributor Author

jrfnl commented Aug 24, 2020

@sebastianbergmann I'd love to give that a try. Just been trying to find out more information about the options you mention in the PHPUnit documentation, but I can't seem to find anything. Are these options new for a future version ? Or have they just not been added to the documentation yet ?

@sebastianbergmann
Copy link
Owner

Are these options new for a future version ? Or have they just not been added to the documentation yet?

I did not get a chance yet to document these options. They were introduced in PHPUnit 9.3.4: https://github.com/sebastianbergmann/phpunit/blob/master/ChangeLog-9.3.md#934---2020-08-10

@sebastianbergmann
Copy link
Owner

sebastianbergmann commented Aug 24, 2020

I did not get a chance yet to document these options.

I pushed (an initial version of) documentation for these options to the https://github.com/sebastianbergmann/phpunit-documentation-english. However, ReadTheDocs does not build the documentation right now for some reason.

@jrfnl
Copy link
Contributor Author

jrfnl commented Aug 26, 2020

@sebastianbergmann Thanks for doing that! ❤️ I need to finish some other things first, but I'm hoping to be able to sit down with this again towards the end of the week.

@sebastianbergmann
Copy link
Owner

@jrfnl Did you get a chance to try the proposed solution/workaround?

@jrfnl
Copy link
Contributor Author

jrfnl commented Sep 21, 2020

@sebastianbergmann Sorry, I haven't gotten round to it yet. For now, I'm using PHPUnit 9.2 with PHP 7.4 for the code coverage builds, but once PHP 8 comes out I will need to have it working with PHPUnit 9.3+, so it is definitely on my (overly full) to-do list to experiment with the caching options you suggested, just not top-of-the-list priority at this very moment.

@sebastianbergmann
Copy link
Owner

No feedback, closing.

@jrfnl
Copy link
Contributor Author

jrfnl commented Feb 21, 2022

@sebastianbergmann Sorry about this. It's still on my todo list, but hasn't reached the top yet. I'm going to try and reserve time to look into this more deeply in a week or two.

jrfnl added a commit to PHPCSStandards/PHPCSUtils that referenced this issue Apr 11, 2022
As of PHPUnit 9.3, PHPUnit started using PHP-Parser as a basis to calculate code coverage.

The problem with this is that PHP-Parser backfills new PHP native tokens, while the code in this repo contains logic which checks for the existence of tokens using `defined()`. That logic breaks with PHP-Parser in play.

An external PHPCS standard may also be using PHP-Parser, but as Parser doesn't fix the tokenization of files, the tokens polyfilled by PHP-Parser would still cause interference.

To work round this, I'm introducing a `TokenHelper::tokenExists()` method which can distinguish tokens defined by PHP and PHPCS from tokens defined by PHP-Parser.

This should solve the issue in most cases, though in edge-cases, PHP-Parser could still prevent the PHPCS native `Tokenizer\PHP` class from providing polyfills when it should.

For external standards which want to use PHPUnit 9.3+ for calculating code coverage, warming the cache is also still recommended, though it shouldn't necessarily be _needed_ anymore if the standard implements the use of the `TokenHelper::tokenExists()` method in all the appropriate places.

Includes unit tests.

Refs:
* sebastianbergmann/php-code-coverage#798
* https://github.com/nikic/PHP-Parser/blob/master/lib/PhpParser/Lexer.php

Note: while `Helper` would have been the more intuitive name for the class, as there is also a `BackCompat\Helper` class, this would mean use aliases would need to be used a lot, so instead, I've elected to name the class `TokenHelper`.
jrfnl added a commit to PHPCSStandards/PHPCSUtils that referenced this issue Apr 11, 2022
As of PHPUnit 9.3, PHPUnit started using PHP-Parser as a basis to calculate code coverage.

The problem with this is that PHP-Parser backfills new PHP native tokens, while the code in this repo contains logic which checks for the existence of tokens using `defined()`. That logic breaks with PHP-Parser in play.

An external PHPCS standard may also be using PHP-Parser, but as Parser doesn't fix the tokenization of files, the tokens polyfilled by PHP-Parser would still cause interference.

To work round this, I'm introducing a `TokenHelper::tokenExists()` method which can distinguish tokens defined by PHP and PHPCS from tokens defined by PHP-Parser.

This should solve the issue in most cases, though in edge-cases, PHP-Parser could still prevent the PHPCS native `Tokenizer\PHP` class from providing polyfills when it should.

For external standards which want to use PHPUnit 9.3+ for calculating code coverage, warming the cache is also still recommended, though it shouldn't necessarily be _needed_ anymore if the standard implements the use of the `TokenHelper::tokenExists()` method in all the appropriate places.

Includes unit tests.

Refs:
* sebastianbergmann/php-code-coverage#798
* https://github.com/nikic/PHP-Parser/blob/master/lib/PhpParser/Lexer.php

Note: while `Helper` would have been the more intuitive name for the class, as there is also a `BackCompat\Helper` class, this would mean use aliases would need to be used a lot, so instead, I've elected to name the class `TokenHelper`.
jrfnl added a commit to PHPCSStandards/PHPCSUtils that referenced this issue Apr 11, 2022
As of PHPUnit 9.3, PHPUnit started using PHP-Parser as a basis to calculate code coverage. Until now, this prevented this repo from using PHPUnit 9.3 (see PR 304 for more details).

Now the issues related to that have been fixed, the PHPUnit version requirements can be widened again.

This then allows to:
* Remove the tweaking of the PHPUnit version in `test` jobs in GH Actions.
* Run code coverage on the latest PHP version (8.1).

Just in case there would still be residual issues, I'm also implementing cache warming in the code coverage workflow as recommended by Sebastian.

Notes regarding cache-warming
* The `--coverage-cache` and `--warm-coverage-cache` options are available since PHPUnit 9.3.4 and if these are used on older PHPUnit versions, PHPUnit will error out with an "unrecognized CLI argument" error.
* In other words: these options can only be used with PHPUnit 9.3+, which is why the PHPUnit version is checked and remembered and subsequently used in the conditions.
* Also: running PHPUnit with the `--warm-coverage-cache` option _does not run the tests_. It literally only warms the cache, which is why this is implemented as a separate step in the workflow.
* The cache directory can be configured in the `phpunit.xml[.dist]` file, but only when using the PHPUnit 9.3+ `coverage` XML tag.
    As the PHPUnit config used needs to stay cross-version compatible with older PHPUnit versions, the CLI option is used for now.
    If, at some point in the future, two config files would be used (one for PHPUnit < 9.3 and one for PHPUnit >= 9.3), the cache directory could be added to the config instead of passing it on the command-line.

Refs:
* sebastianbergmann/php-code-coverage#798 (comment)
* sebastianbergmann/phpunit@9.3.3...9.3.4
jrfnl added a commit to PHPCSStandards/PHPCSUtils that referenced this issue Apr 11, 2022
As of PHPUnit 9.3, PHPUnit started using PHP-Parser as a basis to calculate code coverage. Until now, this prevented this repo from using PHPUnit 9.3 (see PR 304 for more details).

Now the issues related to that have been fixed, the PHPUnit version requirements can be widened again.

This then allows to:
* Remove the tweaking of the PHPUnit version in `test` jobs in GH Actions.
* Run code coverage on the latest PHP version (8.1).

Just in case there would still be residual issues, I'm also implementing cache warming in the code coverage workflow as recommended by Sebastian.

Notes regarding cache-warming:
* The `--coverage-cache` and `--warm-coverage-cache` options are available since PHPUnit 9.3.4 and if these are used on older PHPUnit versions, PHPUnit will error out with an "unrecognized CLI argument" error.
* In other words: these options can only be used with PHPUnit 9.3+, which is why the PHPUnit version is checked and remembered and subsequently used in the conditions.
* Also: running PHPUnit with the `--warm-coverage-cache` option _does not run the tests_. It literally only warms the cache, which is why this is implemented as a separate step in the workflow.
* The cache directory can be configured in the `phpunit.xml[.dist]` file, but only when using the PHPUnit 9.3+ `coverage` XML tag.
    As the PHPUnit config used needs to stay cross-version compatible with older PHPUnit versions, the CLI option is used for now.
    If, at some point in the future, two config files would be used (one for PHPUnit < 9.3 and one for PHPUnit >= 9.3), the cache directory could be added to the config instead of passing it on the command-line.

Refs:
* sebastianbergmann/php-code-coverage#798 (comment)
* sebastianbergmann/phpunit@9.3.3...9.3.4
jrfnl added a commit to PHPCSStandards/PHPCSUtils that referenced this issue Apr 11, 2022
As of PHPUnit 9.3, PHPUnit started using PHP-Parser as a basis to calculate code coverage. Until now, this prevented this repo from using PHPUnit 9.3 (see PR 304 for more details).

Now the issues related to that have been fixed, the PHPUnit version requirements can be widened again.

This then allows to:
* Remove the tweaking of the PHPUnit version in `test` jobs in GH Actions.
* Run code coverage on the latest PHP version (8.1).

Just in case there would still be residual issues, I'm also implementing cache warming in the code coverage workflow as recommended by Sebastian.

Notes regarding cache-warming:
* The `--coverage-cache` and `--warm-coverage-cache` options are available since PHPUnit 9.3.4 and if these are used on older PHPUnit versions, PHPUnit will error out with an "unrecognized CLI argument" error.
* In other words: these options can only be used with PHPUnit 9.3+, which is why the PHPUnit version is checked and remembered and subsequently used in the conditions.
* Also: running PHPUnit with the `--warm-coverage-cache` option _does not run the tests_. It literally only warms the cache, which is why this is implemented as a separate step in the workflow.
* The cache directory can be configured in the `phpunit.xml[.dist]` file, but only when using the PHPUnit 9.3+ `coverage` XML tag.
    As the PHPUnit config used needs to stay cross-version compatible with older PHPUnit versions, the CLI option is used for now.
    If, at some point in the future, two config files would be used (one for PHPUnit < 9.3 and one for PHPUnit >= 9.3), the cache directory could be added to the config instead of passing it on the command-line.

Refs:
* sebastianbergmann/php-code-coverage#798 (comment)
* sebastianbergmann/phpunit@9.3.3...9.3.4
@jrfnl
Copy link
Contributor Author

jrfnl commented Apr 11, 2022

Okay, so it took a little longer still before I had time to properly work on this and run tests with various scenarios, but I finally got round to it.

I can confirm that using the --warm-coverage-cache option together with the --coverage-cache <directory> option, as suggested above by @sebastianbergmann, works.

In case anyone else comes across this issue and is looking for a code sample on how to implement this in a repo which needs to support multiple versions of PHPUnit, here is a code sample for a working GH Actions workflow:

coverage:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        php: ['5.6', '7.2', '8.1']

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Install PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php }}
          coverage: xdebug

      - name: Install Composer dependencies
        uses: "ramsey/composer-install@v2"

      - name: Grab PHPUnit version
        id: phpunit_version
        run: echo ::set-output name=VERSION::$(vendor/bin/phpunit --version | grep --only-matching --max-count=1 --extended-regexp '\b[0-9]+\.[0-9]+')

      - name: "Warm the PHPUnit cache (PHPUnit 9.3+)"
        if: ${{ steps.phpunit_version.outputs.VERSION >= '9.3' }}
        run: vendor/bin/phpunit --coverage-cache ./build/phpunit-cache --warm-coverage-cache

      - name: "Run the unit tests with code coverage (PHPUnit < 9.3)"
        if: ${{ steps.phpunit_version.outputs.VERSION < '9.3' }}
        run: vendor/bin/phpunit

      - name: "Run the unit tests with code coverage (PHPUnit 9.3+)"
        if: ${{ steps.phpunit_version.outputs.VERSION >= '9.3' }}
        run: vendor/bin/phpunit --coverage-cache ./build/phpunit-cache

Notes:

  • The --coverage-cache and --warm-coverage-cache options are available since PHPUnit 9.3.4 and if these are used on older PHPUnit versions, PHPUnit will error out with an "unrecognized CLI argument" error.
  • In other words: these options can only be used with PHPUnit 9.3+, which is why the PHPUnit version is checked and remembered and subsequently used in the conditions.
  • Also: running PHPUnit with the --warm-coverage-cache option does not run the tests. It literally only warms the cache, which is why this is implemented as a separate step in the workflow.

@sebastianbergmann
Copy link
Owner

Thank you, @jrfnl.

jrfnl added a commit to PHPCompatibility/PHPCompatibility that referenced this issue Oct 7, 2022
As of PHPUnit 9.3, PHPUnit started using PHP-Parser as a basis to calculate code coverage. This prevented this repo from using PHPUnit 9.3 (see PR PHPCSStandards/PHPCSUtils 304 for more details) as PHP Parser also backfills tokens and that interfered with the sniffs.

Now support for PHPCS < 3.7.1 has been dropped though, all tokens should exist in PHPCS.
And if in the future we would need to do "does this token exist ?" checks again, PHPCSUtils will provide a `TokenHelper::tokenExists()` method (as of version 1.0.0-alpha4), which will allow us to distinguish between tokens backfilled by PHPCS and tokens backfilled by PHP-Parser.

PHPUnit itself has also added a new feature in PHPUnit 9.3.4 to warm the code cache ahead of running tests recording code coverage. Using that feature should prevent the token interference completely, but implementing it was a bit of an experiment as the feature is barely documented.

Either way, the combination of the above, allows us to:
* Remove the tweaking of the PHPUnit version in `test` jobs in GH Actions.
* Run code coverage on the latest PHP version (8.1).

Notes regarding cache-warming:
* The `--coverage-cache` and `--warm-coverage-cache` options are available since PHPUnit 9.3.4 and if these are used on older PHPUnit versions, PHPUnit will error out with an "unrecognized CLI argument" error.
* In other words: these options can only be used with PHPUnit 9.3+, which is why the PHPUnit version is checked and remembered and subsequently used in the conditions.
* Also: running PHPUnit with the `--warm-coverage-cache` option _does not run the tests_. It literally only warms the cache, which is why this is implemented as a separate step in the workflow.
* The cache directory can be configured in the `phpunit.xml[.dist]` file, but only when using the PHPUnit 9.3+ `coverage` XML tag.
    As the PHPUnit config used by PHPCompatibility needs to stay cross-version compatible with older PHPUnit versions, the CLI option is used for now.
    If, at some point in the future, two config files would be used (one for PHPUnit < 9.3 and one for PHPUnit >= 9.3), the cache directory could be added to the config instead of passing it on the command-line.

Refs:
* sebastianbergmann/php-code-coverage#798 (comment)
* sebastianbergmann/phpunit@9.3.3...9.3.4
jrfnl added a commit to PHPCSStandards/PHP_CodeSniffer that referenced this issue Jan 10, 2024
As of PHPUnit 9.3, PHPUnit started using PHP-Parser as a basis to calculate code coverage. PHP Parser also polyfills tokens and that can interfere with the sniffs, but also with the code coverage runs.

PHPUnit has also added a new feature in PHPUnit 9.3.4 to warm the code cache ahead of running tests recording code coverage. Using that feature should prevent the token interference.

Notes regarding cache-warming:
* The `--coverage-cache` and `--warm-coverage-cache` options are available since PHPUnit 9.3.4 and if these are used on older PHPUnit versions, PHPUnit will error out with an "unrecognized CLI argument" error.
* In other words: these options can only be used with PHPUnit 9.3+, which is why the PHPUnit version is checked and remembered and subsequently used in the conditions.
* Also: running PHPUnit with the `--warm-coverage-cache` option _does not run the tests_. It literally only warms the cache, which is why this is implemented as a separate step in the workflow.
* The cache directory can be configured in the `phpunit.xml[.dist]` file, but only when using the PHPUnit 9.3+ `coverage` XML tag.
    As the PHPUnit config used needs to stay cross-version compatible with older PHPUnit versions, the CLI option is used for now.

Refs:
* sebastianbergmann/php-code-coverage#798 (comment)
* sebastianbergmann/phpunit@9.3.3...9.3.4
jrfnl added a commit to PHPCSStandards/PHP_CodeSniffer that referenced this issue Jan 10, 2024
As of PHPUnit 9.3, PHPUnit started using PHP-Parser as a basis to calculate code coverage. PHP Parser also polyfills tokens and that can interfere with the sniffs, but also with the code coverage runs.

PHPUnit has also added a new feature in PHPUnit 9.3.4 to warm the code cache ahead of running tests recording code coverage. Using that feature should prevent the token interference.

Notes regarding cache-warming:
* The `--coverage-cache` and `--warm-coverage-cache` options are available since PHPUnit 9.3.4 and if these are used on older PHPUnit versions, PHPUnit will error out with an "unrecognized CLI argument" error.
* In other words: these options can only be used with PHPUnit 9.3+, which is why the PHPUnit version is checked and remembered and subsequently used in the conditions.
* Also: running PHPUnit with the `--warm-coverage-cache` option _does not run the tests_. It literally only warms the cache, which is why this is implemented as a separate step in the workflow.
* The cache directory can be configured in the `phpunit.xml[.dist]` file, but only when using the PHPUnit 9.3+ `coverage` XML tag.
    As the PHPUnit config used needs to stay cross-version compatible with older PHPUnit versions, the CLI option is used for now.

Refs:
* sebastianbergmann/php-code-coverage#798 (comment)
* sebastianbergmann/phpunit@9.3.3...9.3.4
jrfnl added a commit to PHPCSStandards/PHP_CodeSniffer that referenced this issue Jan 10, 2024
As of PHPUnit 9.3, PHPUnit started using PHP-Parser as a basis to calculate code coverage. PHP Parser also polyfills tokens and that can interfere with the sniffs, but also with the code coverage runs.

PHPUnit has also added a new feature in PHPUnit 9.3.4 to warm the code cache ahead of running tests recording code coverage. Using that feature should prevent the token interference.

Notes regarding cache-warming:
* The `--coverage-cache` and `--warm-coverage-cache` options are available since PHPUnit 9.3.4 and if these are used on older PHPUnit versions, PHPUnit will error out with an "unrecognized CLI argument" error.
* In other words: these options can only be used with PHPUnit 9.3+, which is why the PHPUnit version is checked and remembered and subsequently used in the conditions.
* Also: running PHPUnit with the `--warm-coverage-cache` option _does not run the tests_. It literally only warms the cache, which is why this is implemented as a separate step in the workflow.
* The cache directory can be configured in the `phpunit.xml[.dist]` file, but only when using the PHPUnit 9.3+ `coverage` XML tag.
    As the PHPUnit config used needs to stay cross-version compatible with older PHPUnit versions, the CLI option is used for now.

Refs:
* sebastianbergmann/php-code-coverage#798 (comment)
* sebastianbergmann/phpunit@9.3.3...9.3.4
jrfnl added a commit to PHPCSStandards/PHP_CodeSniffer that referenced this issue Jan 10, 2024
As of PHPUnit 9.3, PHPUnit started using PHP-Parser as a basis to calculate code coverage. PHP Parser also polyfills tokens and that can interfere with the sniffs, but only in code coverage runs.

In PHPUnit 9.3.4 a new feature was added to warm the code cache ahead of running tests recording code coverage. Using that feature should prevent the token interference.

So far, I've not seen problems with this for this codebase, but better safe than sorry, so I'm going to enable cache warming now anyway.

Notes regarding cache-warming:
* The `--coverage-cache` and `--warm-coverage-cache` options are available since PHPUnit 9.3.4 and if these are used on older PHPUnit versions, PHPUnit will error out with an "unrecognized CLI argument" error.
* In other words: these options can only be used with PHPUnit 9.3+, which is why the PHPUnit version is checked and remembered and subsequently used in the conditions.
* Also: running PHPUnit with the `--warm-coverage-cache` option _does not run the tests_. It literally only warms the cache, which is why this is implemented as a separate step in the workflow.
* The cache directory can be configured in the `phpunit.xml[.dist]` file, but only when using the PHPUnit 9.3+ `coverage` XML tag.
    As the PHPUnit config used needs to stay cross-version compatible with older PHPUnit versions, the CLI option is used for now.

Refs:
* sebastianbergmann/php-code-coverage#798 (comment)
* sebastianbergmann/phpunit@9.3.3...9.3.4

Also note that PHP-Parser 5.0 was released a couple of days ago and when used for code coverage runs on PHP 8.0 (as used for the 4.0 branch), this causes problems.

When I merge this commit up to 4.0, I will adjust the GH Actions script for the 4.0 branch to use PHP 8.1 instead of PHP 8.0 to avoid this issue.

The issue has been reported upstream: sebastianbergmann/php-code-coverage#1025
jrfnl added a commit to PHPCSStandards/PHP_CodeSniffer that referenced this issue Jan 10, 2024
As of PHPUnit 9.3, PHPUnit started using PHP-Parser as a basis to calculate code coverage. PHP Parser also polyfills tokens and that can interfere with the sniffs, but only in code coverage runs.

In PHPUnit 9.3.4 a new feature was added to warm the code cache ahead of running tests recording code coverage. Using that feature should prevent the token interference.

So far, I've not seen problems with this for this codebase, but better safe than sorry, so I'm going to enable cache warming now anyway.

Notes regarding cache-warming:
* The `--coverage-cache` and `--warm-coverage-cache` options are available since PHPUnit 9.3.4 and if these are used on older PHPUnit versions, PHPUnit will error out with an "unrecognized CLI argument" error.
* In other words: these options can only be used with PHPUnit 9.3+, which is why the PHPUnit version is checked and remembered and subsequently used in the conditions.
* Also: running PHPUnit with the `--warm-coverage-cache` option _does not run the tests_. It literally only warms the cache, which is why this is implemented as a separate step in the workflow.
* The cache directory can be configured in the `phpunit.xml[.dist]` file, but only when using the PHPUnit 9.3+ `coverage` XML tag.
    As the PHPUnit config used needs to stay cross-version compatible with older PHPUnit versions, the CLI option is used for now.

Refs:
* sebastianbergmann/php-code-coverage#798 (comment)
* sebastianbergmann/phpunit@9.3.3...9.3.4

Also note that PHP-Parser 5.0 was released a couple of days ago and when used for code coverage runs on PHP 8.0 (as used for the 4.0 branch), this causes problems.

When I merge this commit up to 4.0, I will adjust the GH Actions script for the 4.0 branch to use PHP 8.1 instead of PHP 8.0 to avoid this issue.

The issue has been reported upstream: sebastianbergmann/php-code-coverage#1025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants