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

# 使用 glob 模式选择性地并发运行测试

> 设置 glob 模式来决定哪些文件中哪些测试可以并行运行

`bunfig.toml` 中的 `concurrentTestGlob` 选项可使文件名匹配 glob 模式的文件中的测试并发运行。

## 项目结构

```sh title="项目结构" icon="folder-tree" theme={null}
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={null}
[test]
# 运行所有带有 "concurrent-" 前缀的测试文件，并发执行
concurrentTestGlob = "**/concurrent-*.test.ts"
```

## 测试文件

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

共享状态或依赖于执行顺序的测试应保持顺序执行：

```ts title="tests/unit/math.test.ts" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/typescript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=787d39d6a7d96d7f9540dc74344eba23" theme={null}
import { test, expect } from "bun:test";

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

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

test("使用之前的状态", () => {
  // 此测试依赖于上一个测试的状态
  expect(sharedState).toBe(8);
});
```

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

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

```ts title="tests/integration/concurrent-api.test.ts" icon="https://mintcdn.com/span-inc/82N53aP7NFbaCVSl/icons/typescript.svg?fit=max&auto=format&n=82N53aP7NFbaCVSl&q=85&s=787d39d6a7d96d7f9540dc74344eba23" theme={null}
import { test, expect } from "bun:test";

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

test("获取用户数据", async () => {
  const response = await fetch("/api/user/1");
  expect(response.ok).toBe(true);
});

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

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

## 运行测试

```bash terminal icon="terminal" theme={null}
# 运行所有测试 - concurrent-*.test.ts 文件将并发执行
bun test

# 覆盖：强制所有测试并发运行
# 注意：这会覆盖 bunfig.toml 配置，使所有测试并发执行，忽略 glob 模式
bun test --concurrent

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

# 仅运行集成测试（由于 glob 模式，并发执行）
bun test tests/integration
```

## 优势

1. **逐步迁移**：一次重命名一个文件，将其迁移到并发执行
2. **清晰组织**：文件名告诉你文件的测试如何运行
3. **性能**：独立的集成测试并行完成更快
4. **安全性**：单元测试在需要时保持顺序执行

## 迁移策略

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

1. **从独立的集成测试开始** - 这些通常不共享状态
2. **重命名文件以匹配 glob 模式**：`mv api.test.ts concurrent-api.test.ts`
3. **运行 `bun test`** - 检查竞态条件和不可靠或不期望的失败
4. **逐个继续迁移稳定的测试**

## 提示

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

## 多个模式

`concurrentTestGlob` 也支持多个模式：

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

匹配任意模式的测试文件中的测试都将并发运行：

* `integration/` 目录中的所有测试
* `e2e/` 目录中的所有测试
* 项目中任何位置带有 `concurrent-` 前缀的所有测试
