diff --git a/composer.json b/composer.json index c223f0fb..a32a3185 100644 --- a/composer.json +++ b/composer.json @@ -50,9 +50,11 @@ }, "require-dev": { "pestphp/pest-dev-tools": "^2.12.0", + "pestphp/pest-plugin-type-coverage": "^2.0.0", "symfony/process": "^6.3.0" }, - "minimum-stability": "stable", + "minimum-stability": "dev", + "prefer-stable": true, "config": { "sort-packages": true, "preferred-install": "dist", diff --git a/src/Expectation.php b/src/Expectation.php index df7d095b..893cc049 100644 --- a/src/Expectation.php +++ b/src/Expectation.php @@ -381,9 +381,7 @@ final class Expectation $this, fn (ObjectDescription $object): bool => str_contains((string) file_get_contents($object->path), 'declare(strict_types=1);'), 'to use strict types', - FileLineFinder::where(function (string $line): bool { - return str_contains($line, ' str_contains($line, ' $object->reflectionClass->isFinal(), 'to be final', - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -411,9 +407,7 @@ final class Expectation $this, fn (ObjectDescription $object): bool => $object->reflectionClass->isReadOnly(), 'to be readonly', - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -426,9 +420,7 @@ final class Expectation $this, fn (ObjectDescription $object): bool => $object->reflectionClass->isTrait(), 'to be trait', - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -449,9 +441,7 @@ final class Expectation $this, fn (ObjectDescription $object): bool => $object->reflectionClass->isAbstract(), 'to be abstract', - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -464,9 +454,7 @@ final class Expectation $this, fn (ObjectDescription $object): bool => $object->reflectionClass->isEnum(), 'to be enum', - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -487,9 +475,7 @@ final class Expectation $this, fn (ObjectDescription $object): bool => $object->reflectionClass->isInterface(), 'to be interface', - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -512,9 +498,7 @@ final class Expectation $this, fn (ObjectDescription $object): bool => $object->reflectionClass->isSubclassOf($class), sprintf("to extend '%s'", $class), - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -527,9 +511,7 @@ final class Expectation $this, fn (ObjectDescription $object): bool => $object->reflectionClass->getParentClass() === false, 'to extend nothing', - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -542,9 +524,7 @@ final class Expectation $this, fn (ObjectDescription $object): bool => $object->reflectionClass->getInterfaceNames() === [], 'to implement nothing', - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -562,9 +542,7 @@ final class Expectation fn (ObjectDescription $object): bool => count($interfaces) === count($object->reflectionClass->getInterfaceNames()) && array_diff($interfaces, $object->reflectionClass->getInterfaceNames()) === [], "to only implement '".implode("', '", $interfaces)."'", - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -577,9 +555,7 @@ final class Expectation $this, fn (ObjectDescription $object): bool => str_ends_with($object->reflectionClass->getName(), $suffix), "to have suffix '{$suffix}'", - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -592,9 +568,7 @@ final class Expectation $this, fn (ObjectDescription $object): bool => str_starts_with($object->reflectionClass->getName(), $suffix), "to have prefix '{$suffix}'", - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -619,9 +593,7 @@ final class Expectation return true; }, "to implement '".implode("', '", $interfaces)."'", - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } diff --git a/src/Expectations/OppositeExpectation.php b/src/Expectations/OppositeExpectation.php index 3f85ad3b..d84c00f2 100644 --- a/src/Expectations/OppositeExpectation.php +++ b/src/Expectations/OppositeExpectation.php @@ -84,9 +84,7 @@ final class OppositeExpectation $this->original, fn (ObjectDescription $object): bool => ! str_contains((string) file_get_contents($object->path), 'declare(strict_types=1);'), 'not to use strict types', - FileLineFinder::where(function (string $line): bool { - return str_contains($line, ' str_contains($line, 'original, fn (ObjectDescription $object): bool => ! $object->reflectionClass->isFinal(), 'not to be final', - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -114,9 +110,7 @@ final class OppositeExpectation $this->original, fn (ObjectDescription $object): bool => ! $object->reflectionClass->isReadOnly(), 'not to be readonly', - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -129,9 +123,7 @@ final class OppositeExpectation $this->original, fn (ObjectDescription $object): bool => ! $object->reflectionClass->isTrait(), 'not to be trait', - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -144,9 +136,7 @@ final class OppositeExpectation $this->original, fn (ObjectDescription $object): bool => ! $object->reflectionClass->isAbstract(), 'not to be abstract', - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -159,9 +149,7 @@ final class OppositeExpectation $this->original, fn (ObjectDescription $object): bool => ! $object->reflectionClass->isEnum(), 'not to be enum', - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -174,9 +162,7 @@ final class OppositeExpectation $this->original, fn (ObjectDescription $object): bool => ! $object->reflectionClass->isInterface(), 'not to be interface', - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -191,9 +177,7 @@ final class OppositeExpectation $this->original, fn (ObjectDescription $object): bool => ! $object->reflectionClass->isSubclassOf($class), sprintf("not to extend '%s'", $class), - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -206,14 +190,14 @@ final class OppositeExpectation $this->original, fn (ObjectDescription $object): bool => $object->reflectionClass->getParentClass() !== false, 'to extend a class', - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } /** * Asserts that the given expectation target not to implement the given interfaces. + * + * @param array|string $interfaces */ public function toImplement(array|string $interfaces): ArchExpectation { @@ -230,10 +214,8 @@ final class OppositeExpectation return true; }, - "not to implement '".implode("', '", (array) $interfaces)."'", - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + "not to implement '".implode("', '", $interfaces)."'", + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } @@ -243,31 +225,42 @@ final class OppositeExpectation public function toImplementNothing(): ArchExpectation { return Targeted::make( - $this, + $this->original, fn (ObjectDescription $object): bool => $object->reflectionClass->getInterfaceNames() !== [], 'to implement an interface', - FileLineFinder::where(function (string $line): bool { - return str_contains($line, 'class'); - }), + FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')), ); } - public function toOnlyImplement(array|string $interfaces): ArchExpectation + /** + * Not supported. + * + * @param array|string $interfaces + */ + public function toOnlyImplement(array|string $interfaces): never { throw InvalidExpectation::fromMethods(['not', 'toOnlyImplement']); } + /** + * Not supported. + */ public function toHavePrefix(string $suffix): never { throw InvalidExpectation::fromMethods(['not', 'toHavePrefix']); } + /** + * Not supported. + */ public function toHaveSuffix(string $suffix): never { throw InvalidExpectation::fromMethods(['not', 'toHaveSuffix']); } /** + * Not supported. + * * @param array|string $targets */ public function toOnlyUse(array|string $targets): never @@ -275,6 +268,9 @@ final class OppositeExpectation throw InvalidExpectation::fromMethods(['not', 'toOnlyUse']); } + /** + * Not supported. + */ public function toUseNothing(): never { throw InvalidExpectation::fromMethods(['not', 'toUseNothing']); @@ -358,8 +354,13 @@ final class OppositeExpectation $exporter = Exporter::default(); - $toString = fn ($argument): string => $exporter->shortenedExport($argument); + $toString = fn (mixed $argument): string => $exporter->shortenedExport($argument); - throw new ExpectationFailedException(sprintf('Expecting %s not %s %s.', $toString($this->original->value), strtolower((string) preg_replace('/(? $toString($argument), $arguments)))); + throw new ExpectationFailedException(sprintf( + 'Expecting %s not %s %s.', + $toString($this->original->value), + strtolower((string) preg_replace('/(? $toString($argument), $arguments)), + )); } } diff --git a/src/Factories/TestCaseFactory.php b/src/Factories/TestCaseFactory.php index 0b5b66f4..cbe50985 100644 --- a/src/Factories/TestCaseFactory.php +++ b/src/Factories/TestCaseFactory.php @@ -98,7 +98,7 @@ final class TestCaseFactory { if ('\\' === DIRECTORY_SEPARATOR) { // In case Windows, strtolower drive name, like in UsesCall. - $filename = (string) preg_replace_callback('~^(?P[a-z]+:\\\)~i', static fn ($match): string => strtolower($match['drive']), $filename); + $filename = (string) preg_replace_callback('~^(?P[a-z]+:\\\)~i', static fn (array $match): string => strtolower($match['drive']), $filename); } $filename = str_replace('\\\\', '\\', addslashes((string) realpath($filename))); @@ -134,7 +134,7 @@ final class TestCaseFactory $hasPrintableTestCaseClassFQN = sprintf('\%s', HasPrintableTestCaseName::class); $traitsCode = sprintf('use %s;', implode(', ', array_map( - static fn ($trait): string => sprintf('\%s', $trait), $this->traits)) + static fn (string $trait): string => sprintf('\%s', $trait), $this->traits)) ); $partsFQN = explode('\\', $classFQN); diff --git a/src/Factories/TestCaseMethodFactory.php b/src/Factories/TestCaseMethodFactory.php index abeebffb..b4fce58c 100644 --- a/src/Factories/TestCaseMethodFactory.php +++ b/src/Factories/TestCaseMethodFactory.php @@ -147,11 +147,11 @@ final class TestCaseMethodFactory } $annotations = implode('', array_map( - static fn ($annotation): string => sprintf("\n * %s", $annotation), $annotations, + static fn (string $annotation): string => sprintf("\n * %s", $annotation), $annotations, )); $attributes = implode('', array_map( - static fn ($attribute): string => sprintf("\n %s", $attribute), $attributes, + static fn (string $attribute): string => sprintf("\n %s", $attribute), $attributes, )); return << 0) { - $path = (string) preg_replace_callback('~^(?P[a-z]+:\\\)~i', fn ($match): string => strtolower($match['drive']), $path); + $path = (string) preg_replace_callback('~^(?P[a-z]+:\\\)~i', fn (array $match): string => strtolower($match['drive']), $path); $startChar = strtolower((string) preg_replace('~^([a-z]+:\\\).*$~i', '$1', __DIR__)); } diff --git a/src/Plugins/Coverage.php b/src/Plugins/Coverage.php index 07b21232..668ff09f 100644 --- a/src/Plugins/Coverage.php +++ b/src/Plugins/Coverage.php @@ -50,7 +50,7 @@ final class Coverage implements AddsOutput, HandlesArguments */ public function handleArguments(array $originals): array { - $arguments = [...[''], ...array_values(array_filter($originals, function ($original): bool { + $arguments = [...[''], ...array_values(array_filter($originals, function (string $original): bool { foreach ([self::COVERAGE_OPTION, self::MIN_OPTION] as $option) { if ($original === sprintf('--%s', $option)) { return true; diff --git a/src/Plugins/Parallel.php b/src/Plugins/Parallel.php index 1e610c5f..3354b743 100644 --- a/src/Plugins/Parallel.php +++ b/src/Plugins/Parallel.php @@ -115,13 +115,13 @@ final class Parallel implements HandlesArguments private function runTestSuiteInParallel(array $arguments): int { $handlers = array_filter( - array_map(fn ($handler): object|string => Container::getInstance()->get($handler), self::HANDLERS), - fn ($handler): bool => $handler instanceof HandlesArguments, + array_map(fn (string $handler): object|string => Container::getInstance()->get($handler), self::HANDLERS), + fn (object|string $handler): bool => $handler instanceof HandlesArguments, ); $filteredArguments = array_reduce( $handlers, - fn ($arguments, HandlesArguments $handler): array => $handler->handleArguments($arguments), + fn (array $arguments, HandlesArguments $handler): array => $handler->handleArguments($arguments), $arguments ); @@ -139,13 +139,13 @@ final class Parallel implements HandlesArguments private function runWorkerHandlers(array $arguments): array { $handlers = array_filter( - array_map(fn ($handler): object|string => Container::getInstance()->get($handler), self::HANDLERS), - fn ($handler): bool => $handler instanceof HandlersWorkerArguments, + array_map(fn (string $handler): object|string => Container::getInstance()->get($handler), self::HANDLERS), + fn (object|string $handler): bool => $handler instanceof HandlersWorkerArguments, ); return array_reduce( $handlers, - fn ($arguments, HandlersWorkerArguments $handler): array => $handler->handleWorkerArguments($arguments), + fn (array $arguments, HandlersWorkerArguments $handler): array => $handler->handleWorkerArguments($arguments), $arguments ); } diff --git a/src/Plugins/Parallel/Handlers/Parallel.php b/src/Plugins/Parallel/Handlers/Parallel.php index 2e87a521..76a59af6 100644 --- a/src/Plugins/Parallel/Handlers/Parallel.php +++ b/src/Plugins/Parallel/Handlers/Parallel.php @@ -30,7 +30,7 @@ final class Parallel implements HandlesArguments */ public function handleArguments(array $arguments): array { - $args = array_reduce(self::ARGS_TO_REMOVE, fn ($args, $arg): array => $this->popArgument($arg, $args), $arguments); + $args = array_reduce(self::ARGS_TO_REMOVE, fn (array $args, string $arg): array => $this->popArgument($arg, $args), $arguments); return $this->pushArgument('--runner='.WrapperRunner::class, $args); } diff --git a/src/Plugins/Parallel/Paratest/WrapperRunner.php b/src/Plugins/Parallel/Paratest/WrapperRunner.php index c45d6a5a..2a1db6bb 100644 --- a/src/Plugins/Parallel/Paratest/WrapperRunner.php +++ b/src/Plugins/Parallel/Paratest/WrapperRunner.php @@ -23,6 +23,7 @@ use ParaTest\WrapperRunner\WrapperWorker; use Pest\Result; use Pest\TestSuite; use PHPUnit\Event\Facade as EventFacade; +use PHPUnit\Event\TestRunner\WarningTriggered; use PHPUnit\Runner\CodeCoverage; use PHPUnit\TestRunner\TestResult\Facade as TestResultFacade; use PHPUnit\TestRunner\TestResult\TestResult; @@ -317,7 +318,10 @@ final class WrapperRunner implements RunnerInterface $testResultSum->testTriggeredPhpunitErrorEvents(), $testResultSum->testTriggeredPhpunitWarningEvents(), $testResultSum->testRunnerTriggeredDeprecationEvents(), - array_values(array_filter($testResultSum->testRunnerTriggeredWarningEvents(), fn ($event): bool => ! str_contains($event->message(), 'No tests found'))), + array_values(array_filter( + $testResultSum->testRunnerTriggeredWarningEvents(), + fn (WarningTriggered $event): bool => ! str_contains($event->message(), 'No tests found') + )), ); $this->printer->printResults( diff --git a/src/Repositories/DatasetsRepository.php b/src/Repositories/DatasetsRepository.php index 07c4a42c..90ff9e3f 100644 --- a/src/Repositories/DatasetsRepository.php +++ b/src/Repositories/DatasetsRepository.php @@ -66,11 +66,11 @@ final class DatasetsRepository } /** - * @return Closure|array|never + * @return Closure|array * * @throws ShouldNotHappen */ - public static function get(string $filename, string $description) + public static function get(string $filename, string $description): Closure|array { $dataset = self::$withs[$filename.self::SEPARATOR.$description]; @@ -138,7 +138,7 @@ final class DatasetsRepository /** * @param array|string> $datasets - * @return array> + * @return array> */ private static function processDatasets(array $datasets, string $currentTestFile): array { @@ -193,7 +193,7 @@ final class DatasetsRepository $closestScopeDatasetKey = array_reduce( array_keys($matchingDatasets), - fn ($keyA, $keyB) => $keyA !== null && strlen((string) $keyA) > strlen($keyB) ? $keyA : $keyB + fn (string|int|null $keyA, string|int|null $keyB): string|int|null => $keyA !== null && strlen((string) $keyA) > strlen((string) $keyB) ? $keyA : $keyB ); if ($closestScopeDatasetKey === null) { diff --git a/src/Support/Coverage.php b/src/Support/Coverage.php index 526b15fa..6d61b68d 100644 --- a/src/Support/Coverage.php +++ b/src/Support/Coverage.php @@ -159,10 +159,9 @@ final class Coverage * ['11', '20..25', '50', '60..80']; * ``` * - * @param File $file * @return array */ - public static function getMissingCoverage($file): array + public static function getMissingCoverage(File $file): array { $shouldBeNewLine = true; diff --git a/src/Support/ExceptionTrace.php b/src/Support/ExceptionTrace.php index 8d57f1db..0f6dc10b 100644 --- a/src/Support/ExceptionTrace.php +++ b/src/Support/ExceptionTrace.php @@ -18,11 +18,9 @@ final class ExceptionTrace /** * Ensures the given closure reports the good execution context. * - * @return mixed - * * @throws Throwable */ - public static function ensure(Closure $closure) + public static function ensure(Closure $closure): mixed { try { return $closure(); diff --git a/src/Support/ExpectationPipeline.php b/src/Support/ExpectationPipeline.php index 1df555f8..c9d3f6ed 100644 --- a/src/Support/ExpectationPipeline.php +++ b/src/Support/ExpectationPipeline.php @@ -84,6 +84,6 @@ final class ExpectationPipeline */ public function carry(): Closure { - return fn ($stack, $pipe): Closure => fn () => $pipe($stack, ...$this->passables); + return fn (mixed $stack, callable $pipe): Closure => fn () => $pipe($stack, ...$this->passables); } } diff --git a/src/Support/Reflection.php b/src/Support/Reflection.php index 18a71aa6..3a6f2377 100644 --- a/src/Support/Reflection.php +++ b/src/Support/Reflection.php @@ -24,9 +24,8 @@ final class Reflection * Calls the given method with args on the given object. * * @param array $args - * @return mixed */ - public static function call(object $object, string $method, array $args = []) + public static function call(object $object, string $method, array $args = []): mixed { $reflectionClass = new ReflectionClass($object); @@ -53,9 +52,8 @@ final class Reflection * Bind a callable to the TestCase and return the result. * * @param array $args - * @return mixed */ - public static function bindCallable(callable $callable, array $args = []) + public static function bindCallable(callable $callable, array $args = []): mixed { return Closure::fromCallable($callable)->bindTo(TestSuite::getInstance()->test)(...$args); } @@ -63,10 +61,8 @@ final class Reflection /** * Bind a callable to the TestCase and return the result, * passing in the current dataset values as arguments. - * - * @return mixed */ - public static function bindCallableWithData(callable $callable) + public static function bindCallableWithData(callable $callable): mixed { $test = TestSuite::getInstance()->test; @@ -87,10 +83,8 @@ final class Reflection /** * Gets the property value from of the given object. - * - * @return mixed */ - public static function getPropertyValue(object $object, string $property) + public static function getPropertyValue(object $object, string $property): mixed { $reflectionClass = new ReflectionClass($object); @@ -206,10 +200,7 @@ final class Reflection return $arguments; } - /** - * @return mixed - */ - public static function getFunctionVariable(Closure $function, string $key) + public static function getFunctionVariable(Closure $function, string $key): mixed { return (new ReflectionFunction($function))->getStaticVariables()[$key] ?? null; } diff --git a/src/TestCaseFilters/GitDirtyTestCaseFilter.php b/src/TestCaseFilters/GitDirtyTestCaseFilter.php index f881d9a3..dc4f20b3 100644 --- a/src/TestCaseFilters/GitDirtyTestCaseFilter.php +++ b/src/TestCaseFilters/GitDirtyTestCaseFilter.php @@ -59,13 +59,18 @@ final class GitDirtyTestCaseFilter implements TestCaseFilter $dirtyFiles[substr($dirtyFile, 3)] = trim(substr($dirtyFile, 0, 3)); } - $dirtyFiles = array_filter($dirtyFiles, fn ($status): bool => $status !== 'D'); + $dirtyFiles = array_filter($dirtyFiles, fn (string $status): bool => $status !== 'D'); - $dirtyFiles = array_map(fn ($file, $status): string => in_array($status, ['R', 'RM'], true) ? explode(' -> ', $file)[1] : $file, array_keys($dirtyFiles), $dirtyFiles); + $dirtyFiles = array_map( + fn (string $file, string $status): string => in_array($status, ['R', 'RM'], true) + ? explode(' -> ', $file)[1] + : $file, array_keys($dirtyFiles), $dirtyFiles, + ); $dirtyFiles = array_filter( $dirtyFiles, - fn ($file): bool => str_starts_with('.'.DIRECTORY_SEPARATOR.$file, TestSuite::getInstance()->testPath) || str_starts_with($file, TestSuite::getInstance()->testPath) + fn (string $file): bool => str_starts_with('.'.DIRECTORY_SEPARATOR.$file, TestSuite::getInstance()->testPath) + || str_starts_with($file, TestSuite::getInstance()->testPath) ); $dirtyFiles = array_values($dirtyFiles); diff --git a/tests/Visual/Parallel.php b/tests/Visual/Parallel.php index e8ff77d1..b79aa537 100644 --- a/tests/Visual/Parallel.php +++ b/tests/Visual/Parallel.php @@ -18,7 +18,7 @@ $run = function () { test('parallel', function () use ($run) { expect($run('--exclude-group=integration')) - ->toContain('Tests: 1 deprecated, 3 warnings, 4 incomplete, 1 notice, 8 todos, 15 skipped, 707 passed (1720 assertions)') + ->toContain('Tests: 1 deprecated, 4 warnings, 5 incomplete, 2 notices, 13 todos, 15 skipped, 720 passed (1740 assertions)') ->toContain('Parallel: 3 processes'); })->skipOnWindows();