feat: pr and issue

This commit is contained in:
Nuno Maduro
2024-07-04 00:53:58 +01:00
parent 09ca7a1fd5
commit ee32f25485
26 changed files with 423 additions and 53 deletions

View File

@ -4,7 +4,9 @@
use Pest\Kernel; use Pest\Kernel;
use Pest\Panic; use Pest\Panic;
use Pest\TestCaseFilters\GitDirtyTestCaseFilter; use Pest\TestCaseFilters\GitDirtyTestCaseFilter;
use Pest\TestCaseMethodFilters\IssueTestCaseFilter;
use Pest\TestCaseMethodFilters\NotesTestCaseFilter; use Pest\TestCaseMethodFilters\NotesTestCaseFilter;
use Pest\TestCaseMethodFilters\PrTestCaseFilter;
use Pest\TestCaseMethodFilters\TodoTestCaseFilter; use Pest\TestCaseMethodFilters\TodoTestCaseFilter;
use Pest\TestSuite; use Pest\TestSuite;
use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\ArgvInput;
@ -21,6 +23,7 @@ use Symfony\Component\Console\Output\ConsoleOutput;
$notes = false; $notes = false;
foreach ($arguments as $key => $value) { foreach ($arguments as $key => $value) {
if ($value === '--compact') { if ($value === '--compact') {
$_SERVER['COLLISION_PRINTER_COMPACT'] = 'true'; $_SERVER['COLLISION_PRINTER_COMPACT'] = 'true';
unset($arguments[$key]); unset($arguments[$key]);
@ -31,8 +34,14 @@ use Symfony\Component\Console\Output\ConsoleOutput;
unset($arguments[$key]); unset($arguments[$key]);
} }
if (str_contains($value, '--test-directory')) { if (str_contains($value, '--test-directory=')) {
unset($arguments[$key]); unset($arguments[$key]);
} else if ($value === '--test-directory') {
unset($arguments[$key]);
if (isset($arguments[$key + 1])) {
unset($arguments[$key + 1]);
}
} }
if ($value === '--dirty') { if ($value === '--dirty') {
@ -50,6 +59,46 @@ use Symfony\Component\Console\Output\ConsoleOutput;
unset($arguments[$key]); unset($arguments[$key]);
} }
if (str_contains($value, '--issue=')) {
unset($arguments[$key]);
} else if ($value === '--issue') {
unset($arguments[$key]);
if (isset($arguments[$key + 1])) {
unset($arguments[$key + 1]);
}
}
if (str_contains($value, '--ticket=')) {
unset($arguments[$key]);
} else if ($value === '--ticket') {
unset($arguments[$key]);
if (isset($arguments[$key + 1])) {
unset($arguments[$key + 1]);
}
}
if (str_contains($value, '--pr=')) {
unset($arguments[$key]);
} else if ($value === '--pr') {
unset($arguments[$key]);
if (isset($arguments[$key + 1])) {
unset($arguments[$key + 1]);
}
}
if (str_contains($value, '--pull-request=')) {
unset($arguments[$key]);
} else if ($value === '--pull-request') {
unset($arguments[$key]);
if (isset($arguments[$key + 1])) {
unset($arguments[$key + 1]);
}
}
if (str_contains($value, '--teamcity')) { if (str_contains($value, '--teamcity')) {
unset($arguments[$key]); unset($arguments[$key]);
$arguments[] = '--no-output'; $arguments[] = '--no-output';
@ -57,6 +106,7 @@ use Symfony\Component\Console\Output\ConsoleOutput;
} }
} }
// Used when Pest is required using composer. // Used when Pest is required using composer.
$vendorPath = dirname(__DIR__, 4).'/vendor/autoload.php'; $vendorPath = dirname(__DIR__, 4).'/vendor/autoload.php';
@ -92,6 +142,22 @@ use Symfony\Component\Console\Output\ConsoleOutput;
$testSuite->tests->addTestCaseMethodFilter(new NotesTestCaseFilter()); $testSuite->tests->addTestCaseMethodFilter(new NotesTestCaseFilter());
} }
if ($issue = $input->getParameterOption('--issue')) {
$testSuite->tests->addTestCaseMethodFilter(new IssueTestCaseFilter((int) $issue));
}
if ($issue = $input->getParameterOption('--ticket')) {
$testSuite->tests->addTestCaseMethodFilter(new IssueTestCaseFilter((int) $issue));
}
if ($pr = $input->getParameterOption('--pr')) {
$testSuite->tests->addTestCaseMethodFilter(new PrTestCaseFilter((int) $pr));
}
if ($pr = $input->getParameterOption('--pull-request')) {
$testSuite->tests->addTestCaseMethodFilter(new PrTestCaseFilter((int) $pr));
}
$isDecorated = $input->getParameterOption('--colors', 'always') !== 'never'; $isDecorated = $input->getParameterOption('--colors', 'always') !== 'never';
$output = new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, $isDecorated); $output = new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, $isDecorated);

View File

@ -50,7 +50,7 @@ final class Laravel extends AbstractPreset
->classes() ->classes()
->toHaveMethod('handle'); ->toHaveMethod('handle');
$this->expectations[] = expect('App\Models') $this->expectations[] = expect('App\Models') // @phpstan-ignore-line
->classes() ->classes()
->toExtend('Illuminate\Database\Eloquent\Model') ->toExtend('Illuminate\Database\Eloquent\Model')
->not->toHaveSuffix('Model'); ->not->toHaveSuffix('Model');
@ -62,7 +62,7 @@ final class Laravel extends AbstractPreset
$this->expectations[] = expect('App\Http\Requests') $this->expectations[] = expect('App\Http\Requests')
->classes() ->classes()
->toHaveSuffix('Request') ->toHaveSuffix('Request')
->toExtend('Illuminate\Foundation\Http\FormRequest') // @phpstan-ignore-line ->toExtend('Illuminate\Foundation\Http\FormRequest')
->toHaveMethod('rules'); ->toHaveMethod('rules');
$this->expectations[] = expect('App') $this->expectations[] = expect('App')
@ -72,7 +72,7 @@ final class Laravel extends AbstractPreset
$this->expectations[] = expect('App\Console\Commands') $this->expectations[] = expect('App\Console\Commands')
->classes() ->classes()
->toHaveSuffix('Command') ->toHaveSuffix('Command')
->toExtend('Illuminate\Console\Command') // @phpstan-ignore-line ->toExtend('Illuminate\Console\Command')
->toHaveMethod('handle'); ->toHaveMethod('handle');
$this->expectations[] = expect('App') $this->expectations[] = expect('App')
@ -81,7 +81,7 @@ final class Laravel extends AbstractPreset
$this->expectations[] = expect('App\Mail') $this->expectations[] = expect('App\Mail')
->classes() ->classes()
->toExtend('Illuminate\Mail\Mailable'); // @phpstan-ignore-line ->toExtend('Illuminate\Mail\Mailable');
$this->expectations[] = expect('App') $this->expectations[] = expect('App')
->not->toExtend('Illuminate\Mail\Mailable') ->not->toExtend('Illuminate\Mail\Mailable')
@ -101,7 +101,7 @@ final class Laravel extends AbstractPreset
->toHaveMethod('handle'); ->toHaveMethod('handle');
$this->expectations[] = expect('App\Notifications') $this->expectations[] = expect('App\Notifications')
->toExtend('Illuminate\Notifications\Notification'); // @phpstan-ignore-line ->toExtend('Illuminate\Notifications\Notification');
$this->expectations[] = expect('App') $this->expectations[] = expect('App')
->not->toExtend('Illuminate\Notifications\Notification') ->not->toExtend('Illuminate\Notifications\Notification')
@ -109,10 +109,10 @@ final class Laravel extends AbstractPreset
$this->expectations[] = expect('App\Providers') // @phpstan-ignore-line $this->expectations[] = expect('App\Providers') // @phpstan-ignore-line
->toHaveSuffix('ServiceProvider') ->toHaveSuffix('ServiceProvider')
->toExtend('Illuminate\Support\ServiceProvider') // @phpstan-ignore-line ->toExtend('Illuminate\Support\ServiceProvider')
->not->toBeUsed(); ->not->toBeUsed();
$this->expectations[] = expect('App') $this->expectations[] = expect('App') // @phpstan-ignore-line
->not->toExtend('Illuminate\Support\ServiceProvider') ->not->toExtend('Illuminate\Support\ServiceProvider')
->not->toHaveSuffix('ServiceProvider') ->not->toHaveSuffix('ServiceProvider')
->ignoring('App\Providers'); ->ignoring('App\Providers');

View File

@ -29,15 +29,29 @@ trait Testable
*/ */
private string $__description; private string $__description;
/**
* The test's latest description.
*/
private static string $__latestDescription;
/** /**
* The test's notes. * The test's notes.
*/ */
private static array $__latestNotes = []; private static array $__latestNotes = [];
/** /**
* The test's latest description. * The test's issues.
*
* @var array<int, int>
*/ */
private static string $__latestDescription; private static array $__latestIssues = [];
/**
* The test's PRs.
*
* @var array<int, int>
*/
private static array $__latestPrs = [];
/** /**
* The test's describing, if any. * The test's describing, if any.
@ -79,27 +93,6 @@ trait Testable
*/ */
private array $__snapshotChanges = []; private array $__snapshotChanges = [];
/**
* Adds a new "note" to the Test Case.
*/
public function note(array|string $note): self
{
$note = is_array($note) ? $note : [$note];
self::$__latestNotes = array_merge(self::$__latestNotes, $note);
return $this;
}
/**
* Resets the test case static properties.
*/
public static function flush(): void
{
self::$__beforeAll = null;
self::$__afterAll = null;
}
/** /**
* Creates a new Test Case instance. * Creates a new Test Case instance.
*/ */
@ -113,11 +106,34 @@ trait Testable
$method = $test->getMethod($name); $method = $test->getMethod($name);
$this->__description = self::$__latestDescription = $method->description; $this->__description = self::$__latestDescription = $method->description;
self::$__latestNotes = $method->notes; self::$__latestNotes = $method->notes;
self::$__latestIssues = $method->issues;
self::$__latestPrs = $method->prs;
$this->__describing = $method->describing; $this->__describing = $method->describing;
$this->__test = $method->getClosure($this); $this->__test = $method->getClosure($this);
} }
} }
/**
* Resets the test case static properties.
*/
public static function flush(): void
{
self::$__beforeAll = null;
self::$__afterAll = null;
}
/**
* Adds a new "note" to the Test Case.
*/
public function note(array|string $note): self
{
$note = is_array($note) ? $note : [$note];
self::$__latestNotes = array_merge(self::$__latestNotes, $note);
return $this;
}
/** /**
* Adds a new "setUpBeforeClass" to the Test Case. * Adds a new "setUpBeforeClass" to the Test Case.
*/ */
@ -243,6 +259,8 @@ trait Testable
$this->__description = self::$__latestDescription = $description; $this->__description = self::$__latestDescription = $description;
self::$__latestNotes = $method->notes; self::$__latestNotes = $method->notes;
self::$__latestIssues = $method->issues;
self::$__latestPrs = $method->prs;
parent::setUp(); parent::setUp();
@ -432,4 +450,20 @@ trait Testable
{ {
return self::$__latestNotes; return self::$__latestNotes;
} }
/**
* The latest printable test case issues.
*/
public static function getPrintableTestCaseMethodIssues(): array
{
return self::$__latestIssues;
}
/**
* The latest printable test case PRs.
*/
public static function getPrintableTestCaseMethodPrs(): array
{
return self::$__latestPrs;
}
} }

View File

@ -75,4 +75,12 @@ final class Configuration
{ {
return new Configuration\Theme(); return new Configuration\Theme();
} }
/**
* Gets the context configuration.
*/
public function context(): Configuration\Context
{
return new Configuration\Context();
}
} }

View File

@ -0,0 +1,67 @@
<?php
declare(strict_types=1);
namespace Pest\Configuration;
use NunoMaduro\Collision\Adapters\Phpunit\Printers\DefaultPrinter;
/**
* @internal
*/
final readonly class Context
{
/**
* Sets the test context to GitHub.
*/
public function github(string $project): self
{
DefaultPrinter::linkIssuesWith("https://github.com/{$project}/issues/%s");
DefaultPrinter::linkPrsWith("https://github.com/{$project}/pull/%s");
return $this;
}
/**
* Sets the test context to GitLab.
*/
public function gitlab(string $project): self
{
DefaultPrinter::linkIssuesWith("https://gitlab.com/{$project}/issues/%s");
DefaultPrinter::linkPrsWith("https://gitlab.com/{$project}/merge_requests/%s");
return $this;
}
/**
* Sets the test context to Bitbucket.
*/
public function bitbucket(string $project): self
{
DefaultPrinter::linkIssuesWith('https://bitbucket.org/{$project}/issues/%s');
DefaultPrinter::linkPrsWith("https://bitbucket.org/{$project}/pull-requests/%s");
return $this;
}
/**
* Sets the test context to Jira.
*/
public function jira(string $namespace, string $project): self
{
DefaultPrinter::linkIssuesWith("https://{$namespace}.atlassian.net/browse/{$project}-%s");
return $this;
}
/**
* Sets the test context to custom.
*/
public function using(string $issues, string $prs): self
{
DefaultPrinter::linkIssuesWith($issues);
DefaultPrinter::linkPrsWith($prs);
return $this;
}
}

View File

@ -585,8 +585,6 @@ final class Expectation
/** /**
* Asserts that the given expectation target to be subclass of the given class. * Asserts that the given expectation target to be subclass of the given class.
*
* @param class-string $class
*/ */
public function toExtend(string $class): ArchExpectation public function toExtend(string $class): ArchExpectation
{ {
@ -660,7 +658,7 @@ final class Expectation
/** /**
* Asserts that the given expectation target to only implement the given interfaces. * Asserts that the given expectation target to only implement the given interfaces.
* *
* @param array<int, class-string>|class-string $interfaces * @param array<int, string>|string $interfaces
*/ */
public function toOnlyImplement(array|string $interfaces): ArchExpectation public function toOnlyImplement(array|string $interfaces): ArchExpectation
{ {
@ -704,7 +702,7 @@ final class Expectation
/** /**
* Asserts that the given expectation target to implement the given interfaces. * Asserts that the given expectation target to implement the given interfaces.
* *
* @param array<int, class-string>|class-string $interfaces * @param array<int, string>|string $interfaces
*/ */
public function toImplement(array|string $interfaces): ArchExpectation public function toImplement(array|string $interfaces): ArchExpectation
{ {
@ -888,8 +886,6 @@ final class Expectation
/** /**
* Asserts that the given expectation target to have the given attribute. * Asserts that the given expectation target to have the given attribute.
*
* @param class-string<Attribute> $attribute
*/ */
public function toHaveAttribute(string $attribute): ArchExpectation public function toHaveAttribute(string $attribute): ArchExpectation
{ {

View File

@ -226,8 +226,6 @@ final class OppositeExpectation
/** /**
* Asserts that the given expectation target to be not subclass of the given class. * Asserts that the given expectation target to be not subclass of the given class.
*
* @param class-string $class
*/ */
public function toExtend(string $class): ArchExpectation public function toExtend(string $class): ArchExpectation
{ {
@ -288,7 +286,7 @@ final class OppositeExpectation
/** /**
* Asserts that the given expectation target not to implement the given interfaces. * Asserts that the given expectation target not to implement the given interfaces.
* *
* @param array<int, class-string>|string $interfaces * @param array<int, string>|string $interfaces
*/ */
public function toImplement(array|string $interfaces): ArchExpectation public function toImplement(array|string $interfaces): ArchExpectation
{ {
@ -421,8 +419,6 @@ final class OppositeExpectation
/** /**
* Asserts that the given expectation target not to have the given attribute. * Asserts that the given expectation target not to have the given attribute.
*
* @param class-string<Attribute> $attribute
*/ */
public function toHaveAttribute(string $attribute): ArchExpectation public function toHaveAttribute(string $attribute): ArchExpectation
{ {

View File

@ -49,6 +49,20 @@ final class TestCaseMethodFactory
*/ */
public bool $todo = false; public bool $todo = false;
/**
* The associated issue numbers.
*
* @var array<int, int>
*/
public array $issues = [];
/**
* The associated PRs numbers.
*
* @var array<int, int>
*/
public array $prs = [];
/** /**
* The test's notes. * The test's notes.
* *

View File

@ -18,6 +18,11 @@ final class DescribeCall
*/ */
private static ?string $describing = null; private static ?string $describing = null;
/**
* The describe "before each" call.
*/
private ?BeforeEachCall $currentBeforeEachCall = null;
/** /**
* Creates a new Pending Call. * Creates a new Pending Call.
*/ */
@ -43,6 +48,8 @@ final class DescribeCall
*/ */
public function __destruct() public function __destruct()
{ {
unset($this->currentBeforeEachCall);
self::$describing = $this->description; self::$describing = $this->description;
try { try {
@ -57,14 +64,18 @@ final class DescribeCall
* *
* @param array<int, mixed> $arguments * @param array<int, mixed> $arguments
*/ */
public function __call(string $name, array $arguments): BeforeEachCall public function __call(string $name, array $arguments): self
{ {
$filename = Backtrace::file(); $filename = Backtrace::file();
$beforeEachCall = new BeforeEachCall(TestSuite::getInstance(), $filename); if (! $this->currentBeforeEachCall instanceof \Pest\PendingCalls\BeforeEachCall) {
$this->currentBeforeEachCall = new BeforeEachCall(TestSuite::getInstance(), $filename);
$beforeEachCall->describing = $this->description; $this->currentBeforeEachCall->describing = $this->description;
}
return $beforeEachCall->{$name}(...$arguments); // @phpstan-ignore-line $this->currentBeforeEachCall->{$name}(...$arguments); // @phpstan-ignore-line
return $this;
} }
} }

View File

@ -364,6 +364,48 @@ final class TestCall
return $this; return $this;
} }
/**
* Associates the test with the given issue(s).
*
* @param array<int, string|int>|string|int $number
*/
public function issue(array|string|int $number): self
{
$number = is_array($number) ? $number : [$number];
$number = array_map(fn (string|int $number): int => (int) ltrim((string) $number, '#'), $number);
$this->testCaseMethod->issues = array_merge($this->testCaseMethod->issues, $number);
return $this;
}
/**
* Associates the test with the given ticket(s). (Alias for `issue`)
*
* @param array<int, string|int>|string|int $number
*/
public function ticket(array|string|int $number): self
{
return $this->issue($number);
}
/**
* Associates the test with the given pull request(s).
*
* @param array<int, string|int>|string|int $number
*/
public function pr(array|string|int $number): self
{
$number = is_array($number) ? $number : [$number];
$number = array_map(fn (string|int $number): int => (int) ltrim((string) $number, '#'), $number);
$this->testCaseMethod->prs = array_merge($this->testCaseMethod->issues, $number);
return $this;
}
/** /**
* Adds a note to the test. * Adds a note to the test.
* *

View File

@ -21,7 +21,7 @@ trait HandleArguments
return true; return true;
} }
if (str_starts_with((string) $arg, "$argument=")) { if (str_starts_with((string) $arg, "$argument=")) { // @phpstan-ignore-line
return true; return true;
} }
} }

View File

@ -126,6 +126,18 @@ final class Help implements HandlesArguments
], [ ], [
'arg' => '--notes', 'arg' => '--notes',
'desc' => 'Output to standard output tests with notes', 'desc' => 'Output to standard output tests with notes',
], [
], [
'arg' => '--issue',
'desc' => 'Output to standard output tests with the given issue number',
], [
], [
'arg' => '--pr',
'desc' => 'Output to standard output tests with the given pull request number',
], [
], [
'arg' => '--pull-request',
'desc' => 'Output to standard output tests with the given pull request number (alias for --pr)',
], [ ], [
'arg' => '--retry', 'arg' => '--retry',
'desc' => 'Run non-passing tests first and stop execution upon first error or failure', 'desc' => 'Run non-passing tests first and stop execution upon first error or failure',

View File

@ -34,7 +34,7 @@ final class Parallel implements HandlesArguments
/** /**
* @var string[] * @var string[]
*/ */
private const UNSUPPORTED_ARGUMENTS = ['--todo', '--todos', '--retry', '--notes']; private const UNSUPPORTED_ARGUMENTS = ['--todo', '--todos', '--retry', '--notes', '--issue', '--pr', '--pull-request'];
/** /**
* Whether the given command line arguments indicate that the test suite should be run in parallel. * Whether the given command line arguments indicate that the test suite should be run in parallel.

View File

@ -198,6 +198,8 @@ final class Coverage
$array = []; $array = [];
foreach (array_filter($file->lineCoverageData(), is_array(...)) as $line => $tests) { foreach (array_filter($file->lineCoverageData(), is_array(...)) as $line => $tests) {
assert(is_array($tests));
$array = $eachLine($array, $tests, $line); $array = $eachLine($array, $tests, $line);
} }

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Pest\TestCaseMethodFilters;
use Pest\Contracts\TestCaseMethodFilter;
use Pest\Factories\TestCaseMethodFactory;
final readonly class IssueTestCaseFilter implements TestCaseMethodFilter
{
/**
* Create a new filter instance.
*/
public function __construct(private int $number)
{
//
}
/**
* Filter the test case methods.
*/
public function accept(TestCaseMethodFactory $factory): bool
{
return in_array($this->number, $factory->issues, true);
}
}

View File

@ -7,7 +7,7 @@ namespace Pest\TestCaseMethodFilters;
use Pest\Contracts\TestCaseMethodFilter; use Pest\Contracts\TestCaseMethodFilter;
use Pest\Factories\TestCaseMethodFactory; use Pest\Factories\TestCaseMethodFactory;
final class NotesTestCaseFilter implements TestCaseMethodFilter final readonly class NotesTestCaseFilter implements TestCaseMethodFilter
{ {
public function accept(TestCaseMethodFactory $factory): bool public function accept(TestCaseMethodFactory $factory): bool
{ {

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Pest\TestCaseMethodFilters;
use Pest\Contracts\TestCaseMethodFilter;
use Pest\Factories\TestCaseMethodFactory;
final readonly class PrTestCaseFilter implements TestCaseMethodFilter
{
/**
* Create a new filter instance.
*/
public function __construct(private int $number)
{
//
}
/**
* Filter the test case methods.
*/
public function accept(TestCaseMethodFactory $factory): bool
{
return in_array($this->number, $factory->prs, true);
}
}

View File

@ -7,8 +7,11 @@ namespace Pest\TestCaseMethodFilters;
use Pest\Contracts\TestCaseMethodFilter; use Pest\Contracts\TestCaseMethodFilter;
use Pest\Factories\TestCaseMethodFactory; use Pest\Factories\TestCaseMethodFactory;
final class TodoTestCaseFilter implements TestCaseMethodFilter final readonly class TodoTestCaseFilter implements TestCaseMethodFilter
{ {
/**
* Filter the test case methods.
*/
public function accept(TestCaseMethodFactory $factory): bool public function accept(TestCaseMethodFactory $factory): bool
{ {
return $factory->todo; return $factory->todo;

View File

@ -22,6 +22,9 @@
--bail ........................... Stop execution upon first not-passed test --bail ........................... Stop execution upon first not-passed test
--todos ........................ Output to standard output the list of todos --todos ........................ Output to standard output the list of todos
--notes ......................... Output to standard output tests with notes --notes ......................... Output to standard output tests with notes
--issue ........ Output to standard output tests with the given issue number
--pr .... Output to standard output tests with the given pull request number
--pull-request Output to standard output tests with the given pull request number (alias for --pr)
--retry Run non-passing tests first and stop execution upon first error or failure --retry Run non-passing tests first and stop execution upon first error or failure
--list-suites ................................... List available test suites --list-suites ................................... List available test suites
--testsuite [name] ......... Only run tests from the specified test suite(s) --testsuite [name] ......... Only run tests from the specified test suite(s)

View File

@ -991,6 +991,11 @@
✓ it is not incompleted because of test with assertions ✓ it is not incompleted because of test with assertions
… a "describe" group of tests → it is incompleted … a "describe" group of tests → it is incompleted
PASS Tests\Features\Issue
✓ it may be associated with an issue #1, #2
✓ nested → it may be associated with an issue #1, #4, #5, #6, #3
// an note between an the issue
PASS Tests\Features\It PASS Tests\Features\It
✓ it is a test ✓ it is a test
✓ it is a higher order message test ✓ it is a higher order message test
@ -1027,6 +1032,11 @@
! notice → This is a notice description // tests/Features/Notices.php:4 ! notice → This is a notice description // tests/Features/Notices.php:4
! a "describe" group of tests → notice → This is a notice description // tests/Features/Notices.php:11 ! a "describe" group of tests → notice → This is a notice description // tests/Features/Notices.php:11
PASS Tests\Features\Pr
✓ it may be associated with an pr #2
✓ nested → it may be associated with an pr #3
// an note between an the pr
PASS Tests\Features\Repeat PASS Tests\Features\Repeat
✓ once ✓ once
✓ multiple times @ repetition 1 of 5 ✓ multiple times @ repetition 1 of 5
@ -1212,6 +1222,11 @@
✓ it allows performing no expectations without being risky ✓ it allows performing no expectations without being risky
✓ a "describe" group of tests → it allows performing no expectations without being risky ✓ a "describe" group of tests → it allows performing no expectations without being risky
PASS Tests\Features\Ticket
✓ it may be associated with an ticket #1, #2
✓ nested → it may be associated with an ticket #1, #4, #5, #6, #3
// an note between an the ticket
PASS Tests\Features\Todo - 3 todos PASS Tests\Features\Todo - 3 todos
↓ something todo later ↓ something todo later
↓ something todo later chained ↓ something todo later chained
@ -1501,4 +1516,4 @@
WARN Tests\Visual\Version WARN Tests\Visual\Version
- visual snapshot of help command output - visual snapshot of help command output
Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 13 todos, 24 skipped, 1057 passed (2588 assertions) Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 13 todos, 24 skipped, 1063 passed (2602 assertions)

View File

@ -119,7 +119,7 @@ describe('something 2', function () {
$this->count++; $this->count++;
})->after(function () { })->after(function () {
expect($this->count)->toBe(4); expect($this->count)->toBe(6);
$this->count++; $this->count++;
}); });

15
tests/Features/Issue.php Normal file
View File

@ -0,0 +1,15 @@
<?php
beforeEach(function () {
expect(true)->toBeTrue();
})->issue(1);
it('may be associated with an issue', function () {
expect(true)->toBeTrue();
})->issue(2);
describe('nested', function () {
it('may be associated with an issue', function () {
expect(true)->toBeTrue();
})->issue('#3');
})->issue(4)->note('an note between an the issue')->issue([5, 6]);

15
tests/Features/Pr.php Normal file
View File

@ -0,0 +1,15 @@
<?php
beforeEach(function () {
expect(true)->toBeTrue();
})->pr(1);
it('may be associated with an pr', function () {
expect(true)->toBeTrue();
})->pr(2);
describe('nested', function () {
it('may be associated with an pr', function () {
expect(true)->toBeTrue();
})->pr('#3');
})->pr(4)->note('an note between an the pr')->pr(['#5', 6]);

15
tests/Features/Ticket.php Normal file
View File

@ -0,0 +1,15 @@
<?php
beforeEach(function () {
expect(true)->toBeTrue();
})->ticket(1);
it('may be associated with an ticket', function () {
expect(true)->toBeTrue();
})->ticket(2);
describe('nested', function () {
it('may be associated with an ticket', function () {
expect(true)->toBeTrue();
})->ticket(3);
})->ticket(4)->note('an note between an the ticket')->ticket([5, 6]);

View File

@ -7,6 +7,8 @@ error_reporting(E_ALL);
$GLOBALS['__PEST_INTERNAL_TEST_SUITE'] = true; $GLOBALS['__PEST_INTERNAL_TEST_SUITE'] = true;
pest()->context()->github('pestphp/pest');
pest()->in('PHPUnit/CustomTestCaseInSubFolders/SubFolder/SubFolder')->use(CustomTestCaseInSubFolder::class); pest()->in('PHPUnit/CustomTestCaseInSubFolders/SubFolder/SubFolder')->use(CustomTestCaseInSubFolder::class);
// test case for all the directories inside PHPUnit/GlobPatternTests/SubFolder/ // test case for all the directories inside PHPUnit/GlobPatternTests/SubFolder/

View File

@ -16,7 +16,7 @@ $run = function () {
test('parallel', function () use ($run) { test('parallel', function () use ($run) {
expect($run('--exclude-group=integration')) expect($run('--exclude-group=integration'))
->toContain('Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 13 todos, 19 skipped, 1043 passed (2556 assertions)') ->toContain('Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 13 todos, 19 skipped, 1049 passed (2570 assertions)')
->toContain('Parallel: 3 processes'); ->toContain('Parallel: 3 processes');
})->skipOnWindows(); })->skipOnWindows();