Skip to content
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

Adds --passthru and --passthru-php options. Adds --verbose option. #361

Merged
merged 4 commits into from Jan 25, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
101 changes: 60 additions & 41 deletions README.md
Expand Up @@ -40,39 +40,43 @@ After installation, the binary can be found at `vendor/bin/paratest`. Usage is a

```
Usage:
paratest [-p|--processes="..."] [-f|--functional] [--no-test-tokens] [-h|--help] [--coverage-clover="..."] [--coverage-html="..."] [--coverage-php="..."] [-m|--max-batch-size="..."] [--filter="..."] [--phpunit="..."] [--runner="..."] [--bootstrap="..."] [-c|--configuration="..."] [-g|--group="..."] [--exclude-group="..."] [--stop-on-failure] [--log-junit="..."] [--colors] [--testsuite[="..."]] [--path="..."] [path]
paratest [-p|--processes PROCESSES] [-f|--functional] [--no-test-tokens] [-h|--help] [--coverage-clover COVERAGE-CLOVER] [--coverage-html COVERAGE-HTML] [--coverage-php COVERAGE-PHP] [--coverage-text] [--coverage-xml COVERAGE-XML] [-m|--max-batch-size MAX-BATCH-SIZE] [--filter FILTER] [--parallel-suite] [--passthru PASSTHRU] [--passthru-php PASSTHRU-PHP] [-v|--verbose VERBOSE] [--whitelist WHITELIST] [--phpunit PHPUNIT] [--runner RUNNER] [--bootstrap BOOTSTRAP] [-c|--configuration CONFIGURATION] [-g|--group GROUP] [--exclude-group EXCLUDE-GROUP] [--stop-on-failure] [--log-junit LOG-JUNIT] [--colors] [--testsuite [TESTSUITE]] [--path PATH] [--] [<path>]

Arguments:
path The path to a directory or file containing tests. (default: current directory)

Options:
--processes (-p) The number of test processes to run. (Default: auto)
Possible values:
- Integer (>= 1): Number of processes to run.
- auto (default): Number of processes is automatically set to the number of logical CPU cores.
- half: Number of processes is automatically set to half the number of logical CPU cores.
--functional (-f) Run methods instead of suites in separate processes.
--no-test-tokens Disable TEST_TOKEN environment variables. (Default: Variable is set)
--help (-h) Display this help message.
--coverage-clover Generate code coverage report in Clover XML format.
--coverage-html Generate code coverage report in HTML format.
--coverage-php Serialize PHP_CodeCoverage object to file.
--coverage-text Generate code coverage report in text format.
--coverage-xml Generate code coverage report in PHPUnit XML format.
--max-batch-size (-m) Max batch size (only for functional mode). (Default: 0)
--filter Filter (only for functional mode).
--phpunit The PHPUnit binary to execute. (Default: vendor/bin/phpunit)
--runner Runner, WrapperRunner or SqliteRunner. (Default: Runner)
--bootstrap The bootstrap file to be used by PHPUnit.
--configuration (-c) The PHPUnit configuration file to use.
--group (-g) Only runs tests from the specified group(s).
--exclude-group Don't run tests from the specified group(s).
--stop-on-failure Don't start any more processes after a failure.
--log-junit Log test execution in JUnit XML format to file.
--colors Displays a colored bar as a test result.
--testsuite Filter which testsuite to run.
--path An alias for the path argument.
--parallel-suite Run testsuites in parallel as opposed to running test classes / test functions in parallel.
path The path to a directory or file containing tests. (default: current directory)

Options:
--processes (-p) The number of test processes to run. (Default: auto)
Possible values:
- Integer (>= 1): Number of processes to run.
- auto (default): Number of processes is automatically set to the number of logical CPU cores.
- half: Number of processes is automatically set to half the number of logical CPU cores.
--functional (-f) Run methods instead of suites in separate processes.
--no-test-tokens Disable TEST_TOKEN environment variables. (Default: Variable is set)
--help (-h) Display this help message.
--coverage-clover Generate code coverage report in Clover XML format.
--coverage-html Generate code coverage report in HTML format.
--coverage-php Serialize PHP_CodeCoverage object to file.
--coverage-text Generate code coverage report in text format.
--coverage-xml Generate code coverage report in PHPUnit XML format.
--max-batch-size (-m) Max batch size (only for functional mode). (Default: 0)
--filter Filter (only for functional mode).
--phpunit The PHPUnit binary to execute. (Default: vendor/bin/phpunit)
--runner Runner, WrapperRunner or SqliteRunner. (Default: Runner)
--bootstrap The bootstrap file to be used by PHPUnit.
--configuration (-c) The PHPUnit configuration file to use.
--group (-g) Only runs tests from the specified group(s).
--exclude-group Don't run tests from the specified group(s).
--stop-on-failure Don't start any more processes after a failure.
--log-junit Log test execution in JUnit XML format to file.
--colors Displays a colored bar as a test result.
--testsuite Filter which testsuite to run. Run multiple suits by separating them with ",". Example: --testsuite suite1,suite2
--path An alias for the path argument.
--parallel-suite Run testsuites in parallel as opposed to running test classes / test functions in parallel.
--passthru=PASSTHRU Pass the given arguments verbatim to the underlying test framework. Example: --passthru="'--prepend' 'xdebug-filter.php'"
--passthru-php=PASSTHRU-PHP Pass the given arguments verbatim to the underlying php process. Example: --passthru-php="'-d' 'zend_extension=xdebug.so'"
-v, --verbose=VERBOSE If given, debug output is printed. Example: --verbose=1

```

### Optimizing Speed ###
Expand Down Expand Up @@ -190,22 +194,37 @@ For Contributors: Testing paratest itself

ParaTest's test suite depends on PHPUnit being installed via composer. Make sure you run `composer install` after cloning.

**Note that The `display_errors` php.ini directive must be set to `stderr` to run
the test suite.**
**Note that The `display_errors` php.ini directive must be set to `stderr` to run the test suite.**

You can use composer scripts for convenient access to style checks and tests. Run `compose run-script -l` to list the
available commands:

````
composer run-script -l
scripts:
style Run style checks (only dry run - no fixing!)
style-fix Run style checks and fix violations
test Run all tests
test-unit Run only unit tests
test-functional Run only functional tests
test-paratest Run all tests with paratest itself
````

To run unit tests:
`vendor/bin/phpunit test/unit`
`composer test-unit` OR `vendor/bin/phpunit test/unit`

To run functional tests:
`vendor/bin/phpunit test/functional`
`composer test-functional` OR `vendor/bin/phpunit test/functional`

You can run all tests at once by running phpunit from the project directory:
`composer test` OR `vendor/bin/phpunit`

You can run all tests at once by running phpunit from the project directory.
`vendor/bin/phpunit`
ParaTest can run its own test suite by running it from the `bin` directory:
`composer test` OR `bin/paratest`

ParaTest can run its own test suite by running it from the `bin` directory.
`bin/paratest`
Before creating a Pull Request be sure to run the style checks and commit the eventual changes:
`composer style-fix` OR `vendor/bin/php-cs-fixer fix`

Before creating a Pull Request be sure to run `vendor/bin/php-cs-fixer fix` and
commit the eventual changes.
Use `composer style` to only show violations without fixing.

For an example of ParaTest out in the wild check out the [example](https://github.com/brianium/paratest-selenium).
28 changes: 28 additions & 0 deletions composer.json
Expand Up @@ -42,5 +42,33 @@
"psr-4": {
"ParaTest\\": "test/unit/"
}
},
"scripts": {
"style": [
"php-cs-fixer fix --dry-run --verbose"
],
"style-fix": [
"php-cs-fixer fix"
],
"test": [
"phpunit"
],
"test-unit": [
"phpunit test/unit"
],
"test-functional": [
"phpunit test/functional"
],
"test-paratest": [
"bin/paratest"
]
},
"scripts-descriptions": {
"style": "Run style checks (only dry run - no fixing!)",
"style-fix": "Run style checks and fix violations",
"test": "Run all tests",
"test-unit": "Run only unit tests",
"test-functional": "Run only functional tests",
"test-paratest": "Run all tests with paratest itself"
}
}
7 changes: 5 additions & 2 deletions src/Console/Commands/ParaTestCommand.php
Expand Up @@ -39,7 +39,7 @@ public static function isWhitelistSupported(): bool
protected function configure()
{
$this
->addOption('processes', 'p', InputOption::VALUE_REQUIRED, 'The number of test processes to run.', 5)
->addOption('processes', 'p', InputOption::VALUE_REQUIRED, 'The number of test processes to run.', 'auto')
->addOption('functional', 'f', InputOption::VALUE_NONE, 'Run methods instead of suites in separate processes.')
->addOption('no-test-tokens', null, InputOption::VALUE_NONE, 'Disable TEST_TOKEN environment variables. <comment>(default: variable is set)</comment>')
->addOption('help', 'h', InputOption::VALUE_NONE, 'Display this help message.')
Expand All @@ -50,7 +50,10 @@ protected function configure()
->addOption('coverage-xml', null, InputOption::VALUE_REQUIRED, 'Generate code coverage report in PHPUnit XML format.')
->addOption('max-batch-size', 'm', InputOption::VALUE_REQUIRED, 'Max batch size (only for functional mode).', 0)
->addOption('filter', null, InputOption::VALUE_REQUIRED, 'Filter (only for functional mode).')
->addOption('parallel-suite', null, InputOption::VALUE_NONE, 'Run the suites of the config in parallel.');
->addOption('parallel-suite', null, InputOption::VALUE_NONE, 'Run the suites of the config in parallel.')
->addOption('passthru', null, InputOption::VALUE_REQUIRED, 'Pass the given arguments verbatim to the underlying test framework. Example: --passthru="\'--prepend\' \'xdebug-filter.php\'"')
->addOption('passthru-php', null, InputOption::VALUE_REQUIRED, 'Pass the given arguments verbatim to the underlying php process. Example: --passthru-php="\'-d\' \'zend_extension=xdebug.so\'"')
->addOption('verbose', 'v', InputOption::VALUE_REQUIRED, 'If given, debug output is printed. Example: --verbose=1');

if (self::isWhitelistSupported()) {
$this->addOption('whitelist', null, InputOption::VALUE_REQUIRED, 'Directory to add to the coverage whitelist.');
Expand Down
10 changes: 8 additions & 2 deletions src/Console/Testers/PHPUnit.php
Expand Up @@ -8,6 +8,7 @@
use ParaTest\Runners\PHPUnit\BaseRunner;
use ParaTest\Runners\PHPUnit\Configuration;
use ParaTest\Runners\PHPUnit\Runner;
use ParaTest\Util\Str;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
Expand Down Expand Up @@ -46,7 +47,8 @@ public function configure(Command $command)
->addOption('colors', null, InputOption::VALUE_NONE, 'Displays a colored bar as a test result.')
->addOption('testsuite', null, InputOption::VALUE_OPTIONAL, 'Filter which testsuite to run')
->addArgument('path', InputArgument::OPTIONAL, 'The path to a directory or file containing tests. <comment>(default: current directory)</comment>')
->addOption('path', null, InputOption::VALUE_REQUIRED, 'An alias for the path argument.');
->addOption('path', null, InputOption::VALUE_REQUIRED, 'An alias for the path argument.')
;
$this->command = $command;
}

Expand Down Expand Up @@ -107,7 +109,7 @@ protected function hasConfig(InputInterface $input): bool
*/
protected function getConfig(InputInterface $input)
{
$cwd = getcwd() . DIRECTORY_SEPARATOR;
$cwd = getcwd() . \DIRECTORY_SEPARATOR;

if ($input->getOption('configuration')) {
$configFilename = $input->getOption('configuration');
Expand Down Expand Up @@ -144,6 +146,10 @@ public function getRunnerOptions(InputInterface $input): array
$options = array_merge(['path' => $path], $options);
}

if (array_key_exists('testsuite', $options)) {
$options['testsuite'] = Str::explodeWithCleanup(Configuration::TEST_SUITE_FILTER_SEPARATOR, $options['testsuite']);
}

return $options;
}

Expand Down
4 changes: 2 additions & 2 deletions src/Console/VersionProvider.php
Expand Up @@ -64,12 +64,12 @@ public function getComposerInstalledVersion($package)
}

$struct = json_decode($result, true, 16);
if (!is_array($struct)) {
if (!\is_array($struct)) {
return;
}

foreach ($struct as $entry) {
if (!is_array($entry)) {
if (!\is_array($entry)) {
continue;
}
$name = $entry['name'] ?? null;
Expand Down
2 changes: 1 addition & 1 deletion src/Coverage/CoverageMerger.php
Expand Up @@ -61,7 +61,7 @@ public function addCoverageFromFile(string $coverageFile = null)
if (0 === $file->getSize()) {
$extra = 'This means a PHPUnit process has crashed.';

if (!function_exists('xdebug_get_code_coverage')) {
if (!\function_exists('xdebug_get_code_coverage')) {
$extra = 'Xdebug is disabled! Enable for coverage.';
}

Expand Down
12 changes: 6 additions & 6 deletions src/Logging/JUnit/Reader.php
Expand Up @@ -174,14 +174,14 @@ protected function caseNodesToSuiteProperties(array $nodeArray, array &$testCase
$cb = [TestCase::class, 'caseFromNode'];

return array_reduce($nodeArray, function ($result, $c) use (&$testCases, $cb) {
$testCases[] = call_user_func_array($cb, [$c]);
$testCases[] = \call_user_func_array($cb, [$c]);
$result['name'] = (string) $c['class'];
$result['file'] = (string) $c['file'];
$result['tests'] += 1;
++$result['tests'];
$result['assertions'] += (int) $c['assertions'];
$result['failures'] += count($c->xpath('failure'));
$result['errors'] += count($c->xpath('error'));
$result['skipped'] += count($c->xpath('skipped'));
$result['failures'] += \count($c->xpath('failure'));
$result['errors'] += \count($c->xpath('error'));
$result['skipped'] += \count($c->xpath('skipped'));
$result['time'] += (float) $c['time'];

return $result;
Expand Down Expand Up @@ -217,7 +217,7 @@ protected function getCaseNodes(): array
protected function initSuite()
{
$suiteNodes = $this->xml->xpath('/testsuites/testsuite/testsuite');
$this->isSingle = count($suiteNodes) === 0;
$this->isSingle = \count($suiteNodes) === 0;
$node = current($this->xml->xpath('/testsuites/testsuite'));

if ($node !== false) {
Expand Down
2 changes: 1 addition & 1 deletion src/Logging/JUnit/Writer.php
Expand Up @@ -181,7 +181,7 @@ protected function getSuiteRoot(array $suites): \DOMElement
{
$testsuites = $this->document->createElement('testsuites');
$this->document->appendChild($testsuites);
if (count($suites) === 1) {
if (\count($suites) === 1) {
return $testsuites;
}
$rootSuite = $this->document->createElement('testsuite');
Expand Down
8 changes: 4 additions & 4 deletions src/Logging/LogInterpreter.php
Expand Up @@ -124,11 +124,11 @@ public function flattenCases(): array
$dict[$case->file] = new TestSuite($case->class, 0, 0, 0, 0, 0, 0);
}
$dict[$case->file]->cases[] = $case;
$dict[$case->file]->tests += 1;
++$dict[$case->file]->tests;
$dict[$case->file]->assertions += $case->assertions;
$dict[$case->file]->failures += count($case->failures);
$dict[$case->file]->errors += count($case->errors);
$dict[$case->file]->skipped += count($case->skipped);
$dict[$case->file]->failures += \count($case->failures);
$dict[$case->file]->errors += \count($case->errors);
$dict[$case->file]->skipped += \count($case->skipped);
$dict[$case->file]->time += $case->time;
$dict[$case->file]->file = $case->file;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Parser/Parser.php
Expand Up @@ -57,7 +57,7 @@ public function __construct(string $srcPath)
* Returns the fully constructed class
* with methods or null if the class is abstract.
*
* @return null|ParsedClass
* @return ParsedClass|null
*/
public function getClass()
{
Expand Down
6 changes: 2 additions & 4 deletions src/Runners/PHPUnit/BaseRunner.php
Expand Up @@ -180,19 +180,17 @@ protected function getCoverage()

/**
* Overrides envirenment variables if needed.
*
* @return null
*/
protected function overrideEnvironmentVariables()
{
if (! isset($this->options->filtered['configuration'])) {
if (!isset($this->options->filtered['configuration'])) {
return;
}

$variables = $this->options->filtered['configuration']->getEnvironmentVariables();

foreach ($variables as $key => $value) {
\putenv(sprintf('%s=%s', $key, $value));
putenv(sprintf('%s=%s', $key, $value));

$_ENV[$key] = $value;
}
Expand Down
20 changes: 16 additions & 4 deletions src/Runners/PHPUnit/Configuration.php
Expand Up @@ -12,6 +12,12 @@
*/
class Configuration
{
/**
* @see \PHPUnit\Util\Configuration
* @see https://github.com/sebastianbergmann/phpunit/commit/80754cf323fe96003a2567f5e57404fddecff3bf
*/
const TEST_SUITE_FILTER_SEPARATOR = ',';

/**
* Path to the configuration file.
*
Expand Down Expand Up @@ -100,16 +106,22 @@ public function getSuites()
return $suites;
}

public function hasSuites()
{
return !empty($this->getSuitesName());
}

public function getSuitesName()
{
if (!$this->xml) {
return null;
return;
}
$nodes = $this->xml->xpath('//testsuites/testsuite');
$names = [];
foreach ($nodes as $node) {
$names[] = (string)$node['name'];
$names[] = (string) $node['name'];
}

return $names;
}

Expand Down Expand Up @@ -173,7 +185,7 @@ public function getSuiteByName(string $suiteName)
*/
public function getConfigDir(): string
{
return dirname($this->path) . DIRECTORY_SEPARATOR;
return \dirname($this->path) . \DIRECTORY_SEPARATOR;
}

/**
Expand Down Expand Up @@ -212,7 +224,7 @@ public function getSuitePaths(string $path)
*/
public function getEnvironmentVariables(): array
{
if (! isset($this->xml->php->env)) {
if (!isset($this->xml->php->env)) {
return [];
}

Expand Down