6.8 KiB
Testing Patterns
Analysis Date: 2026-09-07
Test Framework
Runner:
- Vitest
^4.0.18— declared inpackage.jsondevDependencies
Config: None present. There is no vitest.config.ts, vitest.config.js, vitest.setup.*, or any test-related config file anywhere in the repo. Vitest would run with its default configuration (files matching **/*.{test,spec}.?(c|m)[jt]s?(x)).
Assertion Library:
- Vitest's bundled assertions (
expect), plus Jest-compatibledescribe/it/testglobals. No@testing-library/*,jsdom, orhappy-domis installed.
Run Commands (package.json):
pnpm test # Run all tests (runs `vitest`)
There is no dedicated watch mode or coverage script. To run watch/coverage manually:
pnpm vitest --watch # Watch mode
pnpm vitest --coverage # Coverage (requires @vitest/coverage-* provider, not installed)
Test File Organization
Location: No test files currently exist in the repository. A repo-wide search for *.test.ts, *.spec.ts, *.test.tsx, *.spec.tsx returns zero matches.
Planned location (per .agents/review.md): test-case design documents live in docs/test/ (with subfolders where appropriate), following the example template docs/test/template.md. Note: the docs/test/ directory and docs/test/template.md do not exist yet — the workflow is defined but no tests have been authored.
Naming: No established on-disk convention yet. Follow the Vitest default: co-located *.test.ts (or *.spec.ts) next to the module under test, or a __tests__/ directory.
Test Structure
No test source exists to extract a concrete pattern from. The authoritative testing workflow is defined in .agents/review.md and is a manual, human-in-the-loop process:
- The user requests tests for a feature.
- The agent analyzes the feature and proposes test cases in a markdown document (placed in
docs/test/, followingdocs/test/template.md). - The user reviews the proposal over several rounds until the plan is finalized.
- The agent writes the test cases from the document. The agent must not run the test command; the user runs it.
- The user reports results; simple issues are fixed by the user, complex ones may be handed back to the agent.
Test-case design principle (from .agents/review.md): test cases must cover valid inputs AND invalid inputs / exception paths. For invalid paths, the expectation is usually that the system either throws correctly or produces a sensible logger output (rather than silently returning a wrong value).
Document structure for a test-case proposal:
# 测试目的
测试 XXX 系统的基本功能及异常处理。
# 测试用例
## 测试用例 1
- 设计目的:为什么需要这一测试用例(其来源/推导),而非它做什么。
- 针对接口:最重要的若干接口,最好五个以内。
### 测试内容
描述测试内容,并写出预期结果。
Mocking
Framework: None configured. Vitest provides vi.mock(), vi.fn(), vi.spyOn() which are available without extra deps, but no project-specific mocking pattern exists yet.
Relevant for future tests — the logger.catch mechanism (packages/common/src/logger.ts:189): the engine routes all errors/warnings through the logger singleton rather than throwing. Tests can therefore assert error behavior via logger.catch(fn) which returns { ret, info } (captured messages) instead of expecting exceptions. The logger also exposes disable()/enable() to silence output during tests.
What to Mock (prospective): browser globals (document, window, main, Mota) since much engine code references them at module load (e.g. packages/common/src/logger.ts:24-40 references main.replayChecking and document). Data-layer packages (@user/data-base, @user/data-system, @user/data-common) are designed to run in Node for replay verification, so they are the most unit-testable without a DOM.
What NOT to Mock (prospective): the data-layer interfaces themselves (IDataCommon, IDataBase, IDataSystem) — they are designed to be instantiated in Node and driven through their interfaces.
Fixtures and Factories
Test Data: No fixtures or factory helpers exist yet. Note the engine's createXxx factory convention (dev.md "模块初始化"): if a module needs initialization, expose a createXxx function wired up through index.ts. Test setup would follow this pattern rather than relying on module side effects (which are forbidden by dev.md "无副作用").
Location: docs/test/ (for design docs); no fixture directory established.
Coverage
Requirements: None enforced. No coverage script, no coverage provider installed, no CI coverage gate.
View Coverage: not available without installing a @vitest/coverage-* provider and running pnpm vitest --coverage.
Test Types
Unit Tests:
- Not yet written. The layered data-side packages (
@user/data-common,@user/data-base,@user/data-system) are explicitly designed to run in Node ("数据端可在 node 环境中单独运行" —dev.md"双端分离"), making them the natural first targets for unit tests.
Integration Tests:
- Not present. The
IDataCommon/IDataBase/IDataSystemlayer interfaces (packages-user/data-common/src/types.ts,packages-user/data-system/src/types.ts) form a seam where integration tests could assemble a full data-side stack in Node.
E2E Tests:
- Not used. No Playwright/Cypress. The closest is the replay-verification system (
packages-user/data-common/src/replay/) which validates that gameplay is deterministic, but it is a runtime feature, not a test harness.
CI
.github/workflows/page.ymlonly builds and deploys static content to GitHub Pages; it runspnpm build, not tests..github/workflows/codeql.ymlruns CodeQL static analysis; not unit tests.- There is currently no CI step that runs the test suite (and no committed test suite to run).
Common Patterns
Async Testing (prospective): the engine is heavily async/await-based (see ObjectMover.moveProgress in packages-user/data-common/src/common/mover.ts:626). Use await inside it blocks and Promise.withResolvers()/expect(...).resolves patterns as appropriate.
Error Testing (prospective): prefer logger.catch(() => { ... }) and assert on info (the captured { level, message, code }[]) rather than expecting thrown exceptions — the engine is designed to never throw in normal operation.
Determinism (the engine's own "testing" philosophy): the replay system in packages-user/data-common/src/replay/ exists to guarantee that a gameplay run is reproducible. When writing tests for game logic, favor deterministic data-driven inputs so results can be asserted exactly.
Testing analysis: 2026-09-07