/nw-test-design-mandates-scenario-design
Scenario-design mandates for acceptance tests — Hexagonal Boundary Enforcement (drive through driving ports, never internals), Business Language Abstraction (three abstraction layers), User Journey Completeness, Pure Function Extraction Before Fixtures, Algebraic Analysis Before
Claude Code
$ npx -y skills add nWave-ai/nWave --skill nw-test-design-mandates-scenario-design --agent claude-code
Codex
$ npx skills add nWave-ai/nWave --skill nw-test-design-mandates-scenario-design -a codex -y
Cursor
$ npx skills add nWave-ai/nWave --skill nw-test-design-mandates-scenario-design -a cursor -y
Gemini CLI
$ npx skills add nWave-ai/nWave --skill nw-test-design-mandates-scenario-design -a gemini-cli -y
GitHub Copilot
$ npx skills add nWave-ai/nWave --skill nw-test-design-mandates-scenario-design -a github-copilot -y
OpenCode
$ npx skills add nWave-ai/nWave --skill nw-test-design-mandates-scenario-design -a opencode -y
Windsurf
$ npx skills add nWave-ai/nWave --skill nw-test-design-mandates-scenario-design -a windsurf -y
SKILL.md
nw-test-design-mandates-scenario-design.SKILL.mdname: nw-test-design-mandates-scenario-design
description: "Scenario-design mandates for acceptance tests — Hexagonal Boundary Enforcement (drive through driving ports, never internals), Business Language Abstraction (three abstraction layers), User Journey Completeness, Pure Function Extraction Before Fixtures, Algebraic Analysis Before the Scenario (name the law, find its narrowest surface, declare every gated input, prove the scenario can fail), the 3 Pillars style backbone, and Walking Skeleton Strategy. Consult while shaping or judging a scenario's boundary, language, journey completeness, and fixture strategy. Canonical definitions; SSOT for these mandates."
user-invocable: false
disable-model-invocation: true
Test-Design Mandates — Scenario Design
**Kind**: KNOWLEDGE (reference). No forced sequence — consulted on its trigger.
**Trigger**: you are shaping or judging a scenario's SHAPE — what to drive (boundary), what language to use, whether it is a complete user journey, and whether fixtures are parameterized correctly. Mandates 1-4 + the 3 Pillars + Walking Skeleton Strategy.
Numbering is an SSOT-internal index defined in the recomposing core `nw-test-design-mandates`; refer to mandates by descriptive name externally. Language-convention frame (non-Python target adaptation) lives in the core — read it before applying any code example below.
Mandate 1: Hexagonal Boundary Enforcement
Tests invoke through driving ports (entry points), never internal components.
Driving Ports (Test Through These)
Application services/orchestrators | API controllers/CLI handlers | Message consumers/event handlers | Public API facade classes | For a library: its public function/value API (the exported surface a consumer imports) — a library's public function is a driving port exactly like a service method.
Not Entry Points (Never Test Directly)
Internal validators, parsers, formatters | Domain entities/value objects | Repository implementations | Internal service components | A library's private/internal classes and helpers not part of its exported API
Public Library API vs Private Internal Domain Objects
A domain library distinguishes its PUBLIC function/value API (what a consumer is allowed to import and call — the driving boundary) from PRIVATE internal domain objects (implementation detail behind that API). Tests couple to the former only. Coupling to a private internal class or helper — even one that looks stable — is the same boundary violation as calling an internal validator directly; it breaks the moment internals are refactored even though the public contract did not change.
Expected outcomes are derived independently from the requirements/spec, never by reading the implementation and echoing back whatever it currently does — an oracle copied from the code under test cannot catch a defect in that code.
Correct Pattern
# Invoke through system entry point (driving port)
from myapp.orchestrator import AppOrchestrator
def when_user_performs_action(self):
orchestrator = AppOrchestrator()
self.result = orchestrator.perform_action(
context=self.context
)Violation Pattern
# Invoking internal component directly
from myapp.validator import InputValidator # INTERNAL
def when_user_validates_input(self):
validator = InputValidator() # WRONG BOUNDARY
self.result = validator.validate(self.input)Testing internal components creates Testing Theater: tests pass but users cannot access feature through actual entry point. Integration wiring bugs remain hidden.
Mandate 2: Business Language Abstraction
Step methods speak business language, abstract all technical details.
Three Abstraction Layers
**Layer 1 — Business scenario**: Describe the admitted context, user action and outcome with domain terms in the native test layout. Gherkin below is an illustration, not a required dependency. Public protocol terms are valid when the user's actual contract is that protocol.
Scenario: Customer places order for available product
Given customer has items in shopping cart
When customer submits order
Then order is confirmed
And customer receives confirmation email
**Layer 2 - Step Methods**: Business service delegation. Method names use domain terms | Delegate to business service layer (OrderService, not HTTP client) | Assert business outcomes (order.is_confirmed()), not technical state (status_code == 201)
def when_customer_submits_order(self):
self.result = self.order_service.place_order(
customer=self.customer, items=self.cart_items
)
def then_order_is_confirmed(self):
assert self.result.is_confirmed()
assert self.result.has_order_number()**Layer 3 - Business Services**: Production services handle technical implementation. HTTP calls, DB transactions, SMTP hidden inside service layer.
Test Smell Indicators
`requests.post()` in step method | `db.execute()` in step method | `assert response.status_code` | Technical terms in Gherkin
File/Function Naming
Test file and function names describe the feature/business value under test, not test bookkeeping (`test_1`, `test_helper_setup`, `test_case_final_v2`). The canonical test-identifier rule is `nw-test-design-mandates` → Durable outcome naming; apply it to files and functions as well as scenarios.
Mandate 3: User Journey Completeness
User-journey tests validate complete journeys with business value, not isolated technical operations; focused contract/property tests protect a named observable contract at its declared boundary.
Complete Journey Structure
Each scenario body visibly composes typed business-language Given steps, exactly one When, then Then steps for user journeys, or Arrange steps, exactly one Act, then Assert steps for focused contract/property tests. Given/When (or Arrange/Act) steps drive the public driving port; Then/Assert steps own business-named assertions
Read more
name: nw-test-design-mandates-scenario-design description: "Scenario-design mandates for acceptance tests — Hexagonal Boundary Enforcement (drive through driving ports, never internals), Business Language Abstraction (three abstraction layers), User Journey Completeness, Pure Function Extraction Before Fixtures, Algebraic Analysis Before the Scenario (name the law, find its narrowest surface, declare every gated input, prove the scenario can fail), the 3 Pillars style backbone, and Walking Skeleton Strategy. Consult while shaping or judging a scenario's boundary, language, journey completeness, and fixture strategy. Canonical definitions; SSOT for these mandates." user-invocable: false disable-model-invocation: true
Test-Design Mandates — Scenario Design
**Kind**: KNOWLEDGE (reference). No forced sequence — consulted on its trigger.
**Trigger**: you are shaping or judging a scenario's SHAPE — what to drive (boundary), what language to use, whether it is a complete user journey, and whether fixtures are parameterized correctly. Mandates 1-4 + the 3 Pillars + Walking Skeleton Strategy.
Numbering is an SSOT-internal index defined in the recomposing core `nw-test-design-mandates`; refer to mandates by descriptive name externally. Language-convention frame (non-Python target adaptation) lives in the core — read it before applying any code example below.
Mandate 1: Hexagonal Boundary Enforcement
Tests invoke through driving ports (entry points), never internal components.
Driving Ports (Test Through These)
Application services/orchestrators | API controllers/CLI handlers | Message consumers/event handlers | Public API facade classes | For a library: its public function/value API (the exported surface a consumer imports) — a library's public function is a driving port exactly like a service method.
Not Entry Points (Never Test Directly)
Internal validators, parsers, formatters | Domain entities/value objects | Repository implementations | Internal service components | A library's private/internal classes and helpers not part of its exported API
Public Library API vs Private Internal Domain Objects
A domain library distinguishes its PUBLIC function/value API (what a consumer is allowed to import and call — the driving boundary) from PRIVATE internal domain objects (implementation detail behind that API). Tests couple to the former only. Coupling to a private internal class or helper — even one that looks stable — is the same boundary violation as calling an internal validator directly; it breaks the moment internals are refactored even though the public contract did not change.
Expected outcomes are derived independently from the requirements/spec, never by reading the implementation and echoing back whatever it currently does — an oracle copied from the code under test cannot catch a defect in that code.
Correct Pattern
# Invoke through system entry point (driving port)
from myapp.orchestrator import AppOrchestrator
def when_user_performs_action(self):
orchestrator = AppOrchestrator()
self.result = orchestrator.perform_action(
context=self.context
)Violation Pattern
# Invoking internal component directly
from myapp.validator import InputValidator # INTERNAL
def when_user_validates_input(self):
validator = InputValidator() # WRONG BOUNDARY
self.result = validator.validate(self.input)Testing internal components creates Testing Theater: tests pass but users cannot access feature through actual entry point. Integration wiring bugs remain hidden.
Mandate 2: Business Language Abstraction
Step methods speak business language, abstract all technical details.
Three Abstraction Layers
**Layer 1 — Business scenario**: Describe the admitted context, user action and outcome with domain terms in the native test layout. Gherkin below is an illustration, not a required dependency. Public protocol terms are valid when the user's actual contract is that protocol.
Scenario: Customer places order for available product Given customer has items in shopping cart When customer submits order Then order is confirmed And customer receives confirmation email
**Layer 2 - Step Methods**: Business service delegation. Method names use domain terms | Delegate to business service layer (OrderService, not HTTP client) | Assert business outcomes (order.is_confirmed()), not technical state (status_code == 201)
def when_customer_submits_order(self):
self.result = self.order_service.place_order(
customer=self.customer, items=self.cart_items
)
def then_order_is_confirmed(self):
assert self.result.is_confirmed()
assert self.result.has_order_number()**Layer 3 - Business Services**: Production services handle technical implementation. HTTP calls, DB transactions, SMTP hidden inside service layer.
Test Smell Indicators
`requests.post()` in step method | `db.execute()` in step method | `assert response.status_code` | Technical terms in Gherkin
File/Function Naming
Test file and function names describe the feature/business value under test, not test bookkeeping (`test_1`, `test_helper_setup`, `test_case_final_v2`). The canonical test-identifier rule is `nw-test-design-mandates` → Durable outcome naming; apply it to files and functions as well as scenarios.
Mandate 3: User Journey Completeness
User-journey tests validate complete journeys with business value, not isolated technical operations; focused contract/property tests protect a named observable contract at its declared boundary.
Complete Journey Structure
Each scenario body visibly composes typed business-language Given steps, exactly one When, then Then steps for user journeys, or Arrange steps, exactly one Act, then Assert steps for focused contract/property tests. Given/When (or Arrange/Act) steps drive the public driving port; Then/Assert steps own business-named assertions
Other skills on nwave.
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about nw-test-design-mandates-scenario-design.
- Which coding agents can use nw-test-design-mandates-scenario-design?
- nw-test-design-mandates-scenario-design installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

