mirror of
https://github.com/pestphp/pest.git
synced 2026-03-06 07:47:22 +01:00
5
.github/workflows/tests.yml
vendored
5
.github/workflows/tests.yml
vendored
@ -10,8 +10,9 @@ jobs:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
php: ['7.3', '7.4', '8.0']
|
||||
dependency-version: [prefer-lowest, prefer-stable]
|
||||
parallel: ['', '--parallel']
|
||||
|
||||
name: PHP ${{ matrix.php }} - ${{ matrix.os }} - ${{ matrix.dependency-version }}
|
||||
name: PHP ${{ matrix.php }} - ${{ matrix.os }} - ${{ matrix.dependency-version }} - ${{ matrix.parallel }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
@ -38,7 +39,7 @@ jobs:
|
||||
if: "matrix.php >= 8"
|
||||
|
||||
- name: Unit Tests
|
||||
run: php bin/pest --colors=always --exclude-group=integration
|
||||
run: php bin/pest --colors=always --exclude-group=integration ${{ matrix.parallel }}
|
||||
|
||||
- name: Integration Tests
|
||||
run: php bin/pest --colors=always --group=integration
|
||||
|
||||
16
bin/pest
16
bin/pest
@ -3,9 +3,9 @@
|
||||
|
||||
use NunoMaduro\Collision\Provider;
|
||||
use Pest\Actions\ValidatesEnvironment;
|
||||
use Pest\Console\Command;
|
||||
use Pest\Support\Container;
|
||||
use Pest\TestSuite;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
@ -42,14 +42,22 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
ValidatesEnvironment::in($testSuite);
|
||||
|
||||
$args = $_SERVER['argv'];
|
||||
|
||||
// Let's remove any arguments that PHPUnit does not understand
|
||||
if ($argv->hasParameterOption('--test-directory')) {
|
||||
foreach ($_SERVER['argv'] as $key => $value) {
|
||||
foreach ($args as $key => $value) {
|
||||
if (strpos($value, '--test-directory') !== false) {
|
||||
unset($_SERVER['argv'][$key]);
|
||||
unset($args[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit($container->get(Command::class)->run($_SERVER['argv']));
|
||||
if (($runInParallel = $argv->hasParameterOption(['--parallel', '-P'])) && !class_exists(\Pest\Parallel\Command::class)) {
|
||||
$output->writeln("Parallel support requires the Pest Parallel plugin. Run <fg=yellow;options=bold>`composer require --dev pestphp/pest-plugin-parallel`</> first.");
|
||||
exit(Command::FAILURE);
|
||||
}
|
||||
|
||||
$command = $runInParallel ? \Pest\Parallel\Command::class : \Pest\Console\Command::class;
|
||||
exit($container->get($command)->run($args));
|
||||
})();
|
||||
|
||||
@ -43,7 +43,8 @@
|
||||
"illuminate/console": "^8.47.0",
|
||||
"illuminate/support": "^8.47.0",
|
||||
"laravel/dusk": "^6.15.0",
|
||||
"pestphp/pest-dev-tools": "dev-master"
|
||||
"pestphp/pest-dev-tools": "dev-master",
|
||||
"pestphp/pest-plugin-parallel": "^1.0"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
@ -59,12 +60,14 @@
|
||||
"test:lint": "php-cs-fixer fix -v --dry-run",
|
||||
"test:types": "phpstan analyse --ansi --memory-limit=-1",
|
||||
"test:unit": "php bin/pest --colors=always --exclude-group=integration",
|
||||
"test:parallel": "php bin/pest -P --colors=always --exclude-group=integration",
|
||||
"test:integration": "php bin/pest --colors=always --group=integration",
|
||||
"update:snapshots": "REBUILD_SNAPSHOTS=true php bin/pest --colors=always",
|
||||
"test": [
|
||||
"@test:lint",
|
||||
"@test:types",
|
||||
"@test:unit",
|
||||
"@test:parallel",
|
||||
"@test:integration"
|
||||
]
|
||||
},
|
||||
|
||||
50
src/Actions/InteractsWithPlugins.php
Normal file
50
src/Actions/InteractsWithPlugins.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest\Actions;
|
||||
|
||||
use Pest\Contracts\Plugins\AddsOutput;
|
||||
use Pest\Contracts\Plugins\HandlesArguments;
|
||||
use Pest\Plugin\Loader;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class InteractsWithPlugins
|
||||
{
|
||||
/**
|
||||
* Transform the input arguments by passing it to the relevant plugins.
|
||||
*
|
||||
* @param array<int, string> $argv
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public static function handleArguments(array $argv): array
|
||||
{
|
||||
$plugins = Loader::getPlugins(HandlesArguments::class);
|
||||
|
||||
/** @var HandlesArguments $plugin */
|
||||
foreach ($plugins as $plugin) {
|
||||
$argv = $plugin->handleArguments($argv);
|
||||
}
|
||||
|
||||
return $argv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides an opportunity for any plugins that want
|
||||
* to provide additional output after test execution.
|
||||
*/
|
||||
public static function addOutput(int $result): int
|
||||
{
|
||||
$plugins = Loader::getPlugins(AddsOutput::class);
|
||||
|
||||
/** @var AddsOutput $plugin */
|
||||
foreach ($plugins as $plugin) {
|
||||
$result = $plugin->addOutput($result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@ -6,11 +6,9 @@ namespace Pest\Console;
|
||||
|
||||
use Pest\Actions\AddsDefaults;
|
||||
use Pest\Actions\AddsTests;
|
||||
use Pest\Actions\InteractsWithPlugins;
|
||||
use Pest\Actions\LoadStructure;
|
||||
use Pest\Actions\ValidatesConfiguration;
|
||||
use Pest\Contracts\Plugins\AddsOutput;
|
||||
use Pest\Contracts\Plugins\HandlesArguments;
|
||||
use Pest\Plugin\Loader;
|
||||
use Pest\Plugins\Version;
|
||||
use Pest\Support\Container;
|
||||
use Pest\TestSuite;
|
||||
@ -57,23 +55,12 @@ final class Command extends BaseCommand
|
||||
*/
|
||||
protected function handleArguments(array $argv): void
|
||||
{
|
||||
/*
|
||||
* First, let's call all plugins that want to handle arguments
|
||||
*/
|
||||
$plugins = Loader::getPlugins(HandlesArguments::class);
|
||||
$argv = InteractsWithPlugins::handleArguments($argv);
|
||||
|
||||
/** @var HandlesArguments $plugin */
|
||||
foreach ($plugins as $plugin) {
|
||||
$argv = $plugin->handleArguments($argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Next, as usual, let's send the console arguments to PHPUnit.
|
||||
*/
|
||||
parent::handleArguments($argv);
|
||||
|
||||
/*
|
||||
* Finally, let's validate the configuration. Making
|
||||
* Let's validate the configuration. Making
|
||||
* sure all options are yet supported by Pest.
|
||||
*/
|
||||
ValidatesConfiguration::in($this->arguments);
|
||||
@ -128,16 +115,7 @@ final class Command extends BaseCommand
|
||||
LoadStructure::in($this->testSuite->rootPath);
|
||||
|
||||
$result = parent::run($argv, false);
|
||||
|
||||
/*
|
||||
* Let's call all plugins that want to add output after test execution
|
||||
*/
|
||||
$plugins = Loader::getPlugins(AddsOutput::class);
|
||||
|
||||
/** @var AddsOutput $plugin */
|
||||
foreach ($plugins as $plugin) {
|
||||
$result = $plugin->addOutput($result);
|
||||
}
|
||||
$result = InteractsWithPlugins::addOutput($result);
|
||||
|
||||
exit($result);
|
||||
}
|
||||
|
||||
@ -286,7 +286,7 @@ final class TeamCity extends DefaultResultPrinter
|
||||
{
|
||||
$this->markAsFailure($t);
|
||||
$this->writeWarning($test->getName());
|
||||
$this->phpunitTeamCity->addSkippedTest($test, $t, $time);
|
||||
$this->phpunitTeamCity->printIgnoredTest($test->getName(), $t, $time);
|
||||
}
|
||||
|
||||
private function markAsFailure(Throwable $t): void
|
||||
|
||||
@ -44,6 +44,20 @@ final class TestRepository
|
||||
return count($this->state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filename of each test that should be executed in the suite.
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function getFilenames(): array
|
||||
{
|
||||
$testsWithOnly = $this->testsUsingOnly();
|
||||
|
||||
return array_values(array_map(function (TestCaseFactory $factory): string {
|
||||
return $factory->filename;
|
||||
}, count($testsWithOnly) > 0 ? $testsWithOnly : $this->state));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the given callable foreach test case.
|
||||
*/
|
||||
@ -85,9 +99,7 @@ final class TestRepository
|
||||
}
|
||||
}
|
||||
|
||||
$onlyState = array_filter($this->state, function ($testFactory): bool {
|
||||
return $testFactory->only;
|
||||
});
|
||||
$onlyState = $this->testsUsingOnly();
|
||||
|
||||
$state = count($onlyState) > 0 ? $onlyState : $this->state;
|
||||
|
||||
@ -100,6 +112,18 @@ final class TestRepository
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all tests that have called the only method.
|
||||
*
|
||||
* @return array<TestCaseFactory>
|
||||
*/
|
||||
private function testsUsingOnly(): array
|
||||
{
|
||||
return array_filter($this->state, function ($testFactory): bool {
|
||||
return $testFactory->only;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the given `$testCaseClass` on the given `$paths`.
|
||||
*
|
||||
|
||||
@ -614,6 +614,8 @@
|
||||
PASS Tests\Unit\TestSuite
|
||||
✓ it does not allow to add the same test description twice
|
||||
✓ it alerts users about tests with arguments but no input
|
||||
✓ it can return an array of all test suite filenames
|
||||
✓ it can filter the test suite filenames to those with the only method
|
||||
|
||||
PASS Tests\Visual\Help
|
||||
✓ visual snapshot of help command output
|
||||
@ -647,5 +649,5 @@
|
||||
✓ it is a test
|
||||
✓ it uses correct parent class
|
||||
|
||||
Tests: 4 incompleted, 9 skipped, 419 passed
|
||||
Tests: 4 incompleted, 9 skipped, 421 passed
|
||||
|
||||
@ -7,7 +7,7 @@ global $globalHook;
|
||||
// HACK: we have to determine our $globalHook->calls baseline. This is because
|
||||
// two other tests are executed before this one due to filename ordering.
|
||||
$args = $_SERVER['argv'] ?? [];
|
||||
$single = isset($args[1]) && Str::endsWith(__FILE__, $args[1]);
|
||||
$single = (isset($args[1]) && Str::endsWith(__FILE__, $args[1])) || ($_SERVER['PEST_PARALLEL'] ?? false);
|
||||
$offset = $single ? 0 : 2;
|
||||
|
||||
uses()->beforeAll(function () use ($globalHook, $offset) {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\SubFolder\SubFolder\SubFolder;
|
||||
namespace Tests\CustomTestCaseInSubFolders\SubFolder\SubFolder;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
<?php
|
||||
|
||||
uses(Tests\SubFolder\SubFolder\SubFolder\CustomTestCaseInSubFolder::class)->in('CustomTestCaseInSubFolders/SubFolder');
|
||||
@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
use Tests\CustomTestCaseInSubFolders\SubFolder\SubFolder\CustomTestCaseInSubFolder;
|
||||
|
||||
uses(CustomTestCaseInSubFolder::class)->in('PHPUnit/CustomTestCaseInSubFolders/SubFolder/SubFolder');
|
||||
|
||||
uses()->group('integration')->in('Visual');
|
||||
|
||||
// NOTE: global test value container to be mutated and checked across files, as needed
|
||||
|
||||
@ -22,3 +22,30 @@ it('alerts users about tests with arguments but no input', function () {
|
||||
DatasetMissing::class,
|
||||
sprintf("A test with the description '%s' has %d argument(s) ([%s]) and no dataset(s) provided in %s", 'foo', 1, 'int $arg', __FILE__),
|
||||
);
|
||||
|
||||
it('can return an array of all test suite filenames', function () {
|
||||
$testSuite = new TestSuite(getcwd(), 'tests');
|
||||
$test = function () {};
|
||||
$testSuite->tests->set(new \Pest\Factories\TestCaseFactory(__FILE__, 'foo', $test));
|
||||
$testSuite->tests->set(new \Pest\Factories\TestCaseFactory(__FILE__, 'bar', $test));
|
||||
|
||||
expect($testSuite->tests->getFilenames())->toEqual([
|
||||
__FILE__,
|
||||
__FILE__,
|
||||
]);
|
||||
});
|
||||
|
||||
it('can filter the test suite filenames to those with the only method', function () {
|
||||
$testSuite = new TestSuite(getcwd(), 'tests');
|
||||
$test = function () {};
|
||||
|
||||
$testWithOnly = new \Pest\Factories\TestCaseFactory(__FILE__, 'foo', $test);
|
||||
$testWithOnly->only = true;
|
||||
$testSuite->tests->set($testWithOnly);
|
||||
|
||||
$testSuite->tests->set(new \Pest\Factories\TestCaseFactory('Baz/Bar/Boo.php', 'bar', $test));
|
||||
|
||||
expect($testSuite->tests->getFilenames())->toEqual([
|
||||
__FILE__,
|
||||
]);
|
||||
});
|
||||
|
||||
@ -9,7 +9,7 @@ test('visual snapshot of test suite on success', function () {
|
||||
]);
|
||||
|
||||
$output = function () use ($testsPath) {
|
||||
$process = (new Symfony\Component\Process\Process(['php', 'bin/pest'], dirname($testsPath), ['EXCLUDE' => 'integration', 'REBUILD_SNAPSHOTS' => false]));
|
||||
$process = (new Symfony\Component\Process\Process(['php', 'bin/pest'], dirname($testsPath), ['EXCLUDE' => 'integration', 'REBUILD_SNAPSHOTS' => false, 'PARATEST' => 0]));
|
||||
|
||||
$process->run();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user