Skip to content
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

fix: dont run all nested beforeAll hooks on test start #17938

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

francescov1
Copy link

What does this PR do?

This fixes a bug in the bun test runner related to beforeAll timing execution. Previously, beforeAll blocks inside nested describe blocks would execute at the beginning of the entire test file, rather than immediately before their describe block began.

  • Documentation or TypeScript types (it's okay to leave the rest blank in this case)
  • Code changes

Example test file:

import { afterAll, beforeAll, describe, expect, it } from "bun:test";

beforeAll(() => console.log("beforeAll top level"));
afterAll(() => console.log("afterAll top level"));
describe("describe root", () => {
  beforeAll(() => console.log("beforeAll describe root"));
  afterAll(() => console.log("afterAll describe root"));

  describe("describe 1", () => {
    beforeAll(() => console.log("beforeAll describe 1"));
    afterAll(() => console.log("afterAll describe 1"));
    it("test 1", () => {
      console.log("started test 1");
      expect(true).toBe(true);
    });
  });

  describe("describe 2", () => {
    beforeAll(() => console.log("beforeAll describe 2"));
    afterAll(() => console.log("afterAll describe 2"));

    it("test 2", () => {
      console.log("started test 2");
      expect(true).toBe(true);
    });
  });
});

Before fix:

beforeAll top level
beforeAll describe root
beforeAll describe 1
beforeAll describe 2
started test 1
✓ describe root > describe 1 > test 1 [0.06ms]
afterAll describe 1
started test 2
✓ describe root > describe 2 > test 2 [0.01ms]
afterAll describe 2
afterAll describe root
afterAll top level

After fix:

beforeAll top level
beforeAll describe root
beforeAll describe 1
started test 1
✓ describe root > describe 1 > test 1 [0.03ms]
afterAll describe 1
beforeAll describe 2
started test 2
✓ describe root > describe 2 > test 2 [0.01ms]
afterAll describe 2
afterAll describe root
afterAll top level

How did you verify your code works?

I updated the tests in jest-hooks.test.ts to validate this order of operations

  • I checked the lifetime of memory allocated to verify it's (1) freed and (2) only freed when it should be
  • I included a test for the new code, or an existing test covers it
  • JSValue used outside outside of the stack is either wrapped in a JSC.Strong or is JSValueProtect'ed
  • I wrote TypeScript/JavaScript tests and they pass locally (bun-debug test test-file-name.test)

@@ -1132,15 +1153,6 @@ pub const DescribeScope = struct {
var i: TestRunner.Test.ID = 0;

if (this.shouldEvaluateScope()) {
if (this.runCallback(globalObject, .beforeAll)) |err| {
Copy link
Author

@francescov1 francescov1 Mar 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the main culprit, it goes up the parent chain and calls all beforeAll blocks and its own before starting the test

@@ -1375,6 +1367,12 @@ pub const TestRunnerTask = struct {
jsc_vm.onUnhandledRejectionCtx = this;
jsc_vm.onUnhandledRejection = onUnhandledRejection;

if (this.describe.runCallback(globalThis, .beforeAll)) |err| {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead we can trigger the beforeAll blocks right before the beforeEach blocks

@francescov1 francescov1 changed the title dont run all beforealls at once fix: dont run all beforealls at once Mar 6, 2025
@francescov1 francescov1 changed the title fix: dont run all beforealls at once fix: dont run all nested beforeAll hooks on test start Mar 6, 2025
@dylan-conway
Copy link
Member

Testing this manually, it seems there's some test failures in test-test.test.ts.

I also noticed a segfault running this test:

beforeAll(() => {
    throw new Error("oops");
});

test("t1", () => {
    expect(1).toBe(1);
});

Not sure why it's happening, but seems the error printing is causing it.

@francescov1
Copy link
Author

Ok will resolve

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

Successfully merging this pull request may close these issues.

2 participants