用途
testing-patterns 是一份跨语言的测试标准与模式参考,用于统一 TypeScript、Rust、Swift、Go 四种技术栈在同一个工程体系内的测试写法。它既给出各语言各自的约定,也给出跨语言的通用准则,帮助团队在多种语言并存的仓库中保持一致的测试风格与质量标准。
主要能力
TypeScript / JavaScript(Vitest)
- 文件约定:并列式测试
src/foo.test.ts放在src/foo.ts旁边(主要模式);E2E 测试使用*.e2e.test.ts放在test/目录或并列放置;需要真实 API Key 的测试使用*.live.test.ts;全局钩子放在test/setup.ts。配置采用分层方式,由基础vitest.config.ts被vitest.unit.config.ts、vitest.e2e.config.ts、vitest.live.config.ts扩展。 - 用例结构使用
describe/it/expect/vi,示例中演示了权限解析函数在安全工具上自动放行、在危险操作上发起提示两种情形。 - Mock 模式:函数 Mock(
vi.fn)用于依赖注入;模块 Mock(vi.mock)建议少用,优先 DI;vi.spyOn监听已有方法;vi.stubEnv替换环境变量(配合unstubEnvs: true自动清理);假定时器需在afterEach恢复以免跨用例泄漏。 - 全局 setup 示例使用
withIsolatedTestHome()为每个 worker 提供隔离的 HOME,并在afterAll清理。 - 测试数据建议使用工厂函数(如
makePermissionRequest)而非裸对象字面量,通过overrides覆盖字段。 - 覆盖率配置示例:provider 为
v8,reporter 为text与lcov,all: false只统计被测试执行到的文件,阈值 lines 70 / functions 70 / branches 55 / statements 70,并可 include、exclude 指定范围。 - 反模式清单:不要把
maxWorkers设置超过 16;不要测试实现细节(内部状态、私有方法);在参数化依赖注入可行时不要使用vi.mock;不要跨用例泄漏假定时器;不要跳过空输入、null、边界值、错误路径等边界情形。
Rust(cargo test)
- 文件约定:内联单元测试使用
#[cfg(test)] mod tests放在每个源文件底部(主要模式);集成测试放在 crate 根目录的tests/(在 workspace 项目中较少使用);仅测试用依赖写入各 crateCargo.toml的[dev-dependencies]。 - 常用命令:
cargo test --lib运行全部;cargo test -p claudio-gateway --lib运行单个 crate;cargo test --lib test_name_substring按名称过滤;cargo test --lib -- --skip concurrent跳过慢测试。 - 示例覆盖
BoundedMap的插入读取、容量淘汰、TTL 过期三类用例。 - 异步测试使用
#[tokio::test],示例演示无工具调用时立即返回、达到最大迭代次数时产出最终响应。 - Stub / Mock 采用基于 trait 的模拟:
StubProvider始终返回固定响应、不发起网络请求;ScriptedProvider按顺序返回预配置响应,适合多轮智能体循环。异步上下文中使用Arc<dyn Trait>注入 Mock。 - Workspace 项目中,每个 crate 有自己的
#[cfg(test)]模块(典型工作区有 100+ 测试文件),共享测试工具放在专用 stub 模块(如providers/src/stub.rs),可按 crate 独立测试。 - 也给出了 Tauri 命令的最小内联测试示例(版本号比较判断)。
Swift / iOS(Swift Testing)
- 使用 Swift Testing 框架(非 XCTest),配合
@Test宏与#expect断言。 - 用例结构以
@Suite struct组织,示例演示 KeychainStore 的保存 / 读取 / 更新 / 删除往返测试。 - 共享状态使用
@Suite(.serialized)串行执行;UI 绑定状态使用@MainActor;依赖 UserDefaults 的代码使用withUserDefaults辅助函数做快照与恢复。 - 异步测试方法演示挂起与恢复周期对状态的影响。
- 提供「暴露内部」的测试辅助模式:在生产代码中提供
_test_前缀的访问器方法。 - 使用 actor(如
CaptureBox)在闭包中安全捕获值。 - 构建与测试命令使用
xcodebuild test指定 project、scheme 与模拟器 destination,另提供仅构建以捕获编译错误的命令。
Go(go test)
- 文件约定:
*_test.go与被测代码放在同一包内;测试使用同包名(如package crypto)以获得内部访问权限。 - 命令:
go test ./...、go test ./internal/crypto/。 - 标准模式示例为 Encrypt / Decrypt 往返校验,错误用例测试短密钥被拒。
- 集成测试使用 channel 与
select+time.After做超时控制,演示客户端与服务端握手校验。 - 唯一性与确定性测试:生成密钥不应重复、指纹应确定性。
- 竞态检测:
go test -race ./...,建议在 CI 中始终运行。
使用方式
该资源以模式文档形式组织,按语言分章。使用时按所用语言查阅对应章节,遵循其中的文件命名、目录结构、命令与配置;跨语言部分给出了何时写测试、命名约定、测试金字塔、不测什么、CI 集成与快速参考表。
跨语言通用准则
- 必须测试:边界逻辑、解析、序列化、加密、状态机、错误路径;缺陷修复也应先写失败用例。
- 不必测试:平凡的 getter / setter、框架接线、单行委托、第三方库行为(那是对方的职责)。
- 命名约定:TypeScript 用
describe("module") > it("does X when Y");Rust 用 snake_case 函数名;Swift 用@Suite结构体上的 camelCase 方法名;Go 用TestXxx的 PascalCase。 - 测试金字塔目标比例约为 70% 单元、20% 集成、10% E2E。
- 不应测试:框架内部(Tauri IPC 管线、axum 路由接线、SwiftUI 视图布局)、第三方 API 响应(改为 Mock)、仅做委托的平凡包装、生成代码。
CI 集成(GitHub Actions)
给出了四种语言的片段:TypeScript 运行 pnpm test 与 pnpm test:coverage;Rust 运行 cargo test --lib 与 cargo clippy -- -D warnings;Swift 运行 xcodebuild test;Go 运行 go test -race -cover ./...。
快速参考与 Mock 策略
快速参考表汇总四种语言的框架、运行命令、配置文件和约定。Mock 策略表说明各语言的首选方式与应避免的做法:TypeScript 用 vi.fn() 加参数注入,避免整模块重度 vi.mock();Rust 用基于 trait 的 stub,简单场景避免 mockall;Swift 用 _test_ 访问器加 actor 捕获,避免 swizzling 与运行时补丁;Go 用基于接口的注入加 channel,避免 monkey patching 与 reflect。
属性测试与覆盖率
属性测试适用于可表达为规则的不变量(交换律、往返、幂等、单调性),一个属性测试可替代大量示例用例。库选型:TypeScript 使用 fast-check,Rust 使用 proptest,Swift 使用 swift-testing 加手工生成器(用 Int.random(in:) 循环配合 #expect),Go 使用标准库 testing/quick 或 gopter。适合解析器、编码器、序列化、数学工具、排序 / 合并逻辑;纯 I/O 包装不适合。
覆盖率目标按层划分:纯逻辑与解析器 90%+;服务 / 处理器代码 70-80%;UI / 视图层 40-60%;胶水与框架接线不测量。文档强调覆盖率是下限而非目标,100% 行覆盖但无输出断言不能证明任何东西。
适用场景与限制
适用于在同一仓库或团队内使用 TypeScript、Rust、Swift、Go 中一种或多种语言的测试实践统一,尤其是 CLI、网关、多语言工作区与移动端项目。限制:文档面向上述四种语言与指定框架(Vitest、cargo test、Swift Testing、go test),其他语言与测试框架未涉及;具体价格、授权方式、平台支持等信息暂未提供。