Skip to content

bug(testFramework): PHPUnit adapter mis-parses test framework options #3138

@theofidry

Description

@theofidry
Question Answer
Infection version 0.32.7
Test Framework version All
CI either
PHP version any
Platform any
Github Repo https://github.com/infection/infection

While expanding PHPUnit adapter command-line scenario coverage in #3133, several broken or ambiguous transformations were identified.

The affected input is testFrameworkOptions from infection.json5, or the equivalent --test-framework-options CLI option. The same parsing path is used when building both the initial PHPUnit command and mutant PHPUnit commands.

This issue may also affect the other test framework adapters.

Current behaviour

Examples from PR #3133:

  • Short PHPUnit options are rewritten as long options: -v becomes --v.
  • Space-separated option values are kept as a single raw token: --filter "a test with spaces" becomes one token containing the quotes, rather than --filter plus a test with spaces.
  • Quoted values keep their shell quotes: --filter="a test with spaces" still contains the quote characters in the generated argv token.
  • Option values containing -- are split as if the value introduced a new option: --filter="a test -- with option-like text" --group=default is split inside the filter value.
  • Positional PHPUnit arguments are rewritten as long options: tests/FooTest.php --filter=Foo becomes --tests/FooTest.php --filter=Foo.
  • Quoted positional arguments have both problems: "tests/Foo Test.php" becomes --"tests/Foo Test.php".
  • User-provided filters are not detected consistently when Infection also generates class-to-test filters: --filter Foo and --filter=Foo do not prevent the generated --filter FooTest|BazTest from being appended.
  • Repeated spaces are preserved in option tokens: --group=default --filter=Foo leaves a trailing space on the --group token.
  • Tabs and newlines are not treated as argument separators: --group=default\t--filter=Foo and --group=default\n--filter=Foo remain single tokens.
  • Other options with separated values have the same issue, for example, --testsuite "Unit Tests" and --configuration custom-phpunit.xml.

Expected behaviour

Infection should preserve the user-provided PHPUnit command-line semantics when building PHPUnit command arrays:

  • short options remain short options;
  • quoted values are parsed into argv values without shell quote characters;
  • option-like text inside quoted values is preserved as value text;
  • positional PHPUnit arguments remain positional arguments;
  • whitespace between arguments is handled like normal command-line whitespace;
  • user-provided --filter options are recognised with either --filter value or --filter=value spelling, so Infection does not append a second generated filter.

Reproduction

The scenarios are covered in PR #3133 in:

  • tests/phpunit/TestFramework/PhpUnit/Adapter/PhpUnitAdapter/PhpUnitAdapterTest.php
  • tests/phpunit/TestFramework/PhpUnit/Adapter/PhpUnitAdapter/InitialTestRunScenario.php
  • tests/phpunit/TestFramework/PhpUnit/Adapter/PhpUnitAdapter/MutantCommandLineScenario.php

Minimal example:

{
    "source": {
        "directories": ["src"]
    },
    "testFramework": "phpunit",
    "testFrameworkOptions": "--filter \"a test -- with option-like text\" --group=default"
}

Equivalent CLI example:

vendor/bin/infection --test-framework-options='--filter "a test -- with option-like text" --group=default'

Related

infection.json5
{
    "source": {
        "directories": ["src"]
    },
    "testFramework": "phpunit",
    "testFrameworkOptions": "--filter \"a test -- with option-like text\" --group=default"
}
phpunit.xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit/>

Metadata

Metadata

Assignees

Type

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions