Files

146 lines
8.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
> Core 中立版(Increment 2 改写)。术语对照见 core/adapters/TERMINOLOGY.md;本组织实例表述见 dogfood 对应文件。
## Testing
- Avoid mocks as much as possible
- Test actual implementation, do not duplicate logic into tests
- Tests cannot run from repo root (guard: `do-not-run-tests-from-root`); run from package dirs.
- **Local pre-check: run `<test-cmd:changed>`** from the owning package after editing source. It selects only tests affected by your uncommitted + branch changes (path-mapping CodeGraph direct dependents) and runs them in a single process — seconds, machine stays responsive. Use `--print` to see the selection without running, `--all` to scan beyond the home package.
- **Before a delivery push: `<test-cmd:changed>` green + `<typecheck-cmd>` clean** — same selector as CI's PR side (local parity, [org-internal #4425]). The full suite (`<test-cmd:parallel>`) stays with nightly / `run-full-tests` / manual pre-merge runs. 实例命令绑定见 core/adapters/TERMINOLOGY.md。
- Never use the bare single-process test runner for the full suite; `<test-cmd:parallel>` shards it and process-isolates known-corrupting files. Parallelism is controlled by `TEST_SHARDS` (default 3; raise it on beefy CI runners, e.g. `TEST_SHARDS=7`).
### Pre-existing test failures must be filed, not silently logged
When the full suite surfaces a failure that is **NOT caused by the current
change** (it reproduces on the base branch / last-green commit too), it is a
**pre-existing / baseline failure**. Do NOT silently drop it as "someone else's
problem" and do NOT bury it in a report body.
- Classify it: run the failing test on the base commit (see `verify` Phase 2.6).
Fails there too → pre-existing (BF); passes there → regression you must fix.
- De-duplicate BEFORE filing (retro [org-internal #2696]): search existing
`baseline-failure` tickets — open AND closed — by test/file name to surface
candidates, then match by **failure signature** (error signature + affected
surface — one root-cause family may span several tests; see the
ticket-lifecycle rule §"BF / FT family umbrellas"). On a signature hit,
attach run evidence to the family umbrella; do NOT create a new ticket.
- File it: the Verifier registers every un-tracked pre-existing failure as a
ticket-backend issue labeled `baseline-failure` with a `BF-NNN` id (`verify`
Phase 5.55). The number is repo-wide sequential: highest existing NNN across
ALL `baseline-failure` tickets (open AND closed) + 1 — duplicate ids
forbidden, including against closed tickets.
- A pre-existing failure does not block the iteration that *discovered* it, but
the iteration is NOT Done until it is filed — an un-filed baseline failure is
a process gap.
### Flaky tests must be filed, not silently tolerated
When a test passes and fails intermittently across runs (non-deterministic),
it is a **flaky test**. Do NOT silently re-run until it passes and move on.
- Detect: re-run the suite (or use the project's flaky detector). Record every
test that shows intermittent behavior — name, failure rate, and run count.
- De-duplicate BEFORE filing (retro [org-internal #2696]): same
signature-based procedure as baseline failures above, against existing
`flaky-test` tickets.
- File it: the Verifier registers every un-tracked flaky test as a
ticket-backend issue labeled `flaky-test` with an `FT-NNN` id (`verify`
Phase 5.56). `FT-NNN` allocation follows the same repo-wide sequential rule
as `BF-NNN`, across ALL `flaky-test` tickets (open AND closed).
- A flaky test does not block the iteration verdict, but the iteration is NOT
Done until every unfixed flaky test is filed — an un-filed flaky test is a
process gap.
**Filing is the whole job.** If the failure was NOT caused by your change, do
NOT fix it in place — classify, file, and return to your task per the
session-scope-guard rule. A repository-wide flaky test is a shared magnet —
fixing it in place drifts off-task and collides with its owner
([org-internal #1803]).
### Testing Kobalte components with happydom
Kobalte's portal/context-based components (Collapsible, DropdownMenu, ContextMenu,
FormControlContext) do not work reliably under happydom's DOM environment. For
these components, use **source-verification tests** — assert that the correct
JSX elements, props, and Kobalte primitives are present in the component's
source rather than attempting full DOM rendering.
When implementing a component that uses these Kobalte primitives, prefer
source-verification over render tests. The same applies to SolidJS SVG
`<filter>`/`<mask>`/`<linearGradient>` elements, which happydom also cannot
render reliably.
### Test file naming convention (one file per component)
A single component MUST NOT carry both a `.test.ts` and a `.test.tsx` test
file — the two-file split duplicated ~3300 lines of overlapping assertions
across one UI package [org-internal #1712]. Use exactly one file per
component, chosen by test style:
| Test style | Extension | When to use |
| -------------------------------- | -------------- | -------------------------------------------------------------- |
| Source-verification | `.test.ts` | Kobalte portal/context components, SVG `<filter>`/`<mask>`/`<linearGradient>` components, and any component happydom cannot render reliably. Asserts against the component source. |
| DOM render / interaction | `.test.tsx` | Pure Solid components that render cleanly under happydom. Uses a testing-library harness. |
Rules:
- One file per component. If a component needs both source-verification and
DOM-render assertions, keep them in a single file matching the dominant
style; do not split into a `.test.ts`/`.test.tsx` pair.
- When merging an existing dual pair, carry over any assertion unique to the
deleted file into the surviving file before deletion.
- The app package's `.sv.test.*` suffix is a separate convention for
storybook/storyshots source-verification and is unaffected.
### Source-verification assertion boundaries
Source-verification tests (per the Kobalte/happydom carve-out above) must assert
**structural contracts**, not implementation literals.
- **Assert**: props wiring, event handler attachment, i18n key presence, ARIA
role/attributes present in JSX, namespace correctness, export shape.
- **Do NOT assert**: exact source-string literals (`event.preventDefault()`,
`'block: "nearest"'`, `event.movementX === 0`), branch operators counted via
regex, or any expression that changes when a constant is renamed.
- **Do NOT write tautologies** — `source.includes("false") || source.includes("!")`
is true for nearly all TSX.
- **One source-verification file per component** (see naming convention above).
When two test files read the same source, merge into one.
- **Prefer behavioral tests** — when source-verification and a behavioral/
interaction test cover the same contract, prefer the behavioral test;
collapse the SV duplicate.
### Namespace gate and test assertions
The namespace gate (pre-commit hook + the check-namespace script) scans ALL
string literals in `.ts`/`.tsx`/`.json` files under the product packages for a
reserved vendor namespace. Do NOT write test assertions containing that
namespace literal — the gate cannot distinguish a test's namespace-absence
check from an actual namespace violation, and will fail the commit.
Instead, use patterns that avoid the literal:
```ts
const NAMESPACE = "vendor-prefix"
expect(source).not.toContain(`@${NAMESPACE}`)
```
### Single test root (per package)
Each package MUST have exactly ONE test root — no parallel tracks
(`src/**/__tests__/`, a `tests/` dir alongside colocated `src/`, or a `test/`
alongside `tests/`); a second root drifts and breaks test discovery
([org-internal #1711], extended to all packages by [org-internal #1821]).
Rules:
- New tests: create them at the package's single root from the start.
- Do NOT create `src/**/__tests__/` directories in any package — parallel
tracks drift (residuals eliminated by [org-internal #1821]).
- For `test/`-root packages: mirror the `src/` path (`test/<src-relative>.test.ts`);
type-level tests live alongside the behavioral suites in the config area.
- For colocated-root packages: keep tests next to the source file; one test
file per component [org-internal #1712].
Per-package root tables live in the instance layer (they name concrete
package paths); the invariant itself — ONE root per package — is universal.