testing
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTesting conventions and in-memory databases
测试规范与内存数据库
When to use: Writing or debugging tests, choosing unit vs integration style, Postgres/ClickHouse tests, regenerating ClickHouse test schema, or exporting test helpers from packages without pulling test code into production bundles.
适用场景: 编写或调试测试、选择单元测试与集成测试类型、Postgres/ClickHouse测试、重新生成ClickHouse测试架构,或者从包中导出测试工具同时避免将测试代码引入生产包。
Package exports (test code isolation)
包导出(测试代码隔离)
Test utilities (fakes, in-memory DB helpers, fixtures) must not be exported from a package’s main entry ().
src/index.ts- Never re-export from or
./test/in the main./testing/src/index.ts - To expose test helpers, add a subpath in
/testingpackage.json:exports
json
{
"exports": {
".": "./src/index.ts",
"./testing": "./src/testing/my-test-helpers.ts"
}
}- Consumers:
import { Fake } from "@platform/my-package/testing" - Biome blocks test paths in production source; tsdown fails the build if test code is resolved from prod entry points
noRestrictedImports
测试工具(模拟对象、内存数据库助手、测试夹具)绝对不能从包的主入口()导出。
src/index.ts- 绝对不要在主入口中重新导出
src/index.ts或./test/下的内容./testing/ - 如需暴露测试助手,在的
package.json中添加**exports子路径**:/testing
json
{
"exports": {
".": "./src/index.ts",
"./testing": "./src/testing/my-test-helpers.ts"
}
}- 消费者使用方式:
import { Fake } from "@platform/my-package/testing" - Biome的规则会阻止生产代码引入测试路径;若生产入口解析到测试代码,tsdown会使构建失败
noRestrictedImports
Conventions
测试规范
- Shared default environment: Node with globals enabled ()
packages/vitest-config/index.ts - Write tests, mostly e2e, some unit tests when logic is complex
- Unit tests: domain entities/use-cases/policies with fakes
- Contract tests: adapter compliance against domain ports
- Integration tests: infra-backed tests for Postgres/ClickHouse/Redis/BullMQ/object storage
- End-to-end tests: ingest boundary to query boundary across organization scoping
- Keep tests deterministic and isolated
- Prefer package-local runs during iteration; run full monorepo tests before PR
- 共享默认环境:启用全局变量的Node环境()
packages/vitest-config/index.ts - 编写测试时,以端到端测试为主,当逻辑复杂时编写单元测试
- 单元测试:针对领域实体/用例/策略,使用模拟对象
- 契约测试:验证适配器是否符合领域端口要求
- 集成测试:针对Postgres/ClickHouse/Redis/BullMQ/对象存储的基础设施测试
- 端到端测试:覆盖从数据摄入边界到查询边界的全流程,包含组织范围限定
- 保持测试的确定性与隔离性
- 迭代期间优先运行包本地测试;提交PR前运行完整的单仓库测试
Database testing (in-memory)
数据库测试(内存型)
Always use in-memory databases for tests. Do not use / to mock repository methods and do not require running database servers. The project provides embedded, in-process database engines that run the real SQL against the real schema:
vi.mockvi.fn- ClickHouse → chdb (package): An in-process ClickHouse engine via
chdb.@platform/testkit - Postgres → PGlite (): An in-process Postgres via WASM via
@electric-sql/pglite.@platform/testkit
测试必须使用内存数据库。不要使用/来模拟仓库方法,也不需要运行外部数据库服务器。项目提供了嵌入式、进程内的数据库引擎,可基于真实架构运行真实SQL:
vi.mockvi.fn- ClickHouse → chdb(包):通过
chdb提供的进程内ClickHouse引擎。@platform/testkit - Postgres → PGlite():通过
@electric-sql/pglite提供的基于WASM的进程内Postgres。@platform/testkit
Postgres test setup (@platform/testkit
)
@platform/testkitPostgres测试配置(@platform/testkit
)
@platform/testkittypescript
import { setupTestPostgres } from "@platform/testkit"
import { beforeAll, describe, it } from "vitest"
const pg = setupTestPostgres()
describe("MyRepository", () => {
it("does something", async () => {
// pg.postgresDb is a real Drizzle instance backed by PGlite in-memory
// pg.db is the lower-level Drizzle/PGlite instance for direct queries
})
})setupTestPostgres()- beforeAll: creates a PGlite instance, creates the role, and runs all Drizzle migrations
latitude_app - afterAll: closes the PGlite connection
typescript
import { setupTestPostgres } from "@platform/testkit"
import { beforeAll, describe, it } from "vitest"
const pg = setupTestPostgres()
describe("MyRepository", () => {
it("does something", async () => {
// pg.postgresDb是基于内存PGlite的真实Drizzle实例
// pg.db是用于直接查询的底层Drizzle/PGlite实例
})
})setupTestPostgres()- beforeAll:创建PGlite实例、创建角色,并运行所有Drizzle迁移
latitude_app - afterAll:关闭PGlite连接
ClickHouse test setup (@platform/testkit
)
@platform/testkitClickHouse测试配置(@platform/testkit
)
@platform/testkittypescript
import { setupTestClickHouse } from "@platform/testkit"
import { beforeAll, describe, it } from "vitest"
const ch = setupTestClickHouse()
describe("MyRepository", () => {
let repo: ReturnType<typeof createMyRepository>
beforeAll(() => {
repo = createMyRepository(ch.client)
})
it("does something", async () => {
// ch.client is a real ClickHouseClient backed by chdb in-memory
})
})setupTestClickHouse()- beforeAll: creates a chdb session and loads the schema from
schema.sql - beforeEach: truncates all tables for test isolation
- afterAll: destroys the session and cleans up temp files
After new ClickHouse migrations, regenerate the in-memory test schema (only if the user asked you to run migration-related commands — see database-clickhouse-weaviate):
bash
pnpm --filter @platform/db-clickhouse ch:schema:dumptypescript
import { setupTestClickHouse } from "@platform/testkit"
import { beforeAll, describe, it } from "vitest"
const ch = setupTestClickHouse()
describe("MyRepository", () => {
let repo: ReturnType<typeof createMyRepository>
beforeAll(() => {
repo = createMyRepository(ch.client)
})
it("does something", async () => {
// ch.client是基于内存chdb的真实ClickHouseClient实例
})
})setupTestClickHouse()- beforeAll:创建chdb会话并从加载架构
schema.sql - beforeEach:清空所有表以保证测试隔离
- afterAll:销毁会话并清理临时文件
在新增ClickHouse迁移后,重新生成内存测试架构(仅当用户要求运行迁移相关命令时执行——参考database-clickhouse-weaviate):
bash
pnpm --filter @platform/db-clickhouse ch:schema:dumpWhy not vi.mock
?
vi.mock为什么不使用vi.mock
?
vi.mockMocking repositories with tests the wiring, not the queries. In-memory databases catch real bugs: wrong column names, broken aggregations, incorrect clauses, and schema mismatches. They run quickly with zero external dependencies.
vi.fn()argMaxGROUP BY使用模拟仓库方法只能测试代码连接,无法测试查询逻辑。内存数据库可以捕获真实的bug:错误的列名、失效的聚合、不正确的子句以及架构不匹配问题。它们运行速度快且无外部依赖。
vi.fn()argMaxGROUP BY