Skip to content

Commit

Permalink
Merge pull request #164 from pczerkas/add-chunking-base
Browse files Browse the repository at this point in the history
Add --chunk-size option
  • Loading branch information
Jean85 authored Jun 15, 2022
2 parents 0212b7a + 24da0dc commit 6a70778
Show file tree
Hide file tree
Showing 39 changed files with 980 additions and 61 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ vendor
build/
swiftmailer/
docker-compose.override.yml
.vscode/
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## Unreleased
### Added
* Add `--chunk-size` option [#164](https://github.com/facile-it/paraunit/pull/164)
* Add native enabling of Xdebug coverage mode [#170](https://github.com/facile-it/paraunit/pull/170)
* Report full process output when in debug mode [#170](https://github.com/facile-it/paraunit/pull/170)
* Add support for Symfony 6 [#168](https://github.com/facile-it/paraunit/pull/168)
Expand Down Expand Up @@ -58,7 +59,7 @@ First stable release. The following changes are in comparison to the previous, u
## [1.0.0-beta1] - 2019-04-08
### Breaking changes
* Drop support for older packages: [#134](https://github.com/facile-it/paraunit/pull/134)
* `phpunit/phpunit` 6
* `phpunit/phpunit` 6
* `phpunit/php-code-coverage` < 6
* All Symfony components < 3.4
* Scalar and return types added everywhere possible
Expand Down
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,22 @@ To use this package, use Composer:
```json
{
"require-dev": {
"facile-it/paraunit": "^1.1"
"facile-it/paraunit": "^1.3"
}
}
```

### Compatibility
You can use Paraunit with many different versions of PHPUnit or Symfony, following this compatibility list:

| Paraunit version | Compatible PHPUnit Version | Compatible Symfony Version |
|------------------|----------------------------|----------------------------|
| 1.2 | 9.3+ | 3.4, 4, 5 |
| 1.1 | 9.1, 9.2 | 3.4, 4, 5 |
| 1.0.* | 7, 8 | 3.4, 4, 5 |
| 0.12.* | 6, 7 | 2.8, 3, 4 |
You can use Paraunit with many versions of PHPUnit or Symfony, following this compatibility list:

| Paraunit version | Compatible PHPUnit Version | Compatible Symfony Version |
|----------------------|----------------------------|----------------------------|
| 2.0 (to be released) | 10+ | 4.4, 5, 6 |
| 1.3 | 9.3+ | 4.4, 5, 6 |
| 1.2 | 9.3+ | 3.4, 4, 5 |
| 1.1 | 9.1, 9.2 | 3.4, 4, 5 |
| 1.0.* | 7, 8 | 3.4, 4, 5 |
| 0.12.* | 6, 7 | 2.8, 3, 4 |

## Usage
Paraunit starts as a Symfony console command, but it's provided through a bin launcher; you can run it like this:<br/>
Expand Down
3 changes: 2 additions & 1 deletion psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
</MixedArrayAssignment>
</file>
<file src="src/Configuration/ParallelConfiguration.php">
<MixedArgument occurrences="5">
<MixedArgument occurrences="6">
<code>$input-&gt;getArgument('stringFilter')</code>
<code>$input-&gt;getOption('chunk-size')</code>
<code>$input-&gt;getOption('configuration') ?? '.'</code>
<code>$input-&gt;getOption('logo')</code>
<code>$input-&gt;getOption('parallel')</code>
Expand Down
1 change: 1 addition & 0 deletions src/Command/ParallelCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ protected function configure(): void
$this->addOption('configuration', 'c', InputOption::VALUE_REQUIRED, 'The PHPUnit XML config filename or path');
$this->addArgument('stringFilter', InputArgument::OPTIONAL, 'A case-insensitive string to filter tests filename');
$this->addOption('parallel', null, InputOption::VALUE_REQUIRED, 'Number of concurrent processes to launch', 10);
$this->addOption('chunk-size', null, InputOption::VALUE_REQUIRED, 'Number of test files in chunk', 1);
$this->addOption('debug', null, InputOption::VALUE_NONE, 'Print verbose debug output');
$this->addOption('logo', null, InputOption::VALUE_NONE, 'Print the Shark logo at the top');

Expand Down
33 changes: 33 additions & 0 deletions src/Configuration/ChunkSize.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Paraunit\Configuration;

class ChunkSize
{
/** @var positive-int */
private $chunkSize;

public function __construct(int $chunkSize)
{
if ($chunkSize < 1) {
throw new \InvalidArgumentException('Chunk size must be 1 or greater');
}

$this->chunkSize = $chunkSize;
}

/**
* @return positive-int
*/
public function getChunkSize(): int
{
return $this->chunkSize;
}

public function isChunked(): bool
{
return $this->chunkSize > 1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Paraunit\Configuration\DependencyInjection;

use Paraunit\Configuration\ChunkSize;
use Paraunit\Configuration\PHPDbgBinFile;
use Paraunit\Configuration\PHPUnitBinFile;
use Paraunit\Configuration\PHPUnitConfig;
Expand Down Expand Up @@ -45,6 +46,7 @@ private function configureProcessWithCoverage(ContainerBuilder $container): void
{
$container->setDefinition(CommandLineWithCoverage::class, new Definition(CommandLineWithCoverage::class, [
new Reference(PHPUnitBinFile::class),
new Reference(ChunkSize::class),
new Reference(PcovProxy::class),
new Reference(XDebugProxy::class),
new Reference(PHPDbgBinFile::class),
Expand All @@ -56,6 +58,7 @@ private function configureProcessWithCoverage(ContainerBuilder $container): void
new Reference(CommandLineWithCoverage::class),
new Reference(PHPUnitConfig::class),
new Reference(TempFilenameFactory::class),
new Reference(ChunkSize::class),
]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Paraunit\Configuration\DependencyInjection;

use Paraunit\Configuration\ChunkSize;
use Paraunit\Configuration\PHPUnitBinFile;
use Paraunit\Configuration\PHPUnitConfig;
use Paraunit\Configuration\TempFilenameFactory;
Expand All @@ -20,6 +21,7 @@
use Paraunit\Process\CommandLine;
use Paraunit\Process\ProcessFactory;
use Paraunit\Process\ProcessFactoryInterface;
use Paraunit\Runner\ChunkFile;
use Paraunit\Runner\PipelineCollection;
use Paraunit\Runner\PipelineFactory;
use Paraunit\Runner\Runner;
Expand Down Expand Up @@ -75,6 +77,9 @@ private function configureConfiguration(ContainerBuilder $container): void
$container->setDefinition(TempFilenameFactory::class, new Definition(TempFilenameFactory::class, [
new Reference(TempDirectory::class),
]));
$container->setDefinition(ChunkSize::class, new Definition(ChunkSize::class, [
'%paraunit.chunk_size%',
]));
}

private function configureEventDispatcher(ContainerBuilder $container): void
Expand Down Expand Up @@ -111,6 +116,7 @@ private function configurePrinter(ContainerBuilder $container): void
$finalPrinterArguments = [
new Reference(TestResultList::class),
$output,
new Reference(ChunkSize::class),
];
$container->setDefinition(FinalPrinter::class, new Definition(FinalPrinter::class, $finalPrinterArguments));
$container->setDefinition(FailuresPrinter::class, new Definition(FailuresPrinter::class, $finalPrinterArguments));
Expand All @@ -126,12 +132,14 @@ private function configureProcess(ContainerBuilder $container): void
{
$container->setDefinition(CommandLine::class, new Definition(CommandLine::class, [
new Reference(PHPUnitBinFile::class),
new Reference(ChunkSize::class),
]));

$container->setDefinition(ProcessFactoryInterface::class, new Definition(ProcessFactory::class, [
new Reference(CommandLine::class),
new Reference(PHPUnitConfig::class),
new Reference(TempFilenameFactory::class),
new Reference(ChunkSize::class),
]));
}

Expand All @@ -149,8 +157,14 @@ private function configureRunner(ContainerBuilder $container): void
new Reference(ProcessFactoryInterface::class),
new Reference(Filter::class),
new Reference(PipelineCollection::class),
new Reference(ChunkSize::class),
new Reference(ChunkFile::class),
]))
->setPublic(true);

$container->setDefinition(ChunkFile::class, new Definition(ChunkFile::class, [
new Reference(PHPUnitConfig::class),
]));
}

private function configureServices(ContainerBuilder $container): void
Expand Down
2 changes: 2 additions & 0 deletions src/Configuration/DependencyInjection/ParserDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Paraunit\Configuration\DependencyInjection;

use Paraunit\Configuration\ChunkSize;
use Paraunit\Configuration\TempFilenameFactory;
use Paraunit\Parser\DeprecationParser;
use Paraunit\Parser\JSON\AbnormalTerminatedParser;
Expand Down Expand Up @@ -82,6 +83,7 @@ private function defineParsers(ContainerBuilder $container): array
]),
AbnormalTerminatedParser::class => new Definition(AbnormalTerminatedParser::class, [
new Reference('paraunit.test_result.abnormal_terminated_container'),
new Reference(ChunkSize::class),
LogFetcher::LOG_ENDING_STATUS,
]),
UnknownResultParser::class => new Definition(UnknownResultParser::class, [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Paraunit\Configuration\DependencyInjection;

use Paraunit\Configuration\ChunkSize;
use Paraunit\Configuration\PHPUnitConfig;
use Paraunit\TestResult\TestResultContainer;
use Paraunit\TestResult\TestResultFormat;
Expand All @@ -27,6 +28,7 @@ public function configure(ContainerBuilder $container): void
$container->setDefinition($testResultContainerName, new Definition(TestResultContainer::class, [
new Reference($formatName),
new Reference(PHPUnitConfig::class),
new Reference(ChunkSize::class),
]));

$testResultList->addMethodCall('addContainer', [new Reference($testResultContainerName)]);
Expand Down
1 change: 1 addition & 0 deletions src/Configuration/ParallelConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ protected function tagEventSubscribers(ContainerBuilder $container): void
protected function loadCommandLineOptions(ContainerBuilder $containerBuilder, InputInterface $input): void
{
$containerBuilder->setParameter('paraunit.max_process_count', $input->getOption('parallel'));
$containerBuilder->setParameter('paraunit.chunk_size', $input->getOption('chunk-size'));
$containerBuilder->setParameter('paraunit.phpunit_config_filename', $input->getOption('configuration') ?? '.');
$containerBuilder->setParameter('paraunit.testsuite', $input->getOption('testsuite'));
$containerBuilder->setParameter('paraunit.string_filter', $input->getArgument('stringFilter'));
Expand Down
19 changes: 15 additions & 4 deletions src/Parser/JSON/AbnormalTerminatedParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Paraunit\Parser\JSON;

use Paraunit\Configuration\ChunkSize;
use Paraunit\Process\AbstractParaunitProcess;
use Paraunit\TestResult\Interfaces\TestResultHandlerInterface;
use Paraunit\TestResult\Interfaces\TestResultInterface;
Expand All @@ -12,12 +13,18 @@

class AbnormalTerminatedParser extends GenericParser
{
/** @var ChunkSize */
private $chunkSize;

/** @var string */
private $lastStartedTest = '[UNKNOWN]';

public function __construct(TestResultHandlerInterface $testResultHandler)
{
public function __construct(
TestResultHandlerInterface $testResultHandler,
ChunkSize $chunkSize
) {
parent::__construct($testResultHandler, LogFetcher::LOG_ENDING_STATUS);
$this->chunkSize = $chunkSize;
}

public function handleLogItem(AbstractParaunitProcess $process, Log $logItem): ?TestResultInterface
Expand Down Expand Up @@ -52,7 +59,11 @@ private function saveTestFQCN(AbstractParaunitProcess $process, Log $logItem): v
return;
}

$suiteName = explode('::', $logItem->getTest());
$process->setTestClassName($suiteName[0]);
if ($this->chunkSize->isChunked()) {
$suiteName = basename($process->getFilename());
} else {
$suiteName = explode('::', $logItem->getTest())[0];
}
$process->setTestClassName($suiteName);
}
}
12 changes: 10 additions & 2 deletions src/Printer/AbstractFinalPrinter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Paraunit\Printer;

use Paraunit\Configuration\ChunkSize;
use Paraunit\TestResult\TestResultList;
use Symfony\Component\Console\Output\OutputInterface;

Expand All @@ -12,10 +13,17 @@ abstract class AbstractFinalPrinter extends AbstractPrinter
/** @var TestResultList */
protected $testResultList;

public function __construct(TestResultList $testResultList, OutputInterface $output)
{
/** @var ChunkSize */
protected $chunkSize;

public function __construct(
TestResultList $testResultList,
OutputInterface $output,
ChunkSize $chunkSize
) {
parent::__construct($output);
$this->testResultList = $testResultList;
$this->chunkSize = $chunkSize;
}

abstract public function onEngineEnd(): void;
Expand Down
7 changes: 6 additions & 1 deletion src/Printer/FilesRecapPrinter.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,19 @@ private function printFileRecap(TestResultContainerInterface $testResultContaine
}

$filenames = $testResultContainer->getFileNames();
if ($this->chunkSize->isChunked()) {
$fileTitle = 'chunks';
} else {
$fileTitle = 'files';
}

if (count($filenames)) {
$tag = $testResultContainer->getTestResultFormat()->getTag();
$title = $testResultContainer->getTestResultFormat()->getTitle();
$this->getOutput()->writeln('');
$this->getOutput()->writeln(
sprintf(
'<%s>%d files with %s:</%s>',
"<%s>%d $fileTitle with %s:</%s>",
$tag,
count($filenames),
strtoupper($title),
Expand Down
18 changes: 14 additions & 4 deletions src/Printer/FinalPrinter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Paraunit\Printer;

use Paraunit\Configuration\ChunkSize;
use Paraunit\Lifecycle\AbstractEvent;
use Paraunit\Lifecycle\EngineEnd;
use Paraunit\Lifecycle\EngineStart;
Expand All @@ -29,9 +30,12 @@ class FinalPrinter extends AbstractFinalPrinter implements EventSubscriberInterf
/** @var int */
private $processRetried;

public function __construct(TestResultList $testResultList, OutputInterface $output)
{
parent::__construct($testResultList, $output);
public function __construct(
TestResultList $testResultList,
OutputInterface $output,
ChunkSize $chunkSize
) {
parent::__construct($testResultList, $output, $chunkSize);

$this->stopWatch = new Stopwatch();
$this->processCompleted = 0;
Expand Down Expand Up @@ -91,7 +95,13 @@ private function printTestCounters(): void
}

$this->getOutput()->writeln('');
$this->getOutput()->write(sprintf('Executed: %d test classes', $this->processCompleted - $this->processRetried));
$executedNum = $this->processCompleted - $this->processRetried;
if ($this->chunkSize->isChunked()) {
$executedTitle = 'chunks';
} else {
$executedTitle = 'test classes';
}
$this->getOutput()->write(sprintf("Executed: %d $executedTitle", $executedNum));
if ($this->processRetried > 0) {
$this->getOutput()->write(sprintf(' (%d retried)', $this->processRetried));
}
Expand Down
Loading

0 comments on commit 6a70778

Please sign in to comment.