mirror of
https://github.com/motajs/template.git
synced 2026-09-13 18:38:50 +08:00
114 lines
6.8 KiB
Markdown
114 lines
6.8 KiB
Markdown
# Testing Patterns
|
|
|
|
**Analysis Date:** 2026-09-07
|
|
|
|
## Test Framework
|
|
|
|
**Runner:**
|
|
- [Vitest](https://vitest.dev) `^4.0.18` — declared in `package.json` `devDependencies`
|
|
|
|
**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-compatible `describe`/`it`/`test` globals. No `@testing-library/*`, `jsdom`, or `happy-dom` is installed.
|
|
|
|
**Run Commands (`package.json`):**
|
|
```bash
|
|
pnpm test # Run all tests (runs `vitest`)
|
|
```
|
|
|
|
There is **no** dedicated watch mode or coverage script. To run watch/coverage manually:
|
|
```bash
|
|
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:
|
|
|
|
1. The user requests tests for a feature.
|
|
2. The agent analyzes the feature and proposes test cases in a markdown document (placed in `docs/test/`, following `docs/test/template.md`).
|
|
3. The user reviews the proposal over several rounds until the plan is finalized.
|
|
4. The agent writes the test cases from the document. The agent **must not** run the test command; the user runs it.
|
|
5. 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:**
|
|
```md
|
|
# 测试目的
|
|
|
|
测试 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` / `IDataSystem` layer 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.yml` only builds and deploys static content to GitHub Pages; it runs `pnpm build`, **not** tests.
|
|
- `.github/workflows/codeql.yml` runs 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*
|