> For AI agents: the complete documentation index is available at /zh/llms.txt, the full documentation bundle is available at /zh/llms-full.txt.

# Hooks

Hooks 允许你在测试或测试套件执行之前或之后运行初始化和清理逻辑。

## beforeAll

- **类型：** `(fn: (ctx: SuiteContext) => void | Promise<void>, timeout?: number) => void`

在当前套件的所有测试之前运行。

当前套件中没有可执行的测试时，例如所有测试都被跳过、被测试名称筛选排除，或未被 `test.only` 选中，Rstest 不会执行该 hook。

```ts
import { beforeAll } from '@rstest/core';

beforeAll(async (ctx) => {
  // 在所有测试前的初始化逻辑
  // ctx.filepath 表示当前测试文件路径
  ctx.meta.startedAt = Date.now();
});
```

`beforeAll` 也支持返回一个函数，在所有测试之后运行，用于清理操作（等价于 `afterAll`）：

```ts
import { beforeAll } from '@rstest/core';

beforeAll(async () => {
  const cleanUp = await doSomething();

  // 在所有测试后的清理逻辑
  return async () => {
    await cleanUp();
  };
});
```

## afterAll

- **类型：** `(fn: (ctx: SuiteContext) => void | Promise<void>, timeout?: number) => void`

在当前套件的所有测试之后运行。

当前套件中没有可执行的测试时，例如所有测试都被跳过、被测试名称筛选排除，或未被 `test.only` 选中，Rstest 不会执行该 hook。

```ts
import { afterAll } from '@rstest/core';

afterAll(async (ctx) => {
  // 在所有测试后的清理逻辑
  ctx.meta.finished = true;
});
```


[Added in v0.11.1](https://github.com/web-infra-dev/rstest/releases/tag/v0.11.1)

`ctx.meta` 是当前 suite 的可变元数据对象。如果 suite 通过 `describe(name, { meta }, fn)` 声明，`ctx.meta` 会以应用完套件继承后的元数据作为初始值。文件级 hooks 写入的元数据会出现在 `TestFileResult.meta`；`describe` 内 hooks 写入的元数据会出现在传给自定义 Reporter 的对应 suite result 上。

## beforeEach

- **类型：** `<ExtraContext = object>(fn: (ctx: TestContext & ExtraContext) => void | ((ctx: TestContext & ExtraContext) => void | Promise<void>) | Promise<void | ((ctx: TestContext & ExtraContext) => void | Promise<void>)>, timeout?: number) => void`

`ctx` 的字段详见 [`TestContext`](/zh/api/runtime-api/test-api/test.md#testcontext)(以下测试级 hook 同理)。

在当前套件的每个测试之前运行。

```ts
import { beforeEach } from '@rstest/core';

beforeEach(async () => {
  // 每个测试前的初始化逻辑
});
```

`beforeEach` 也支持返回一个函数，在每个测试之后运行，用于清理操作（等价于 `afterEach`）：

```ts
import { beforeEach } from '@rstest/core';

beforeEach(async () => {
  const cleanUp = await doSomething();

  // 每个测试后的清理逻辑
  return async () => {
    await cleanUp();
  };
});
```


[Added in v0.11.4](https://github.com/web-infra-dev/rstest/releases/tag/v0.11.4)

`beforeEach`、`afterEach` callback 以及 `beforeEach` 返回的 cleanup 函数都可以使用通过 `test.extend` 创建的 fixture。将 fixture 类型作为 `ExtraContext` 传入；Rstest 会在某个 callback 第一次请求 fixture 前完成初始化。详见[在 hook 中使用 fixture](/zh/api/runtime-api/test-api/test.md#在-hook-中使用-fixture)。

使用 fixture 的 hook callback 必须在 hook 参数中通过直接对象解构声明 fixture 依赖。Rstest 不会从 hook 函数体推断依赖。使用 fixture 的 callback 不支持对象 rest property 和默认值。

## afterEach

- **类型：** `<ExtraContext = object>(fn: (ctx: TestContext & ExtraContext) => void | Promise<void>, timeout?: number) => void`

在当前套件的每个测试之后运行。

```ts
import { afterEach } from '@rstest/core';

afterEach(async () => {
  // 每个测试后的清理逻辑
});
```

## onTestFinished

- **类型：** `(fn: (ctx: TestContext) => void | Promise<void>, timeout?: number) => void`

测试运行完成后调用，无论测试成功或失败。可用于执行清理操作。该 hook 会在 `afterEach` 之后执行。

```ts
import { onTestFinished, test } from '@rstest/core';

test('test server', () => {
  const server = startServer();
  // Register a cleanup function to close the server after the test
  onTestFinished(() => server.close());

  server.listen(3000, () => {
    console.log('Server is running on port 3000');
  });
});
```

需要注意的是，当你在并发测试中使用 `onTestFinished` hook 时，你应当从测试上下文中获取该 hook。这是因为 Rstest 在并发测试中无法准确追踪来自全局的 onTestFinished hook 所属的具体测试。

```ts
describe.concurrent('并发套件', () => {
  test('test 1', async ({ onTestFinished }) => {
    /* ... */
  });
  test('test 2', async ({ onTestFinished }) => {
    /* ... */
  });
});
```

## onTestFailed

- **类型：** `(fn: (ctx: TestContext) => void | Promise<void>, timeout?: number) => void`

测试运行失败后调用。

```ts
import { onTestFailed, test } from '@rstest/core';

test('test server', () => {
  const server = startServer();

  onTestFailed(({ task }) => {
    console.log(task.result?.errors);
  });

  server.listen(3000, () => {
    console.log('Server is running on port 3000');
  });
});
```

需要注意的是，当你在并发测试中使用 `onTestFailed` hook 时，你应当从测试上下文中获取该 hook。这是因为 Rstest 在并发测试中无法准确追踪来自全局的 onTestFailed hook 所属的具体测试。
