mirror of
https://github.com/pestphp/pest.git
synced 2026-03-06 15:57:21 +01:00
Execute all parent beforeEach and afterEach functions for each test
This commit is contained in:
@ -61,8 +61,10 @@ trait Testable
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The test's describing, if any.
|
* The test's describing, if any.
|
||||||
|
*
|
||||||
|
* @var string[]
|
||||||
*/
|
*/
|
||||||
public ?string $__describing = null;
|
public array $__describing = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the test has ran or not.
|
* Whether the test has ran or not.
|
||||||
|
|||||||
@ -31,8 +31,10 @@ final class TestCaseMethodFactory
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The test's describing, if any.
|
* The test's describing, if any.
|
||||||
|
*
|
||||||
|
* @var string[]
|
||||||
*/
|
*/
|
||||||
public ?string $describing = null;
|
public array $describing = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The test's description, if any.
|
* The test's description, if any.
|
||||||
@ -201,7 +203,7 @@ final class TestCaseMethodFactory
|
|||||||
];
|
];
|
||||||
|
|
||||||
foreach ($this->depends as $depend) {
|
foreach ($this->depends as $depend) {
|
||||||
$depend = Str::evaluable($this->describing !== null ? Str::describe($this->describing, $depend) : $depend);
|
$depend = Str::evaluable($this->describing === [] ? $depend : Str::describe($this->describing, $depend));
|
||||||
|
|
||||||
$this->attributes[] = new Attribute(
|
$this->attributes[] = new Attribute(
|
||||||
\PHPUnit\Framework\Attributes\Depends::class,
|
\PHPUnit\Framework\Attributes\Depends::class,
|
||||||
|
|||||||
@ -43,7 +43,7 @@ if (! function_exists('beforeAll')) {
|
|||||||
*/
|
*/
|
||||||
function beforeAll(Closure $closure): void
|
function beforeAll(Closure $closure): void
|
||||||
{
|
{
|
||||||
if (! is_null(DescribeCall::describing())) {
|
if (DescribeCall::describing() !== []) {
|
||||||
$filename = Backtrace::file();
|
$filename = Backtrace::file();
|
||||||
|
|
||||||
throw new BeforeAllWithinDescribe($filename);
|
throw new BeforeAllWithinDescribe($filename);
|
||||||
@ -205,7 +205,7 @@ if (! function_exists('afterAll')) {
|
|||||||
*/
|
*/
|
||||||
function afterAll(Closure $closure): void
|
function afterAll(Closure $closure): void
|
||||||
{
|
{
|
||||||
if (! is_null(DescribeCall::describing())) {
|
if (DescribeCall::describing() !== []) {
|
||||||
$filename = Backtrace::file();
|
$filename = Backtrace::file();
|
||||||
|
|
||||||
throw new AfterAllWithinDescribe($filename);
|
throw new AfterAllWithinDescribe($filename);
|
||||||
|
|||||||
@ -54,7 +54,7 @@ final class AfterEachCall
|
|||||||
$proxies = $this->proxies;
|
$proxies = $this->proxies;
|
||||||
|
|
||||||
$afterEachTestCase = ChainableClosure::boundWhen(
|
$afterEachTestCase = ChainableClosure::boundWhen(
|
||||||
fn (): bool => is_null($describing) || $this->__describing === $describing,
|
fn (): bool => $describing === [] || in_array(end($describing), $this->__describing, true),
|
||||||
ChainableClosure::bound(fn () => $proxies->chain($this), $this->closure)->bindTo($this, self::class), // @phpstan-ignore-line
|
ChainableClosure::bound(fn () => $proxies->chain($this), $this->closure)->bindTo($this, self::class), // @phpstan-ignore-line
|
||||||
)->bindTo($this, self::class);
|
)->bindTo($this, self::class);
|
||||||
|
|
||||||
|
|||||||
@ -63,12 +63,12 @@ final class BeforeEachCall
|
|||||||
|
|
||||||
$beforeEachTestCall = function (TestCall $testCall) use ($describing): void {
|
$beforeEachTestCall = function (TestCall $testCall) use ($describing): void {
|
||||||
|
|
||||||
if ($this->describing !== null) {
|
if ($this->describing !== []) {
|
||||||
if ($describing !== $this->describing) {
|
if (end($describing) !== end($this->describing)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($describing !== $testCall->describing) {
|
if (! in_array(end($describing), $testCall->describing, true)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ final class BeforeEachCall
|
|||||||
};
|
};
|
||||||
|
|
||||||
$beforeEachTestCase = ChainableClosure::boundWhen(
|
$beforeEachTestCase = ChainableClosure::boundWhen(
|
||||||
fn (): bool => is_null($describing) || $this->__describing === $describing,
|
fn (): bool => $describing === [] || in_array(end($describing), $this->__describing, true),
|
||||||
ChainableClosure::bound(fn () => $testCaseProxies->chain($this), $this->closure)->bindTo($this, self::class), // @phpstan-ignore-line
|
ChainableClosure::bound(fn () => $testCaseProxies->chain($this), $this->closure)->bindTo($this, self::class), // @phpstan-ignore-line
|
||||||
)->bindTo($this, self::class);
|
)->bindTo($this, self::class);
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ final class BeforeEachCall
|
|||||||
*/
|
*/
|
||||||
public function after(Closure $closure): self
|
public function after(Closure $closure): self
|
||||||
{
|
{
|
||||||
if ($this->describing === null) {
|
if ($this->describing === []) {
|
||||||
throw new AfterBeforeTestFunction($this->filename);
|
throw new AfterBeforeTestFunction($this->filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,11 +11,15 @@ trait Describable
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Note: this is property is not used; however, it gets added automatically by rector php.
|
* Note: this is property is not used; however, it gets added automatically by rector php.
|
||||||
|
*
|
||||||
|
* @var string[]
|
||||||
*/
|
*/
|
||||||
public string $__describing;
|
public array $__describing;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The describing of the test case.
|
* The describing of the test case.
|
||||||
|
*
|
||||||
|
* @var string[]
|
||||||
*/
|
*/
|
||||||
public ?string $describing = null;
|
public array $describing = [];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,10 +39,12 @@ final class DescribeCall
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* What is the current describing.
|
* What is the current describing.
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
*/
|
*/
|
||||||
public static function describing(): ?string
|
public static function describing(): array
|
||||||
{
|
{
|
||||||
return self::$describing[count(self::$describing) - 1] ?? null;
|
return self::$describing;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,7 +75,7 @@ final class DescribeCall
|
|||||||
if (! $this->currentBeforeEachCall instanceof \Pest\PendingCalls\BeforeEachCall) {
|
if (! $this->currentBeforeEachCall instanceof \Pest\PendingCalls\BeforeEachCall) {
|
||||||
$this->currentBeforeEachCall = new BeforeEachCall(TestSuite::getInstance(), $filename);
|
$this->currentBeforeEachCall = new BeforeEachCall(TestSuite::getInstance(), $filename);
|
||||||
|
|
||||||
$this->currentBeforeEachCall->describing = $this->description;
|
$this->currentBeforeEachCall->describing[] = $this->description;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->currentBeforeEachCall->{$name}(...$arguments); // @phpstan-ignore-line
|
$this->currentBeforeEachCall->{$name}(...$arguments); // @phpstan-ignore-line
|
||||||
|
|||||||
@ -76,7 +76,7 @@ final class TestCall // @phpstan-ignore-line
|
|||||||
throw new TestDescriptionMissing($this->filename);
|
throw new TestDescriptionMissing($this->filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
$description = is_null($this->describing)
|
$description = $this->describing === []
|
||||||
? $this->description
|
? $this->description
|
||||||
: Str::describe($this->describing, $this->description);
|
: Str::describe($this->describing, $this->description);
|
||||||
|
|
||||||
@ -683,7 +683,7 @@ final class TestCall // @phpstan-ignore-line
|
|||||||
throw new TestDescriptionMissing($this->filename);
|
throw new TestDescriptionMissing($this->filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! is_null($this->describing)) {
|
if ($this->describing !== []) {
|
||||||
$this->testCaseMethod->describing = $this->describing;
|
$this->testCaseMethod->describing = $this->describing;
|
||||||
$this->testCaseMethod->description = Str::describe($this->describing, $this->description);
|
$this->testCaseMethod->description = Str::describe($this->describing, $this->description);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -103,10 +103,14 @@ final class Str
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a describe block as `$describeDescription` → `$testDescription` format.
|
* Creates a describe block as `$describeDescription` → `$testDescription` format.
|
||||||
|
*
|
||||||
|
* @param string[] $describeDescriptions
|
||||||
*/
|
*/
|
||||||
public static function describe(string $describeDescription, string $testDescription): string
|
public static function describe(array $describeDescriptions, string $testDescription): string
|
||||||
{
|
{
|
||||||
return sprintf('`%s` → %s', $describeDescription, $testDescription);
|
$descriptionComponents = [...$describeDescriptions, $testDescription];
|
||||||
|
|
||||||
|
return sprintf(str_repeat('`%s` → ', count($describeDescriptions)).'%s', ...$descriptionComponents);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -27,6 +27,8 @@
|
|||||||
PASS Tests\Features\AfterEach
|
PASS Tests\Features\AfterEach
|
||||||
✓ it does not get executed before the test
|
✓ it does not get executed before the test
|
||||||
✓ it gets executed after the test
|
✓ it gets executed after the test
|
||||||
|
✓ outer → inner → it does not get executed before the test
|
||||||
|
✓ outer → inner → it should call all parent afterEach functions
|
||||||
|
|
||||||
PASS Tests\Features\Assignee
|
PASS Tests\Features\Assignee
|
||||||
✓ it may be associated with an assignee [@nunomaduro, @taylorotwell]
|
✓ it may be associated with an assignee [@nunomaduro, @taylorotwell]
|
||||||
@ -40,6 +42,7 @@
|
|||||||
PASS Tests\Features\BeforeEach
|
PASS Tests\Features\BeforeEach
|
||||||
✓ it gets executed before each test
|
✓ it gets executed before each test
|
||||||
✓ it gets executed before each test once again
|
✓ it gets executed before each test once again
|
||||||
|
✓ outer → inner → it should call all parent beforeEach functions
|
||||||
|
|
||||||
PASS Tests\Features\BeforeEachProxiesToTestCallWithExpectations
|
PASS Tests\Features\BeforeEachProxiesToTestCallWithExpectations
|
||||||
✓ runs 1
|
✓ runs 1
|
||||||
@ -1585,4 +1588,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, 17 todos, 28 skipped, 1096 passed (2649 assertions)
|
Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 17 todos, 28 skipped, 1099 passed (2656 assertions)
|
||||||
@ -26,3 +26,25 @@ it('gets executed after the test', function () {
|
|||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
$this->state->bar = 2;
|
$this->state->bar = 2;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('outer', function () {
|
||||||
|
afterEach(function () {
|
||||||
|
$this->state->bar++;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('inner', function () {
|
||||||
|
afterEach(function () {
|
||||||
|
$this->state->bar++;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not get executed before the test', function () {
|
||||||
|
expect($this->state)->toHaveProperty('bar');
|
||||||
|
expect($this->state->bar)->toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call all parent afterEach functions', function () {
|
||||||
|
expect($this->state)->toHaveProperty('bar');
|
||||||
|
expect($this->state->bar)->toBe(4);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@ -25,3 +25,19 @@ it('gets executed before each test once again', function () {
|
|||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
$this->bar++;
|
$this->bar++;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('outer', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
$this->bar++;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('inner', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
$this->bar++;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call all parent beforeEach functions', function () {
|
||||||
|
expect($this->bar)->toBe(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@ -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, 17 todos, 19 skipped, 1086 passed (2625 assertions)')
|
->toContain('Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 17 todos, 19 skipped, 1089 passed (2632 assertions)')
|
||||||
->toContain('Parallel: 3 processes');
|
->toContain('Parallel: 3 processes');
|
||||||
})->skipOnWindows();
|
})->skipOnWindows();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user