Test Suite Ensure
Ensure the current project's test suite is in place: detect tech stack and framework, scaffold if necessary, generate unit tests (required, logic code only), and optionally generate/run E2E tests.
Invocation Conventions
- Standalone trigger: When the user says a trigger word, run the full flow on the current project
- Called by workflow: Scope test generation to the workflow's changed logic files
- Read SKILL.md before calling: Workflows must read this file before each invocation — never call from memory
Workflow modes
Workflow callers MUST declare one mode:
mode=advisory: If required test scaffolding is absent and the user declines it, continue with a report reminder that logic changes lack generated tests. This is non-blocking.
mode=mandatory: Refused required scaffolding or a failing unit-test run blocks exit from the execution stage. Resolve the issue or wait for the user before continuing.
Standalone invocation uses the full flow. The unit-test failure handling in Phase 5 still applies in both modes.
Boundary vs test-first-discipline
This skill is post-hoc: detect stack, scaffold, generate/run tests for existing logic, advisory vs mandatory gating. It does not own failing-test-first order. Completing test-suite-ensure MUST NOT be described as satisfying test-first-discipline. When both are in scope, hosts run test-first during behavior implementation and test-suite-ensure afterward for coverage/scaffold gaps.
Phase 1: Tech Stack Detection
Scan the project root to determine the primary language and framework:
| File |
Detection |
package.json |
JavaScript / TypeScript |
go.mod |
Go |
requirements.txt / pyproject.toml / setup.py |
Python |
pom.xml / build.gradle |
Java |
Cargo.toml |
Rust |
*.csproj / *.sln |
C# / .NET |
If package.json is detected, further identify the frontend framework:
- Contains
"vite" → prefer Vitest
- Contains
"react" / "vue" / "angular" → frontend framework (but tests still cover logic layer only)
- Contains
"next" / "nuxt" → server-side rendering framework
- Contains only
"express" / "fastify" / "koa" etc. → pure Node.js backend
Phase 2: Test Framework Detection
Detect existing test framework based on tech stack:
JavaScript / TypeScript:
jest.config.js / jest.config.ts exists, or package.json devDependencies contains jest → Jest ✅
vitest.config.js / vitest.config.ts exists, or devDependencies contains vitest → Vitest ✅
package.json scripts.test is configured → corresponding framework ✅
- None found → needs scaffolding (see Phase 3)
Python:
pytest.ini / setup.cfg [tool:pytest] / pyproject.toml [tool.pytest.ini_options] exists → Pytest ✅
devDependencies or requirements*.txt contains pytest → Pytest ✅
- None found → needs scaffolding (see Phase 3)
Go:
- Built-in
go test; detecting go.mod is sufficient ✅, no extra framework needed
Java:
pom.xml contains junit dependency, or build.gradle contains testImplementation 'junit' → JUnit ✅
Rust:
- Built-in
cargo test, no extra detection needed ✅
Phase 3: Framework Scaffolding (only when Phase 2 determines "needs scaffolding")
Select and install based on tech stack:
| Tech Stack |
Preferred Choice |
Install Command |
| TypeScript + Vite project |
Vitest |
npm install -D vitest @vitest/ui |
| TypeScript / JavaScript general |
Jest + ts-jest |
npm install -D jest ts-jest @types/jest |
| Python |
Pytest |
pip install pytest pytest-cov |
Scaffolding steps:
- Run the install command
- Create minimal config file (
vitest.config.ts / jest.config.ts / pytest.ini)
- Add
"test" entry to package.json scripts (if not present):
- Vitest:
"test": "vitest run"
- Jest:
"test": "jest"
Tool constraints: ✅ Bash allowed for install commands; ✅ Write allowed for config files
Phase 4: Unit Test Scope Determination
In Scope (Logic Code)
The following directories and file types are in scope:
services/, utils/, helpers/, lib/, core/, models/, store/, api/
- Pure logic hooks (no JSX/template rendering in
hooks/, composables/)
- Utility function files (
*.util.ts, *.helper.ts, *.service.ts)
- State management logic (Vuex / Redux / Zustand / Pinia store logic layer)
- Data processing, formatting, validation, transformation functions
Out of Scope (UI Layer — No Unit Tests)
The following directories and file types are out of scope:
components/, views/, pages/, layouts/, screens/
- Files with JSX / template rendering:
.tsx, .vue, .svelte, .jsx
*.stories.tsx, *.stories.ts (Storybook)
__mocks__/, fixtures/ (test helper files)
- Style files (
*.css, *.scss, *.less)
Scope Priority
- When called by workflow: Prioritize covering logic files from the workflow's changed files; if none provided, scan globally
- When standalone: Scan globally, prioritize logic files without corresponding test files
Phase 5: Unit Test Generation & Execution 【Required, Blocking】
Generation Principles
- Each logic file maps to one test file; if one exists, append missing cases, don't overwrite
- Each function/method must cover at least three case types:
- Happy path (normal input)
- Boundary values (empty, zero, extreme input)
- Error path (exception thrown, invalid input)
- Use the framework's native assertions; don't introduce extra assertion libraries
Test File Naming Conventions
| Framework |
Naming Convention |
Recommended Location |
| Jest / Vitest |
<name>.spec.ts or <name>.test.ts |
Same dir as source, or __tests__/ |
| Pytest |
test_<name>.py or <name>_test.py |
tests/ dir or same dir as source |
| Go |
<name>_test.go |
Same dir as source (same package) |
| JUnit |
<Name>Test.java |
src/test/java/ matching package path |
Running
For Node / JavaScript / TypeScript projects, align the Node version to the project-declared version before running — invoke the node-version-discipline skill (it probes the full chain .nvmrc / .node-version / .tool-versions / volta / engines.node / CI config, and asks the user if none declared). Tests on the wrong Node version produce false passes / false fails. Other stacks (Python / Go / Rust / Java) are unaffected.
# JavaScript / TypeScript (Jest)
npm test -- --passWithNoTests
# JavaScript / TypeScript (Vitest)
npx vitest run
# Python
pytest --tb=short
# Go
go test ./...
# Rust
cargo test
# Java (Maven)
mvn test
# Java (Gradle)
./gradlew test
Blocking Conditions
When unit tests fail (non-zero exit code):
- Output failed test list (filename + test name + error message)
- Attempt auto-fix (max 2 rounds: analyze error → modify test code or implementation)
- After 2 rounds still failing: stop, wait for user intervention, output:
- Failure cause analysis
- Suggested fix direction (modify implementation / adjust test expectations / manually add mocks)
Phase 6: E2E Test Detection & Execution 【Optional】
Detect E2E Support
| Config File |
Framework |
playwright.config.ts / playwright.config.js |
Playwright |
cypress.config.ts / cypress.config.js |
Cypress |
nightwatch.conf.js / nightwatch.conf.ts |
Nightwatch |
wdio.conf.js / wdio.conf.ts |
WebdriverIO |
- Detected → proceed with E2E test generation and execution
- Not detected → silently skip, note in output: "No E2E framework detected, skipping"
E2E Test Generation Principles (only when framework is detected)
- Prioritize core user flows (login/registration, main business operations, key page navigation)
- When called by workflow, focus on pages/flows affected by this change
- If E2E cases exist, append, don't overwrite
Running
# Playwright
npx playwright test
# Cypress (headless mode)
npx cypress run
On E2E failure: output failure screenshot path (if any) and failure reason; do not block the main flow (E2E is optional).
Output Format
【test-suite-ensure Results】
- Tech Stack: ... (e.g. TypeScript + Vite)
- Test Framework: Existing <name> / Newly installed <name> (with config file path)
- Unit Tests:
- In-scope logic files: X
- New test files: X, Appended cases: X
- Run result: ✅ X passed, 0 failed / ❌ X failed (list failed tests)
- E2E Tests:
- Detection: Detected <framework name> / Not detected, skipped
- Run result: ✅ X passed / ❌ X failed (with screenshot path) / Skipped
Common Mistakes
| Mistake |
Consequence |
Fix |
| Including UI component files in unit test scope |
Generates meaningless render tests, high maintenance cost |
Strictly follow exclusion rules, cover logic layer only |
| Reinstalling when framework already exists |
Dependency version conflicts |
Skip Phase 3 when Phase 2 detects a framework |
| Overwriting existing test files |
Loses existing test logic |
Always use append mode, never overwrite |
| Continuing after 2+ rounds of unit test failures |
Delivering with failing tests |
Must stop after 2 rounds, wait for user intervention |
| Blocking main flow on E2E failure |
E2E is optional, shouldn't be a hard gate |
E2E failure only outputs a warning, doesn't block |
| Ignoring changed file list when called by workflow |
Test coverage too broad or missing key changes |
Prioritize changed files as scope, then expand globally |
1---2name: test-suite-ensure3description: Ensure the current project has a proper test suite — detect tech stack & framework, scaffold if needed, generate unit tests (required, logic code only), and optionally generate/run E2E tests. Triggers when user says "test-suite-ensure", 「补全测试」「生成测试」「确保测试」「补充单元测试」「添加单元测试」「检查测试覆盖」 (complete tests / generate tests / ensure tests / add unit tests / check test coverage). Also callable by solve-workflow and opsx-solve-workflow in their execution-stage test steps.4---56# Test Suite Ensure78Ensure the current project's test suite is in place: detect tech stack and framework, scaffold if necessary, generate unit tests (required, logic code only), and optionally generate/run E2E tests.910## Invocation Conventions1112- **Standalone trigger**: When the user says a trigger word, run the full flow on the current project13- **Called by workflow**: Scope test generation to the workflow's changed logic files14- **Read SKILL.md before calling**: Workflows must read this file before each invocation — never call from memory1516### Workflow modes1718Workflow callers MUST declare one mode:1920- **`mode=advisory`**: If required test scaffolding is absent and the user declines it, continue with a report reminder that logic changes lack generated tests. This is non-blocking.21- **`mode=mandatory`**: Refused required scaffolding or a failing unit-test run blocks exit from the execution stage. Resolve the issue or wait for the user before continuing.2223Standalone invocation uses the full flow. The unit-test failure handling in Phase 5 still applies in both modes.2425### Boundary vs `test-first-discipline`2627This skill is **post-hoc**: detect stack, scaffold, generate/run tests for **existing** logic, advisory vs mandatory gating. It does **not** own failing-test-first order. Completing test-suite-ensure **MUST NOT** be described as satisfying `test-first-discipline`. When both are in scope, hosts run test-first during behavior implementation and test-suite-ensure afterward for coverage/scaffold gaps.2829---3031## Phase 1: Tech Stack Detection3233Scan the project root to determine the primary language and framework:3435| File | Detection |36|------|-----------|37| `package.json` | JavaScript / TypeScript |38| `go.mod` | Go |39| `requirements.txt` / `pyproject.toml` / `setup.py` | Python |40| `pom.xml` / `build.gradle` | Java |41| `Cargo.toml` | Rust |42| `*.csproj` / `*.sln` | C# / .NET |4344If `package.json` is detected, further identify the frontend framework:4546- Contains `"vite"` → prefer Vitest47- Contains `"react"` / `"vue"` / `"angular"` → frontend framework (but tests still cover logic layer only)48- Contains `"next"` / `"nuxt"` → server-side rendering framework49- Contains only `"express"` / `"fastify"` / `"koa"` etc. → pure Node.js backend5051---5253## Phase 2: Test Framework Detection5455Detect existing test framework based on tech stack:5657**JavaScript / TypeScript:**5859- `jest.config.js` / `jest.config.ts` exists, or `package.json` `devDependencies` contains `jest` → Jest ✅60- `vitest.config.js` / `vitest.config.ts` exists, or `devDependencies` contains `vitest` → Vitest ✅61- `package.json` `scripts.test` is configured → corresponding framework ✅62- None found → needs scaffolding (see Phase 3)6364**Python:**6566- `pytest.ini` / `setup.cfg [tool:pytest]` / `pyproject.toml [tool.pytest.ini_options]` exists → Pytest ✅67- `devDependencies` or `requirements*.txt` contains `pytest` → Pytest ✅68- None found → needs scaffolding (see Phase 3)6970**Go:**7172- Built-in `go test`; detecting `go.mod` is sufficient ✅, no extra framework needed7374**Java:**7576- `pom.xml` contains `junit` dependency, or `build.gradle` contains `testImplementation 'junit'` → JUnit ✅7778**Rust:**7980- Built-in `cargo test`, no extra detection needed ✅8182---8384## Phase 3: Framework Scaffolding (only when Phase 2 determines "needs scaffolding")8586Select and install based on tech stack:8788| Tech Stack | Preferred Choice | Install Command |89|-----------|-----------------|-----------------|90| TypeScript + Vite project | Vitest | `npm install -D vitest @vitest/ui` |91| TypeScript / JavaScript general | Jest + ts-jest | `npm install -D jest ts-jest @types/jest` |92| Python | Pytest | `pip install pytest pytest-cov` |9394Scaffolding steps:95961. Run the install command972. Create minimal config file (`vitest.config.ts` / `jest.config.ts` / `pytest.ini`)983. Add `"test"` entry to `package.json` `scripts` (if not present):99 - Vitest: `"test": "vitest run"`100 - Jest: `"test": "jest"`101102**Tool constraints**: ✅ Bash allowed for install commands; ✅ Write allowed for config files103104---105106## Phase 4: Unit Test Scope Determination107108### In Scope (Logic Code)109110The following directories and file types are **in scope**:111112- `services/`, `utils/`, `helpers/`, `lib/`, `core/`, `models/`, `store/`, `api/`113- Pure logic hooks (no JSX/template rendering in `hooks/`, `composables/`)114- Utility function files (`*.util.ts`, `*.helper.ts`, `*.service.ts`)115- State management logic (Vuex / Redux / Zustand / Pinia store logic layer)116- Data processing, formatting, validation, transformation functions117118### Out of Scope (UI Layer — No Unit Tests)119120The following directories and file types are **out of scope**:121122- `components/`, `views/`, `pages/`, `layouts/`, `screens/`123- Files with JSX / template rendering: `.tsx`, `.vue`, `.svelte`, `.jsx`124- `*.stories.tsx`, `*.stories.ts` (Storybook)125- `__mocks__/`, `fixtures/` (test helper files)126- Style files (`*.css`, `*.scss`, `*.less`)127128### Scope Priority1291301. **When called by workflow**: Prioritize covering logic files from the workflow's changed files; if none provided, scan globally1312. **When standalone**: Scan globally, prioritize logic files without corresponding test files132133---134135## Phase 5: Unit Test Generation & Execution 【Required, Blocking】136137### Generation Principles138139- Each logic file maps to one test file; if one exists, **append** missing cases, don't overwrite140- Each function/method must cover at least three case types:141 - Happy path (normal input)142 - Boundary values (empty, zero, extreme input)143 - Error path (exception thrown, invalid input)144- Use the framework's native assertions; don't introduce extra assertion libraries145146### Test File Naming Conventions147148| Framework | Naming Convention | Recommended Location |149|-----------|-------------------|---------------------|150| Jest / Vitest | `<name>.spec.ts` or `<name>.test.ts` | Same dir as source, or `__tests__/` |151| Pytest | `test_<name>.py` or `<name>_test.py` | `tests/` dir or same dir as source |152| Go | `<name>_test.go` | Same dir as source (same package) |153| JUnit | `<Name>Test.java` | `src/test/java/` matching package path |154155### Running156157> For Node / JavaScript / TypeScript projects, align the Node version to the project-declared version before running — invoke the `node-version-discipline` skill (it probes the full chain `.nvmrc` / `.node-version` / `.tool-versions` / `volta` / `engines.node` / CI config, and asks the user if none declared). Tests on the wrong Node version produce false passes / false fails. Other stacks (Python / Go / Rust / Java) are unaffected.158159```bash160# JavaScript / TypeScript (Jest)161npm test -- --passWithNoTests162163# JavaScript / TypeScript (Vitest)164npx vitest run165166# Python167pytest --tb=short168169# Go170go test ./...171172# Rust173cargo test174175# Java (Maven)176mvn test177178# Java (Gradle)179./gradlew test180```181182### Blocking Conditions183184When unit tests fail (non-zero exit code):1851861. Output failed test list (filename + test name + error message)1872. Attempt auto-fix (max **2 rounds**: analyze error → modify test code or implementation)1883. After 2 rounds still failing: **stop, wait for user intervention**, output:189 - Failure cause analysis190 - Suggested fix direction (modify implementation / adjust test expectations / manually add mocks)191192---193194## Phase 6: E2E Test Detection & Execution 【Optional】195196### Detect E2E Support197198| Config File | Framework |199|-------------|-----------|200| `playwright.config.ts` / `playwright.config.js` | Playwright |201| `cypress.config.ts` / `cypress.config.js` | Cypress |202| `nightwatch.conf.js` / `nightwatch.conf.ts` | Nightwatch |203| `wdio.conf.js` / `wdio.conf.ts` | WebdriverIO |204205- **Detected** → proceed with E2E test generation and execution206- **Not detected** → silently skip, note in output: "No E2E framework detected, skipping"207208### E2E Test Generation Principles (only when framework is detected)209210- Prioritize core user flows (login/registration, main business operations, key page navigation)211- When called by workflow, focus on pages/flows affected by this change212- If E2E cases exist, **append**, don't overwrite213214### Running215216```bash217# Playwright218npx playwright test219220# Cypress (headless mode)221npx cypress run222```223224On E2E failure: output failure screenshot path (if any) and failure reason; **do not block** the main flow (E2E is optional).225226---227228## Output Format229230```text231【test-suite-ensure Results】232- Tech Stack: ... (e.g. TypeScript + Vite)233- Test Framework: Existing <name> / Newly installed <name> (with config file path)234- Unit Tests:235 - In-scope logic files: X236 - New test files: X, Appended cases: X237 - Run result: ✅ X passed, 0 failed / ❌ X failed (list failed tests)238- E2E Tests:239 - Detection: Detected <framework name> / Not detected, skipped240 - Run result: ✅ X passed / ❌ X failed (with screenshot path) / Skipped241```242243---244245## Common Mistakes246247| Mistake | Consequence | Fix |248|---------|-------------|-----|249| Including UI component files in unit test scope | Generates meaningless render tests, high maintenance cost | Strictly follow exclusion rules, cover logic layer only |250| Reinstalling when framework already exists | Dependency version conflicts | Skip Phase 3 when Phase 2 detects a framework |251| Overwriting existing test files | Loses existing test logic | Always use append mode, never overwrite |252| Continuing after 2+ rounds of unit test failures | Delivering with failing tests | Must stop after 2 rounds, wait for user intervention |253| Blocking main flow on E2E failure | E2E is optional, shouldn't be a hard gate | E2E failure only outputs a warning, doesn't block |254| Ignoring changed file list when called by workflow | Test coverage too broad or missing key changes | Prioritize changed files as scope, then expand globally |