10000 [Bug]: afterEach Hook Execution Order Is Inverted Compared to Documentation · Issue #1400 · pestphp/pest · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

[Bug]: afterEach Hook Execution Order Is Inverted Compared to Documentation #1400

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
jonathanpmartins opened this issue May 7, 2025 · 1 comment
Labels

Comments

@jonathanpmartins
Copy link
jonathanpmartins commented May 7, 2025

When using afterEach hooks at different levels (global in Pest.php and in test files), the execution order is completely reversed compared to what's stated in the documentation.

According to the Global Hooks documentation, it states:

Any before* hooks defined in the Pest.php configuration file will be executed prior to hooks defined in individual test files. Similarly, any after* hooks specified in the Pest.php configuration file will be executed after any hooks defined in individual test files.

However, I've observed that the afterEach hooks are executed in the reverse order from what's documented:

  1. The global hook runs first
  2. Then the outermost test file hook
  3. Then any intermediate nested hooks
  4. Finally the innermost hook

How to Reproduce

I've created a minimal test case to demonstrate this issue:

  1. Set up a fresh Laravel project with Pest:
composer global require laravel/installer
laravel new example-app

(Selected Pest for testing during installation)

  1. Created a nested test structure in tests/Unit/ExampleTest.php:
<?php

beforeEach(function ()
{
    dump('1');
});

afterEach(function ()
{
    dump('6');
});

test('Outer Test', function ()
{
    dump('Outer Test');
    expect(true)->toBeTrue();
});

describe('Group 1', function ()
{
    beforeEach(function ()
    {
        dump('2');
    });

    afterEach(function ()
    {
        dump('5');
    });

    test('Middle Test', function ()
    {
        dump('Middle Test');
        expect(true)->toBeTrue();
    });

    describe('Group 2', function ()
    {
        beforeEach(function ()
        {
            dump('3');
        });

        afterEach(function ()
        {
            dump('4');
        });

        test('Inner test', function ()
        {
            dump('Inner test');
            expect(true)->toBeTrue();
        });
    });
});
  1. Added a global hook in tests/Pest.php:
pest()->beforeEach(function ()
{
    dump('0 global beforeEach()');
});

pest()->afterEach(function ()
{
    dump('7 global afterEach()');
});

Test Output

$ php artisan test
^ "0 global beforeEach()"
^ "1"
^ "Outer Test"
^ "7 global afterEach()"
^ "6"
^ "0 global beforeEach()"
^ "1"
^ "2"
^ "Middle Test"
^ "7 global afterEach()"
^ "6"
^ "5"
^ "0 global beforeEach()"
^ "1"
^ "2"
^ "3"
^ "Inner test"
^ "7 global afterEach()" <-- Should be last, runs first
^ "6"                    <-- Should be second-to-last, runs second
^ "5"                    <-- Should be third-to-last, runs third
^ "4"                    <-- Should be first, runs last
   PASS  Tests\Unit\ExampleTest
  ✓ Outer Test
  ✓ Group 1 → Middle Test
  ✓ Group 1 → Group 2 → Inner test
  Tests:    3 passed (3 assertions)
  Duration: 0.03s

Sample Repository

pest-bug-example-repo

Pest Version

3.8.2

PHP Version

8.4.6

Operation System

Linux

Expected Behavior

According to the documentation, for a test in the innermost describe block:

  1. The beforeEach hooks should execute in order: global → outer → middle → inner (this works correctly)
  2. The test runs
  3. The afterEach hooks should execute in the reverse order: inner → middle → outer → global

However, the actual output shows the afterEach hooks running in the exact opposite order: global → outer → middle → inner.

Additional observations

The afterEach hooks are completely reversed from what would be expected. This behavior is counterintuitive and makes it difficult to properly clean up resources in a consistent manner. Since beforeEach hooks set up state in a specific order, it would be logical for afterEach hooks to clean up in the reverse order.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant
0