> ## Documentation Index
> Fetch the complete documentation index at: https://bun.zhcndoc.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 使用通配符模式有选择地并发运行测试

> 设置通配符模式以决定来自哪些文件的哪些测试并行运行

本指南演示如何使用 `concurrentTestGlob` 选项，基于文件命名模式有选择地并发运行测试。

## 项目结构

```sh title="项目结构" icon="folder-tree" theme={"theme":{"light":"github-light","dark":"dracula"}}
my-project/
├── bunfig.toml
├── tests/
│   ├── unit/
│   │   ├── math.test.ts          # 顺序执行
│   │   └── utils.test.ts         # 顺序执行
│   └── integration/
│       ├── concurrent-api.test.ts     # 并发执行
│       └── concurrent-database.test.ts # 并发执行
```

## 配置

配置你的 `bunfig.toml`，使带有 "concurrent-" 前缀的测试文件并发运行：

```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}}
[test]
# 并发执行所有以 "concurrent-" 开头的测试文件
concurrentTestGlob = "**/concurrent-*.test.ts"
```

## 测试文件

### 单元测试（顺序执行）

顺序测试适用于共享状态或有特定执行顺序需求的测试：

```ts title="tests/unit/math.test.ts" icon="https://mintcdn.com/bun-zhcndoc/cnUTwgMuf4cCrwC-/icons/typescript.svg?fit=max&auto=format&n=cnUTwgMuf4cCrwC-&q=85&s=e7767043c9e885c34f2d6c8fe2a95217" theme={"theme":{"light":"github-light","dark":"dracula"}}
import { test, expect } from "bun:test";

// 这些测试默认顺序执行
let sharedState = 0;

test("addition", () => {
  sharedState = 5 + 3;
  expect(sharedState).toBe(8);
});

test("uses previous state", () => {
  // 该测试依赖于前一个测试的状态
  expect(sharedState).toBe(8);
});
```

### 集成测试（并发执行）

匹配通配符模式的文件中的测试自动并发运行：

```ts title="tests/integration/concurrent-api.test.ts" icon="https://mintcdn.com/bun-zhcndoc/cnUTwgMuf4cCrwC-/icons/typescript.svg?fit=max&auto=format&n=cnUTwgMuf4cCrwC-&q=85&s=e7767043c9e885c34f2d6c8fe2a95217" theme={"theme":{"light":"github-light","dark":"dracula"}}
import { test, expect } from "bun:test";

// 由于文件名匹配通配符模式，这些测试会自动并发执行。
// 在匹配 concurrentTestGlob 时，使用 test() 等同于 test.concurrent()。
// 每个测试都是独立的，可以并行运行。

test("fetch user data", async () => {
  const response = await fetch("/api/user/1");
  expect(response.ok).toBe(true);
});

// 也可以显式使用 test.concurrent() 标记为并发执行
test.concurrent("fetch posts", async () => {
  const response = await fetch("/api/posts");
  expect(response.ok).toBe(true);
});

// 也可以显式使用 test.serial() 标记为顺序执行
test.serial("fetch comments", async () => {
  const response = await fetch("/api/comments");
  expect(response.ok).toBe(true);
});
```

## 运行测试

```bash terminal icon="terminal" theme={"theme":{"light":"github-light","dark":"dracula"}}
# 运行所有测试 - concurrent-*.test.ts 文件将并发运行
bun test

# 覆盖设置：强制所有测试并发运行
# 注意：此选项会覆盖 bunfig.toml，所有测试无视通配符都并发运行
bun test --concurrent

# 只运行单元测试（顺序执行）
bun test tests/unit

# 只运行集成测试（由于通配符模式并发执行）
bun test tests/integration
```

## 优点

1. **逐步迁移**：通过重命名文件逐个迁移到并发测试
2. **清晰的组织**：文件命名约定体现执行方式
3. **性能提升**：集成测试并行执行更快
4. **安全保障**：单元测试在需要时保持顺序执行
5. **灵活性强**：通过重命名文件轻松更改执行方式

## 迁移策略

迁移现有测试到并发执行：

1. **从独立的集成测试开始** — 通常这些测试不共享状态
2. **重命名文件以匹配通配符模式**：`mv api.test.ts concurrent-api.test.ts`
3. **确保测试仍然通过** — 运行 `bun test` 确认无竞态条件
4. **监控共享状态问题** — 观察是否有不稳定测试或意外失败
5. **逐步迁移稳定测试** — 不要急于全部迁移

## 建议

* **使用描述性前缀**：如 `concurrent-`、`parallel-`、`async-`
* **将相关的顺序测试放在一起**，保持同一目录
* **用注释说明某些测试必须顺序执行的原因**
* **在顺序文件中使用 `test.concurrent()` 实现细粒度控制**
  （注意：在匹配 `concurrentTestGlob` 的文件中，普通 `test()` 即为并发执行）

## 多个模式

你可以为不同测试类别指定多个模式：

```toml title="bunfig.toml" icon="settings" theme={"theme":{"light":"github-light","dark":"dracula"}}
[test]
concurrentTestGlob = [
  "**/integration/*.test.ts",
  "**/e2e/*.test.ts",
  "**/concurrent-*.test.ts"
]
```

此配置将使匹配以下任一模式的测试并发执行：

* 所有 `integration/` 目录下的测试
* 所有 `e2e/` 目录下的测试
* 项目中任意位置所有以 `concurrent-` 前缀命名的测试文件
