Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
veewee committed Dec 2, 2020
1 parent 4367040 commit 1cf6dfd
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 6 deletions.
7 changes: 5 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@
"fix-cs": "./tools/php-cs-fixer.phar fix",
"psalm": "./tools/psalm.phar",
"tests": "./tools/phpunit.phar",
"coverage": "@php ./tools/full-coverage-check.php .phpunit.cache/clover.xml",
"infection": "./tools/infection.phar",
"coverage": "@php ./tools/full-coverage-check.php .phpunit.cache/clover/clover.xml",
"infection": [
"Composer\\Config::disableProcessTimeout",
"./tools/infection.phar"
],
"ci": [
"@parallel psalm cs tests",
"@parallel coverage infection"
Expand Down
2 changes: 2 additions & 0 deletions infection.json.dist
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
"src"
]
},
"minMsi": 100,
"minCoveredMsi": 100,
"phpUnit": {
"customPath": ".\/tools\/phpunit.phar"
},
Expand Down
3 changes: 2 additions & 1 deletion phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
<directory suffix=".php">src</directory>
</include>
<report>
<clover outputFile=".phpunit.cache/clover.xml" />
<clover outputFile=".phpunit.cache/clover/clover.xml" />
<html outputDirectory=".phpunit.cache/report" lowUpperBound="99" highLowerBound="99" />
</report>
</coverage>
</phpunit>
4 changes: 2 additions & 2 deletions src/Scripts/ParallelScript.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ static function (Process $process) use ($task, $io, $resultMap): void {

return $resultMap->conclude(
static function () use ($resultMap, $io): int {
$io->write(['<info>Finished running', ...$resultMap->listSucceededTasks(), '</info>']);
$io->write(['<info>Finished running: ', ...$resultMap->listSucceededTasks(), '</info>']);

return 0;
},
Expand All @@ -86,7 +86,7 @@ static function (int $resultCode) use ($io, $resultMap): int {
'<error>Failed running: ',
...$resultMap->listFailedTasks(),
'',
'Not all tasks could be executed succesfully!',
'Not all tasks could be executed successfully!',
'</error>',
]);

Expand Down
7 changes: 7 additions & 0 deletions tests/Unit/Finder/PhpExecutableFinderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,11 @@ public function it_throws_exception_on_php_executable_not_found(): void
$phpExecutableFinder = new PhpExecutableFinder($finder);
$phpExecutableFinder();
}

/** @test */
public function it_can_create_a_default_finder(): void
{
$phpExecutableFinder = PhpExecutableFinder::default();
self::assertInstanceOf(PhpExecutableFinder::class, $phpExecutableFinder);
}
}
24 changes: 23 additions & 1 deletion tests/Unit/ParallelPluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,37 @@

namespace ComposerRunParallel\Test\Unit;

use Composer\Composer;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\IO\NullIO;
use Composer\Plugin\Capability\CommandProvider;
use Composer\Plugin\Capable;
use Composer\Plugin\PluginInterface;
use Composer\Script\Event;
use ComposerRunParallel\Command\ParallelCommandsProvider;
use ComposerRunParallel\Exception\ParallelException;
use ComposerRunParallel\ParallelPlugin;
use PHPUnit\Framework\TestCase;

/**
* @covers \ComposerRunParallel\ParallelPlugin
* @covers \ComposerRunParallel\Scripts\ParallelScript
*/
final class ParallelPluginTest extends TestCase
{
/** @test */
public function it_is_a_composer_plugin(): void
{
self::assertInstanceOf(PluginInterface::class, new ParallelPlugin());
$plugin = new ParallelPlugin();
$io = new NullIO();
$composer = new Composer();

self::assertInstanceOf(PluginInterface::class, $plugin);

// These should do nothing for now ...
$plugin->activate($composer, $io);
$plugin->deactivate($composer, $io);
$plugin->uninstall($composer, $io);
}

/** @test */
Expand Down Expand Up @@ -49,5 +63,13 @@ public function it_registers_commands(): void
/** @test */
public function it_can_run_the_parallel_script(): void
{
$composer = new Composer();
$io = new NullIO();

$this->expectException(ParallelException::class);
$this->expectExceptionMessage(ParallelException::atLeastOneTask()->getMessage());

$plugin = new ParallelPlugin();
$plugin->runParallelScript(new Event('parallel', $composer, $io));
}
}
100 changes: 100 additions & 0 deletions tests/Unit/Scripts/ParallelScriptTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,130 @@

namespace ComposerRunParallel\Test\Unit\Script;

use Composer\Composer;
use Composer\EventDispatcher\EventDispatcher;
use Composer\EventDispatcher\ScriptExecutionException;
use Composer\IO\BufferIO;
use Composer\Script\Event;
use Composer\Util\HttpDownloader;
use Composer\Util\Loop;
use Composer\Util\ProcessExecutor;
use ComposerRunParallel\Exception\ParallelException;
use ComposerRunParallel\Finder\PhpExecutableFinder;
use ComposerRunParallel\Scripts\ParallelScript;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use React\Promise\FulfilledPromise;
use Symfony\Component\Process\PhpExecutableFinder as SymfonyPhpExecutableFinder;
use Symfony\Component\Process\Process;

/**
* @covers \ComposerRunParallel\Scripts\ParallelScript
*/
class ParallelScriptTest extends TestCase
{
private BufferIO $io;
private Composer $composer;
private ParallelScript $script;

/** @var MockObject & ProcessExecutor */
private MockObject $processExecutor;

protected function setUp(): void
{
$httpDownloader = $this->createMock(HttpDownloader::class);
$this->processExecutor = $this->createMock(ProcessExecutor::class);
$finder = $this->createMock(SymfonyPhpExecutableFinder::class);
$finder->method('find')->willReturn('php');
$finder->method('findArguments')->willReturn([]);

$this->io = new BufferIO();

$dispatcher = $this->createMock(EventDispatcher::class);
$dispatcher
->method('hasEventListeners')
->will($this->returnCallback(
static fn (Event $event) => in_array($event->getName(), ['task1', 'task2'], true)
));

$this->composer = new Composer();
$this->composer->setEventDispatcher($dispatcher);
$this->composer->setLoop(new Loop($httpDownloader, $this->processExecutor));

$this->script = new ParallelScript(
new PhpExecutableFinder($finder)
);
}


/** @test */
public function it_fails_if_there_are_not_tasks_specified(): void
{
$this->expectException(ParallelException::class);
$this->expectExceptionMessage(ParallelException::atLeastOneTask()->getMessage());

($this->script)($this->createEvent([]));
}

/** @test */
public function it_fails_if_a_task_is_not_known(): void
{
$this->expectException(ParallelException::class);
$this->expectExceptionMessage(ParallelException::invalidTask('unkown')->getMessage());

($this->script)($this->createEvent(['task1', 'unkown']));
}

/** @test */
public function it_can_successfully_run_scripts_in_parallel(): void
{
$this->processExecutor->method('executeAsync')->willReturn(
$this->createProcessResult(true)
);

$result = ($this->script)($this->createEvent(['task1']));

self::assertEquals(0, $result);

$output = $this->io->getOutput();
self::assertStringContainsString('Finished running: ' . PHP_EOL . 'task1', $output);
}

/** @test */
public function it_can_insuccessfully_run_scripts_in_parallel(): void
{
$this->processExecutor->method('executeAsync')->willReturn(
$this->createProcessResult(false),
$this->createProcessResult(true)
);
$exception = null;

try {
($this->script)($this->createEvent(['task1', 'task2']));
} catch (ScriptExecutionException $exception) {

}

self::assertInstanceOf(ScriptExecutionException::class, $exception);

$output = $this->io->getOutput();
self::assertStringContainsString('Succesfully ran: ' . PHP_EOL . 'task2', $output);
self::assertStringContainsString('Failed running: ' . PHP_EOL . 'task1', $output);
self::assertStringContainsString('Not all tasks could be executed successfully!', $output);
}

private function createProcessResult(bool $success): FulfilledPromise
{
$process = $this->createMock(Process::class);
$process->method('getExitCode')->willReturn($success ? 0 : 1);
$process->method('getOutput')->willReturn('stdout');
$process->method('getErrorOutput')->willReturn('stderr');

return new FulfilledPromise($process);
}

private function createEvent(array $tasks): Event
{
return new Event('parallel', $this->composer, $this->io, false, $tasks);
}
}

0 comments on commit 1cf6dfd

Please sign in to comment.