diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 883e3fd6..6ea74077 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -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 diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d4d5e82..944cb54f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [v1.18.0 (2021-08-30)](https://github.com/pestphp/pest/compare/v1.17.0...v1.18.0) +### Added +- `toHaveLength` expectation ([#386](https://github.com/pestphp/pest/pull/386)) +- `nunomaduro/collision:^6.0` support ([4ae482c](https://github.com/pestphp/pest/commit/4ae482c7073fb77782b8a4b5738ef1fcea0f82ab)) + +## [v1.17.0 (2021-08-26)](https://github.com/pestphp/pest/compare/v1.16.0...v1.17.0) +### Added +- `toThrow` expectation ([#361](https://github.com/pestphp/pest/pull/361)) + +## [v1.16.0 (2021-08-19)](https://github.com/pestphp/pest/compare/v1.15.0...v1.16.0) +### Added +- Support for new parallel options ([#369](https://github.com/pestphp/pest/pull/369)) + ## [v1.15.0 (2021-08-04)](https://github.com/pestphp/pest/compare/v1.14.0...v1.15.0) ### Added - `toBeTruthy` and `toBeFalsy` ([#367](https://github.com/pestphp/pest/pull/367)) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 36821899..4037f219 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,6 +31,10 @@ composer lint ``` ## Tests +Update the snapshots: +```bash +composer update:snapshots +``` Run all tests: ```bash composer test diff --git a/README.md b/README.md index 541d9f24..a4e616fe 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,11 @@ We would like to extend our thanks to the following sponsors for funding Pest de ### Premium Sponsors - **[Akaunting](https://akaunting.com)** +- **[Auth0](https://auth0.com)** - **[Codecourse](https://codecourse.com/)** -- **[Meema](https://meema.io/)** +- **[Fathom Analytics](https://usefathom.com/)** +- **[Meema](https://meema.io)** - **[Scout APM](https://scoutapm.com)** -- **[Spatie](https://spatie.be/)** +- **[Spatie](https://spatie.be)** Pest is an open-sourced software licensed under the **[MIT license](https://opensource.org/licenses/MIT)**. diff --git a/bin/pest b/bin/pest index 649c6540..2735abfc 100755 --- a/bin/pest +++ b/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 `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)); })(); diff --git a/composer.json b/composer.json index 9a3960f9..d9ac0d22 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ ], "require": { "php": "^7.3 || ^8.0", - "nunomaduro/collision": "^5.4.0", + "nunomaduro/collision": "^5.4.0|^6.0", "pestphp/pest-plugin": "^1.0.0", "phpunit/phpunit": "^9.5.5" }, @@ -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" ] }, diff --git a/src/Actions/InteractsWithPlugins.php b/src/Actions/InteractsWithPlugins.php new file mode 100644 index 00000000..a115ab40 --- /dev/null +++ b/src/Actions/InteractsWithPlugins.php @@ -0,0 +1,50 @@ + $argv + * + * @return array + */ + 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; + } +} diff --git a/src/Console/Command.php b/src/Console/Command.php index 1d6ef21c..a6ce762e 100644 --- a/src/Console/Command.php +++ b/src/Console/Command.php @@ -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); } diff --git a/src/Expectation.php b/src/Expectation.php index fabc51f8..253b1e1e 100644 --- a/src/Expectation.php +++ b/src/Expectation.php @@ -5,13 +5,19 @@ declare(strict_types=1); namespace Pest; use BadMethodCallException; +use Closure; +use InvalidArgumentException; use Pest\Concerns\Extendable; use Pest\Concerns\RetrievesValues; use Pest\Support\Arr; +use Pest\Support\NullClosure; use PHPUnit\Framework\Assert; use PHPUnit\Framework\Constraint\Constraint; use PHPUnit\Framework\ExpectationFailedException; +use ReflectionFunction; +use ReflectionNamedType; use SebastianBergmann\Exporter\Exporter; +use Throwable; /** * @internal @@ -321,6 +327,36 @@ final class Expectation return $this; } + /** + * Asserts that $number matches value's Length. + */ + public function toHaveLength(int $number): Expectation + { + if (is_string($this->value)) { + Assert::assertEquals($number, mb_strlen($this->value)); + + return $this; + } + + if (is_iterable($this->value)) { + return $this->toHaveCount($number); + } + + if (is_object($this->value)) { + if (method_exists($this->value, 'toArray')) { + $array = $this->value->toArray(); + } else { + $array = (array) $this->value; + } + + Assert::assertCount($number, $array); + + return $this; + } + + throw new BadMethodCallException('Expectation value length is not countable.'); + } + /** * Asserts that $count matches the number of elements of the value. */ @@ -350,6 +386,20 @@ final class Expectation return $this; } + /** + * Asserts that the value contains the provided properties $names. + * + * @param iterable $names + */ + public function toHaveProperties(iterable $names): Expectation + { + foreach ($names as $name) { + $this->toHaveProperty($name); + } + + return $this; + } + /** * Asserts that two variables have the same value. * @@ -749,6 +799,56 @@ final class Expectation return $this; } + /** + * Asserts that executing value throws an exception. + * + * @param (Closure(Throwable): mixed)|string $exception + */ + public function toThrow($exception, string $exceptionMessage = null): Expectation + { + $callback = NullClosure::create(); + + if ($exception instanceof Closure) { + $callback = $exception; + $parameters = (new ReflectionFunction($exception))->getParameters(); + + if (1 !== count($parameters)) { + throw new InvalidArgumentException('The given closure must have a single parameter type-hinted as the class string.'); + } + + if (!($type = $parameters[0]->getType()) instanceof ReflectionNamedType) { + throw new InvalidArgumentException('The given closure\'s parameter must be type-hinted as the class string.'); + } + + $exception = $type->getName(); + } + + try { + ($this->value)(); + } catch (Throwable $e) { // @phpstan-ignore-line + if (!class_exists($exception)) { + Assert::assertStringContainsString($exception, $e->getMessage()); + + return $this; + } + + if ($exceptionMessage !== null) { + Assert::assertStringContainsString($exceptionMessage, $e->getMessage()); + } + + Assert::assertInstanceOf($exception, $e); + $callback($e); + + return $this; + } + + if (!class_exists($exception)) { + throw new ExpectationFailedException("Exception with message \"{$exception}\" not thrown."); + } + + throw new ExpectationFailedException("Exception \"{$exception}\" not thrown."); + } + /** * Exports the given value. * diff --git a/src/Logging/TeamCity.php b/src/Logging/TeamCity.php index a9363b43..bfd732fb 100644 --- a/src/Logging/TeamCity.php +++ b/src/Logging/TeamCity.php @@ -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 diff --git a/src/Pest.php b/src/Pest.php index c6d45d15..dec7af04 100644 --- a/src/Pest.php +++ b/src/Pest.php @@ -6,7 +6,7 @@ namespace Pest; function version(): string { - return '1.15.0'; + return '1.18.0'; } function testDirectory(string $file = ''): string diff --git a/src/Repositories/TestRepository.php b/src/Repositories/TestRepository.php index 47684548..e522677a 100644 --- a/src/Repositories/TestRepository.php +++ b/src/Repositories/TestRepository.php @@ -22,7 +22,7 @@ use PHPUnit\Framework\TestCase; final class TestRepository { /** - * @var string + * @var non-empty-string */ private const SEPARATOR = '>>>'; @@ -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 + */ + 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 + */ + private function testsUsingOnly(): array + { + return array_filter($this->state, function ($testFactory): bool { + return $testFactory->only; + }); + } + /** * Uses the given `$testCaseClass` on the given `$paths`. * diff --git a/tests/.snapshots/success.txt b/tests/.snapshots/success.txt index 90293a29..d560456f 100644 --- a/tests/.snapshots/success.txt +++ b/tests/.snapshots/success.txt @@ -422,6 +422,25 @@ PASS Tests\Features\Expect\toHaveKeys ✓ pass ✓ failures + ✓ not failures + + PASS Tests\Features\Expect\toHaveLength + ✓ it passes with ('Fortaleza') + ✓ it passes with ('Sollefteå') + ✓ it passes with ('Ιεράπετρα') + ✓ it passes with (stdClass Object (...)) + ✓ it passes with (Illuminate\Support\Collection Object (...)) + ✓ it passes with array + ✓ it passes with *not* + ✓ it properly fails with *not* + ✓ it fails with (1) + ✓ it fails with (1.5) + ✓ it fails with (true) + ✓ it fails with (null) + + PASS Tests\Features\Expect\toHaveProperties + ✓ pass + ✓ failures ✓ not failures PASS Tests\Features\Expect\toHaveProperty @@ -454,6 +473,19 @@ ✓ failures ✓ not failures + PASS Tests\Features\Expect\toThrow + ✓ passes + ✓ failures 1 + ✓ failures 2 + ✓ failures 3 + ✓ failures 4 + ✓ failures 5 + ✓ failures 6 + ✓ failures 7 + ✓ not failures + ✓ closure missing parameter + ✓ closure missing type-hint + PASS Tests\Features\Helpers ✓ it can set/get properties on $this ✓ it throws error if property do not exist @@ -619,6 +651,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 @@ -652,5 +686,5 @@ ✓ it is a test ✓ it uses correct parent class - Tests: 4 incompleted, 9 skipped, 424 passed + Tests: 4 incompleted, 9 skipped, 447 passed \ No newline at end of file diff --git a/tests/Features/Expect/toHaveLength.php b/tests/Features/Expect/toHaveLength.php new file mode 100644 index 00000000..bd41066b --- /dev/null +++ b/tests/Features/Expect/toHaveLength.php @@ -0,0 +1,27 @@ +toHaveLength(9); +})->with([ + 'Fortaleza', 'Sollefteå', 'Ιεράπετρα', + (object) [1, 2, 3, 4, 5, 6, 7, 8, 9], + collect([1, 2, 3, 4, 5, 6, 7, 8, 9]), +]); + +it('passes with array', function () { + expect([1, 2, 3])->toHaveLength(3); +}); + +it('passes with *not*', function () { + expect('')->not->toHaveLength(1); +}); + +it('properly fails with *not*', function () { + expect('pest')->not->toHaveLength(4); +})->throws(ExpectationFailedException::class); + +it('fails', function ($value) { + expect($value)->toHaveLength(1); +})->with([1, 1.5, true, null])->throws(BadMethodCallException::class); diff --git a/tests/Features/Expect/toHaveProperties.php b/tests/Features/Expect/toHaveProperties.php new file mode 100644 index 00000000..ad3da1b0 --- /dev/null +++ b/tests/Features/Expect/toHaveProperties.php @@ -0,0 +1,26 @@ +name = 'Jhon'; + $object->age = 21; + + expect($object)->toHaveProperties(['name', 'age']); +}); + +test('failures', function () { + $object = new stdClass(); + $object->name = 'Jhon'; + + expect($object)->toHaveProperties(['name', 'age']); +})->throws(ExpectationFailedException::class); + +test('not failures', function () { + $object = new stdClass(); + $object->name = 'Jhon'; + $object->age = 21; + + expect($object)->not->toHaveProperties(['name', 'age']); +})->throws(ExpectationFailedException::class); diff --git a/tests/Features/Expect/toThrow.php b/tests/Features/Expect/toThrow.php new file mode 100644 index 00000000..434ced44 --- /dev/null +++ b/tests/Features/Expect/toThrow.php @@ -0,0 +1,60 @@ +toThrow(RuntimeException::class); + expect(function () { throw new RuntimeException(); })->toThrow(Exception::class); + expect(function () { throw new RuntimeException(); })->toThrow(function (RuntimeException $e) {}); + expect(function () { throw new RuntimeException('actual message'); })->toThrow(function (Exception $e) { + expect($e->getMessage())->toBe('actual message'); + }); + expect(function () {})->not->toThrow(Exception::class); + expect(function () { throw new RuntimeException('actual message'); })->toThrow('actual message'); + expect(function () { throw new Exception(); })->not->toThrow(RuntimeException::class); + expect(function () { throw new RuntimeException('actual message'); })->toThrow(RuntimeException::class, 'actual message'); + expect(function () { throw new RuntimeException('actual message'); })->toThrow(function (RuntimeException $e) {}, 'actual message'); +}); + +test('failures 1', function () { + expect(function () {})->toThrow(RuntimeException::class); +})->throws(ExpectationFailedException::class, 'Exception "' . RuntimeException::class . '" not thrown.'); + +test('failures 2', function () { + expect(function () {})->toThrow(function (RuntimeException $e) {}); +})->throws(ExpectationFailedException::class, 'Exception "' . RuntimeException::class . '" not thrown.'); + +test('failures 3', function () { + expect(function () { throw new Exception(); })->toThrow(function (RuntimeException $e) {}); +})->throws(ExpectationFailedException::class, 'Failed asserting that Exception Object'); + +test('failures 4', function () { + expect(function () { throw new Exception('actual message'); }) + ->toThrow(function (Exception $e) { + expect($e->getMessage())->toBe('expected message'); + }); +})->throws(ExpectationFailedException::class, 'Failed asserting that two strings are identical'); + +test('failures 5', function () { + expect(function () { throw new Exception('actual message'); })->toThrow('expected message'); +})->throws(ExpectationFailedException::class, 'Failed asserting that \'actual message\' contains "expected message".'); + +test('failures 6', function () { + expect(function () {})->toThrow('actual message'); +})->throws(ExpectationFailedException::class, 'Exception with message "actual message" not thrown'); + +test('failures 7', function () { + expect(function () { throw new RuntimeException('actual message'); })->toThrow(RuntimeException::class, 'expected message'); +})->throws(ExpectationFailedException::class); + +test('not failures', function () { + expect(function () { throw new RuntimeException(); })->not->toThrow(RuntimeException::class); +})->throws(ExpectationFailedException::class); + +test('closure missing parameter', function () { + expect(function () {})->toThrow(function () {}); +})->throws(InvalidArgumentException::class, 'The given closure must have a single parameter type-hinted as the class string.'); + +test('closure missing type-hint', function () { + expect(function () {})->toThrow(function ($e) {}); +})->throws(InvalidArgumentException::class, 'The given closure\'s parameter must be type-hinted as the class string.'); diff --git a/tests/Hooks/BeforeAllTest.php b/tests/Hooks/BeforeAllTest.php index 05e57252..66f5801b 100644 --- a/tests/Hooks/BeforeAllTest.php +++ b/tests/Hooks/BeforeAllTest.php @@ -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) { diff --git a/tests/PHPUnit/CustomTestCaseInSubFolders/SubFolder/SubFolder/CustomTestCaseInSubFolder.php b/tests/PHPUnit/CustomTestCaseInSubFolders/SubFolder/SubFolder/CustomTestCaseInSubFolder.php index ee6b1489..205c227a 100644 --- a/tests/PHPUnit/CustomTestCaseInSubFolders/SubFolder/SubFolder/CustomTestCaseInSubFolder.php +++ b/tests/PHPUnit/CustomTestCaseInSubFolders/SubFolder/SubFolder/CustomTestCaseInSubFolder.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Tests\SubFolder\SubFolder\SubFolder; +namespace Tests\CustomTestCaseInSubFolders\SubFolder\SubFolder; use PHPUnit\Framework\TestCase; diff --git a/tests/PHPUnit/Pest.php b/tests/PHPUnit/Pest.php deleted file mode 100644 index 0a886265..00000000 --- a/tests/PHPUnit/Pest.php +++ /dev/null @@ -1,3 +0,0 @@ -in('CustomTestCaseInSubFolders/SubFolder'); diff --git a/tests/Pest.php b/tests/Pest.php index d3fe584f..429bf74c 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -1,5 +1,9 @@ in('PHPUnit/CustomTestCaseInSubFolders/SubFolder/SubFolder'); + uses()->group('integration')->in('Visual'); // NOTE: global test value container to be mutated and checked across files, as needed diff --git a/tests/Unit/TestSuite.php b/tests/Unit/TestSuite.php index 62cc724d..7d6c88a9 100644 --- a/tests/Unit/TestSuite.php +++ b/tests/Unit/TestSuite.php @@ -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__, + ]); +}); diff --git a/tests/Visual/Success.php b/tests/Visual/Success.php index 8c5e1d6f..4885255e 100644 --- a/tests/Visual/Success.php +++ b/tests/Visual/Success.php @@ -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();