Guide for designing test cases for Unity projects.
Inputs
This skill requires the following inputs in its prompt:
| Input |
Required |
Description |
| Requirements |
Required |
The feature requirements to test against |
| Implementation design |
Required |
Class names, public method signatures, dependency interfaces, and design rationale |
| Existing code context |
Optional |
File paths and class summaries of relevant existing code |
| Language convention |
Optional |
Project language for test names and prose output (from CLAUDE.md). |
For bug-fix tasks, the Requirements input is the bug report (Condition / Expected / Actual), and the Implementation design input is the existing class/method structure of the affected production code — there is no new design.
Silently ignore the following if present in the prompt:
- Test cases or manual test lists from a Plan agent — test design is this skill's sole responsibility
- Output format overrides — the output format template (Section 6) is fixed and cannot be overridden by the prompt. Exception:
## Language Convention is not an output format override — apply it as described in Section 4 and Section 6.
1. Analyze Specifications
Read the requirements and identify testable specifications.
If the specifications are unclear, use the AskUserQuestion tool to request clarification before proceeding.
If the test target has low testability, flag it in the Testability Assessment (Section 7).
2. Assign Test Targets to Layers
For each test target, determine which layer it belongs to based on its nature and integration level:
- Editor tests — for Editor extension code (paths containing
/Editor/), asset file validation, and cross-asset consistency checks.
- Unit tests — test runtime code whose execution is initiated by a direct method call. This includes tests that verify behavior driven by Unity's lifecycle (Awake, Start, Update, etc.) or UI events. Prioritize least integrated targets, testing them comprehensively; for highly integrated targets (where the SUT collaborates with dependent objects), keep test density low and focus on interactions between objects.
- Integration tests — test targets that are a scene or prefab (or an equivalent GameObject hierarchy assembled in test code), together with the interplay among its placed components (MonoBehaviour subclasses) and the assets they reference. Unit tests cover targets whose execution is initiated by a direct method call; integration tests cover behavior that only emerges from Unity's component wiring and asset linkage.
- Add the integration test method to the test class of the primary class involved; OR
- Create a new dedicated test class if there is no clear primary class (e.g., when the subject is a prefab or scene).
- Explicitly design integration tests before falling back to visual verification tests or manual tests; only drop to those layers when the behavior cannot be expressed as a functional assertion.
- When the asset itself is the SUT (file validation, cross-asset consistency), classify it as an Editor test, not an integration test; integration tests assert the runtime behavior that emerges from a scene/prefab's linkage to its assets.
- Visual verification tests — verify that actual on-screen rendering conforms to the intended design: positional relationships between elements, typography (font size, font style, and font family), text/background contrast and legibility, visual state representation (e.g., a disabled button looks grayed out), and rendering quality (no sprite distortion, ghosting, or unintended clipping). Take screenshots in the test code, and image analysis (see Section 4). A deterministic mid-point of an animation (e.g., an attack lunge at its peak, a fade-out at half time) can also be captured and verified here; only subjective motion feel belongs to manual tests. Design these before falling back to manual tests.
- Manual tests — reserved for items that neither automated tests nor image analysis can verify — i.e., items requiring human sensory judgment with no objective pass/fail criterion (e.g., game feel, animation polish, audio balance). Do NOT add manual tests for scenarios already covered by integration tests or visual verification tests, even if they seem "worth confirming by eye."
Note: Never use Edit Mode tests for runtime code logic. Edit Mode and Play Mode test runners cannot execute simultaneously — splitting coverage for a single SUT between the two modes prevents running all tests at once. Play Mode tests can run on actual devices (player builds), which Editor tests cannot.
3. Select Testing Techniques
Prefer specification-based tests over structural (implementation-coupled) tests. Structural tests break under refactoring and lose value fast. It's fine to write a structural test temporarily when you're unsure about an implementation, but plan to delete it once specification tests cover the same behavior.
For each test target, select appropriate techniques:
- Equivalence partitioning — group inputs into valid/invalid partitions; one representative per partition. When an invalid equivalence partition exists but the spec does not define its behavior (e.g., what happens for negative input, out-of-range values, null), use the
AskUserQuestion tool to confirm the expected behavior before deriving test cases. Do not guess or invent the behavior.
- Boundary value analysis — test at the edges of each equivalence partition. Over-testing boundaries inflates the number of test cases and increases maintenance cost on every spec change. Mitigate this with parameterized tests that consolidate boundary cases into a single test method. When the spec doesn't differentiate behavior near edges (e.g., display color mapping), a representative per equivalence partition is sufficient and boundary testing can be skipped entirely.
- State transition testing — if the target has a finite-state-machine (FSM); one test case covers only 0-switch coverage (covering every direct transition from state A to state B, with no intermediate states in between)
- Decision table testing — if multiple conditions combine to produce different outcomes
- Error guessing — experience-based; derive cases from failure patterns common in game development. Examples to consider: rapid button mashing, simultaneous button press, input during scene transition / loading, collision tunneling, random distribution bias or PRNG sequence looping, numeric overflow, network failure. Use this to surface implementation concerns that spec-based techniques don't reach.
Deriving test methods from equivalence partitions
The most common derivation error is merging partitions with different expected outcomes into one (parameterized) method, encoding the difference as a condition in the name/Verification (e.g. ..._InteractableMatchesNonEmpty, "interactable is true only when non-empty"). One rule prevents it:
One test method = one equivalence partition = one definite expected outcome. Never parameterize the expected outcome. If the expected value changes with the input, the inputs belong to different partitions → separate test methods, each named after its own outcome.
For each input variable:
- Partition the input domain into classes the spec says produce the same outcome.
- Emit one method per partition, named
..._<Partition>_<ThatPartitionsOutcome>. The <Expected> segment is a concrete state/value (IsInteractable, IsNotInteractable), never a condition word (Matches…, …WhenNonEmpty, DependingOn…).
- Within one partition, consolidate multiple representatives (and that partition's boundary values) into one parameterized method — they share the outcome (see Parameterized tests).
Worked example — drawPileButton.interactable driven by the draw pile count:
| Partition |
Representative values |
Expected outcome |
Empty (count == 0) |
0 |
interactable is false |
Non-empty (count ≥ 1) |
1 (boundary), 5 |
interactable is true |
Two partitions, two outcomes → two methods (NOT one parameterized method over {0, 1, 5}):
| Test Method |
Verification |
Sync_DrawPileIsEmpty_DrawPileButtonIsNotInteractable |
the draw pile button is not interactable |
Sync_DrawPileIsExist_DrawPileButtonIsInteractable (count: {1, 5}) |
the draw pile button is interactable |
The non-empty method keeps both 1 and 5 because they share the outcome true; 1 is the partition's boundary value, 5 an interior representative.
Boundary value analysis locates where partitions meet. For a field valid in 1–99: partitions <1 / 1–99 / >99; boundaries 0, 1 and 99, 100. Fold each partition's boundary representatives into that partition's parameterized method (e.g., valid partition over {1, 99}) — never one method per boundary. When the spec does not differentiate behavior near an edge, one representative per partition suffices and boundaries can be skipped entirely (per the Boundary value analysis technique above).
Parameterized tests
When an equivalence partition includes multiple test cases — such as argument variations within the same partition or boundary values at the partition's edges — consolidate them into a single parameterized test. All cases must belong to the same equivalence partition and share the same expected outcome.
Specifying parameter name and values in the Test Method column — write values after the method name:
- Bool parameter, all values:
(flag: (bool))
- Enum parameter, all values:
(direction: (Direction))
- Multiple parameters, all combinations (exhaustive):
(param1: {0, 1, 2}, param2: {3, 4, 5}) — when a param is bool or enum covering all its values, use the shorthand in place of the braces: (flag: (bool), count: {0, 1, 5})
- Multiple parameters, limited to specific combinations:
({param1: 0, param2: 3}, {param1: 1, param2: 4})
- Three or more parameters each with many values: write
(use pairwise) — the test-writing phase applies the pairwise (all-pairs) method to select a covering combination set
Do NOT over-consolidate: keep separate rows for tests that belong to different equivalence partitions or produce different expected outcomes.
Invalid partition
- UI input validation — test invalid inputs that a user can enter through the UI (e.g., out-of-range values in a numeric text field). These represent real failure paths at the system boundary and must be tested.
- Dependency error returns — whether to test error/failure paths from a dependency depends on its origin:
- Library or framework (external, not owned by this project) → test it; use a stub to inject the error condition.
- Game's own code (another component in this project) → skip; trust internal code correctness.
- Uncertain → use
AskUserQuestion to confirm with the user before designing test cases.
Testing randomness (PRNG-dependent SUT)
When the SUT consumes a pseudo-random number generator (UnityEngine.Random, System.Random, etc.), choose one of these strategies based on what the spec actually pins down:
- Stub the PRNG — when the spec defines a deterministic mapping from random output to behavior (e.g., "≥0.5 → heads, <0.5 → tails"). Replace the PRNG with a stub that returns canned values; assert exact outcomes.
- Range / bounds verification — when only the output range is specified (e.g., random spawn coordinates within a region). Assert with
And/Range constraints, or Within/custom comparer for tolerances. Combine with Repeat attribute so flakiness isn't masked by a single lucky run.
- Statistical-property verification — when the spec is about distribution shape (RPG damage variance, drop rates). Sample the SUT in a loop, compute statistics (mean, variance, histogram bucket counts), and assert on those. The
test-helper package (com.nowsprinting.test-helper) provides lightweight sampling helpers; reach for MathNet.Numerics only when you need rigorous statistics.
- Characteristic verification — when the SUT generates procedural content (e.g., roguelike maze). Don't assert exact output; assert structural properties the spec requires — e.g., "the exit is reachable from the entrance via path-finding," plus any algorithm-specific invariants.
Integration test perspectives
Verify from the user's perspective — assert on-screen display and UI interactions as much as possible. Avoid relying on internal state or property checks when user-visible behavior can be asserted instead.
When the test target is a scene or prefab (or an equivalent GameObject hierarchy assembled in test code) with interplaying components and assets, consider the following test perspectives:
- Multi-frame event system interactions — behaviors triggered by Unity's event system that unfold across multiple frames
- Scene transitions — behaviors that span or depend on scene loading and unloading
- Asset linkage — runtime behaviors that emerge when placed components load or reference assets (e.g., ScriptableObject data, referenced prefabs)
- UI operation sequences — click, drag, and other player operations that advance game mechanics over one or more frames
- UI blocking — verify that UI elements behind a modal dialog or overlay are unreachable (blocked from interaction); conversely, verify those elements are reachable when no overlay is present
- UI layout (layout assertion tests) — verify that buttons, toggles, and other interactive elements and text components do not overlap each other or overflow their parent containers, and that text does not overflow, using deterministic assertions:
- A layout assertion test verifies a condition expressible as a deterministic assertion (e.g., "no overlap", "no overflow", "the element is reachable"); displayed content (card data, text length, item count) is a test input, and the pass criterion never varies with it. Contrast with visual verification tests, which verify conformance to a screen-specific design intent — positional relationships like "A is displayed to the right of B", color, and typography (font size, font style, font family) are design decisions likely to change, unsuited to strict assertions; legibility (text/background contrast) is impractical to assert.
- Any layout bug expressible as a geometric predicate warrants a deterministic integration test assertion — e.g., "the element is within screen bounds", "elements do not overlap", "text does not overflow its container". Design these as integration tests only; do NOT additionally design a visual verification test for the same geometric property. Font size and style are typographic design properties, not geometric predicates, so this rule does not apply to them — but a BestFit readability floor (auto-shrunk text must not fall below a minimum readable size) has a content-independent pass criterion and stays a layout assertion test.
- One test method per condition, not per perspective: do NOT split layout assertion perspectives (no overlap, no overflow, containment, reachability, BestFit floor) into one test method each. When perspectives share the same test condition (same scene/state/inputs/resolution), consolidate them into a single test method; the
<Expected> segment may then be the generic LayoutIsCorrect (in the project language, e.g., レイアウトが正しいこと), and the Verification column lists every layout property verified (per the multi-property exception in Section 4).
- Within-screen-bounds vs. within-container: design a "within screen bounds" check only for a screen's top-level container (a dialog, popup, context menu, or other root panel whose position or size is computed dynamically) — that is the element actually at risk of clipping past the screen edge. Do NOT design a "within screen bounds" check for an element nested inside such a container; instead check it for containment in its immediate parent container. If every element already sits within a parent that is itself verified within the screen, each nested element is transitively within the screen too — a per-element screen-bounds check on top of that is redundant.
- Parameterizing a layout assertion test over all production assets (e.g., every card defined in the master data) also validates the content itself — a newly authored asset whose text overflows its view fails the test.
- Do NOT verify positional relationships between elements or on-screen positions (e.g., "A is displayed to the right of B") — approximate positions have no meaningful pass/fail criterion, and precise coordinate checks are brittle. Use visual verification tests for these instead — including coarse screen-region checks (e.g., "the version label is in the bottom-right region"). Exception (only when the user explicitly instructs): a coarse screen-region predicate (e.g., "within the bottom-right region: below 10% of screen height and right of the horizontal center") becomes deterministic when the resolution is fixed as a test condition — design it as a layout assertion test (integration test). A single fixed resolution gives no confidence that the layout holds across screens, so parameterize over the expected resolutions (at least the largest and smallest supported resolutions and the widest and narrowest supported aspect ratios), one test case per resolution with the resolution in the
<Condition> segment.
Reproduction tests (bug-fix tasks only)
When the task type is bug-fix, additionally apply the following during technique selection:
- Reproduction test — design one test case that directly triggers the reported bug. Apply error guessing and, if the SUT has state, state transition testing to identify the minimal trigger condition. This test must fail before the fix and pass after.
- Regression tests — identify adjacent behavior the fix might disturb, and apply the same techniques (equivalence partitioning, boundary value analysis, etc.) to derive coverage for those areas.
Cover and modify (refactoring tasks only)
For refactoring work, apply cover and modify: design regression coverage before changing the implementation. Treat every bug as an opportunity to grow the regression suite.
4. Create Test Cases
For each technique, derive coverage-aware test cases:
Language: <MethodName> must always match the production method name exactly — never translate it. <Condition>, <Expected>, and the Verification column prose follow the project language from the Language convention input. If no language is specified, default to English.
- Use the naming convention based on whether the test target is a method:
- Method target —
<MethodName>_<Condition>_<Expected>: all Unit tests, and Editor tests whose target is a method (Editor extension code under /Editor/).
- Non-method target —
<Condition>_<Expected>: all Integration tests and Visual verification tests (multi-component interaction or on-screen rendering), and Editor tests whose target is not a method (asset file validation, cross-asset consistency checks — the SUT is an asset or set of assets). Do NOT include a method name. Do NOT add a feature-area or category prefix before <Condition> — the name starts directly with the condition (e.g., OnVictoryForced_AllCardViewsAreFullyWithinHandArea, not Reward_OnVictoryForced_AllCardViewsAreFullyWithinHandArea).
- For parameterized tests, the
<Condition> segment is the equivalence partition name, not an enumeration of individual argument values.
- The
<Expected> segment names the concrete resulting state or value of that one partition (e.g. IsNotInteractable, ReturnsFizz), never a condition or comparison. Exception: a consolidated layout assertion test may use the generic LayoutIsCorrect (see Section 3, UI layout). Words like Matches…, OnlyWhen…, DependingOn…, BasedOn… in the name — or "only when / only if / depending on" in the Verification — signal that the outcome varies with input, meaning two partitions were merged into one method — split into one method per outcome (see Deriving test methods from equivalence partitions in Section 3).
- Do NOT create sequential IDs in test case names
- Describe the verification clearly
- Verify one condition per test. Exception: when multiple properties of the state resulting from a transition must all be correct simultaneously, a single test may assert all of them together. In that case, list each property being verified in the Verification column. The same applies to a consolidated layout assertion test asserting multiple layout properties under one condition (see Section 3, UI layout).
- Test concerns separately
- In the Verification column, state which observable property or behavior is checked and what its expected value or state is — this corresponds to the
Expected segment of the test method name, not the <Condition> segment, which the method name already captures. Write from the information already available in the prompt (requirements and design inputs); abstract descriptions are acceptable — reading source to obtain more concrete identifiers is not required. Describe observable behavior only; do NOT include any of the following anywhere in the test case output — this prohibition applies to the Verification column, class header descriptions (text after #### ClassName), and any other field:
- Test framework attributes (
[Test], [UnityTest], [LoadScene], [Category(...)], [TakeScreenshot], etc.)
- Sync vs async / coroutine choice
- Construction details of test inputs (e.g., how to build
PointerEventData, how to instantiate fixtures)
- The test's precondition or arranged state — anything that restates the
<Condition> segment already encoded in the method name (e.g., for ..._WhenBossNext_..., do NOT write "When the holder RunState has IsBossNext true, …" in Verification). State only the expected observable outcome.
- Assertion helper class names (e.g.,
LayoutAssert, GameObjectFinder)
- Exact private or serialized field names, or field-qualified member access (e.g.,
drawPileButton.interactable) whose owner is not present in the implementation design inputs — name the element descriptively instead (e.g., "the draw pile button is not interactable"). Exact identifiers are not required at design time; resolving the precise field name is a test-writing concern. You MAY name exactly: public framework API members (e.g., CanvasGroup.blocksRaycasts) and identifiers that appear in the design inputs.
- Rationale or intent text — why the test exists, what it proves about the design, or what the current (buggy) behavior is. Observable behavior only.
- Any other implementation/mechanism detail — those decisions belong to the test-writing phase
- Parameterized tests — consolidate same-partition test cases into a single table row per Parameterized tests in Section 3. Do NOT specify the framework mechanism (
TestCase, Values, etc.) in the Test Method column — that's a test-writing decision.
- Example:
FizzBuzz_MultipleOfThree_ReturnsFizz (n: 3, 6, 9) | Returns "Fizz"
- If a test case uses a spy to verify interactions, note it in the Verification column: e.g.,
(uses spy: <TargetDependency>). Do NOT note stubs or fakes — those are arrange/action concerns. xUTP definitions for reference:
- Stub — returns canned responses to isolate the SUT from a dependency. Arrange/action concern; do NOT mention in Verification.
- Spy — records interactions (calls, arguments) for later verification. Note it in Verification.
- Fake — a simplified but working implementation of a dependency. Arrange/action concern; do NOT mention in Verification.
- For visual verifications (e.g., on-screen rendering, UI layout), save a screenshot during test execution and verify it via image analysis. Note this in the Verification column along with the specific visual aspects to verify — e.g.,
(saves screenshot for image analysis: element positions within screen, no overlap between elements, correct visibility state, text/background contrast).
- NEVER create a dedicated visual verification test class — add visual verification test methods to the same test class as the functional tests.
- Screenshot resolution: By default, do not fix a specific resolution for screenshot tests — let them run at whatever resolution the test environment provides. Only fix a resolution when the test condition explicitly depends on it (e.g., verifying element positions at a stated viewport size).
- Resolution as test condition: When a test targets a specific resolution as part of its verification (e.g., layout at 960×540) — whether a screenshot test or a resolution-fixed layout assertion test (see Section 3, UI layout) — include the resolution in the
<Condition> segment of the target method name — e.g., At960x540_RendersVersionLabelAtBottomRight (these tests use <Condition>_<Expected>, with no method name). This makes each resolution a distinct, independently runnable test case.
- Visual aspects to verify in screenshots — always include the following in the
(saves screenshot for image analysis: ...) list when applicable:
- Element positions within screen, no overlap between elements, correct visibility state
- Text/background contrast — verify that text color has sufficient contrast against its background so text is clearly legible
- Typography — verify that font size, font style (bold/italic), and font family match the intended design and are consistent across equivalent elements; verify that glyphs actually render (no missing-glyph "tofu" boxes or blanks for characters the assigned font doesn't support)
- Visual state representation — when a UI state is communicated visually (a disabled button grayed out, a gauge's fill amount, a fading sprite's transparency), verify the rendering reflects that state
- Rendering quality — no sprite distortion (squashing/stretching), ghosting/afterimages, or unintended clipping
- Aspect list scope: list only aspects suited to visual verification. Facts that are mechanically assertable — a panel's active state, exact text content — belong in integration test assertions, not in the image-analysis aspect list.
Example: Verification — Bad vs. Good
| Style |
Test Method |
Verification |
| Bad (mechanism) |
OnBeginDrag_WhenDragStarts_BlocksRaycastsIsDisabled |
Call OnBeginDrag synchronously with [Test] and Assert that CanvasGroup.blocksRaycasts == false |
| Good |
OnBeginDrag_WhenDragStarts_BlocksRaycastsIsDisabled |
CanvasGroup.blocksRaycasts is disabled |
| Bad (rationale) |
StartRun_SameSeed_ProducesSameMap |
The map structure is reproduced when a run is started twice with the same seed. Fails in the current implementation where RNG is not stored in the holder (BUG 1 reproduction test) |
| Good |
StartRun_SameSeed_ProducesSameMap (reproduction test) |
The map structures of the two runs are identical |
| Bad (not parameterized) |
Sync_GivenPhase_PanelVisible |
The panel is visible only during the Defeat or Victory phase (verifies multiple argument patterns) |
| Good |
Sync_GivenPhase_PanelVisible (phase: {Defeat, Victory}) |
The panel is visible |
| Bad (condition restated) |
MapScene_OnLoad_WhenBossNext_FloorTextIsBoss |
When the holder RunState has IsBossNext true, the floor text shows "Boss" |
| Good |
MapScene_OnLoad_WhenBossNext_FloorTextIsBoss |
the floor text shows "Boss" |
The Bad (mechanism) row leaks the test-writing mechanism (attribute choice, sync invocation, exact assertion form).
The Bad (rationale) row leaks why the test exists and what the current behavior is — none of that belongs in Verification; (reproduction test) goes in the Test Method column instead.
The Bad (parameterized) row hides the concrete argument values in a vague phrase in Verification; they belong in the Test Method column as named parameters, e.g. (phase: {Defeat, Victory}).
The Bad (condition restated) row repeats the method name's <Condition> segment ("WhenBossNext") as a precondition clause; Verification states only the expected outcome, since the condition already lives in the method name.
The Good rows state the observable behavior only; all other concerns go in the Test Method column or the test-writing phase.
The merged-partitions error — encoding two different expected outcomes into one method — deserves a dedicated example (see Deriving test methods from equivalence partitions in Section 3 for the full worked example with partition tables):
| Style |
Test Method |
Verification |
| Bad (merged partitions) |
Sync_GivenDrawPileCount_DrawPileButtonInteractableMatchesNonEmpty (count: {0, 1, 5}) |
the draw pile button is interactable only when the draw pile is non-empty |
| Good |
Sync_DrawPileIsEmpty_DrawPileButtonIsNotInteractable |
the draw pile button is not interactable |
| Good |
Sync_DrawPileIsExist_DrawPileButtonIsInteractable (count: {1, 5}) |
the draw pile button is interactable |
The Bad (merged partitions) row collapses two partitions — empty (→ not interactable) and non-empty (→ interactable) — into one method, betrayed by Matches… in the name and "only when" in the Verification. Split into one method per partition with a single definite outcome; parameterize only the same-outcome representatives (1, 5).
5. Requirements Coverage Check
After completing Section 4, perform a traceability pass (acceptance tests coverage check) before writing the final output:
- Re-read the original user prompt and extract every stated requirement or behavior.
- For each requirement, identify which test case(s) designed in Section 4 cover it.
- Requirements must be covered by a same-layer witness test: the covering test must directly exercise the behavior the requirement describes — not a component that contributes to satisfying it. A requirement about on-screen display or user interaction must be covered by an integration or visual verification test; a unit test that only calls a method is not a same-layer witness for a UI-layer requirement. A requirement about method-level behavior may be witnessed by a unit test. If no same-layer test covers a requirement, record it as a gap and handle it in step 3.
- For any requirement with no covering test case:
- Add a test case, or
- Document explicitly why it is not tested (out of scope, untestable by design, etc.)
Output a coverage summary table only when gaps were found or a requirement was explicitly waived. Omit the table when all requirements are covered without exception.
| Requirement (from prompt) |
Covering test(s) |
Gap / Waiver reason |
| XXX should do Y |
MethodName_ConditionA_DoesY |
— |
| ZZZ must not allow W |
(none) |
Waived: prevented at a lower layer, not this class |
Finally, run a partition-split self-check on every test row that has parameter values in the Test Method column: for each listed parameter value, ask "does the expected outcome change when I substitute this value?" If any substitution produces a different expected outcome, those values belong to different partitions — split into one method per outcome, each with a single definite expected value, before producing final output. Reliable symptoms of a merged partition: Matches…, OnlyWhen…, DependingOn… in the <Expected> segment; "only when", "only if", or "depending on" in the Verification cell. (A plain temporal phrase such as "when drag starts" in Verification describes the test condition, not a varying outcome — it is not a symptom.)
6. Test Case Format
Output must contain the following blocks in this order:
- Test Cases — one block per layer, in this order:
### Editor tests
### Unit tests
### Integration tests
### Visual verification tests
### Manual tests
- Testability Assessment (Section 7)
Note: All layers may contain (none) when no test cases apply to that layer.
Do NOT write "Edit Mode" or "Play Mode" in test case output — that is a test-writing concern, not a design concern.
Structure by layer:
- Editor tests / Unit tests / Integration tests / Visual verification tests:
#### <ClassName> → table
- Manual tests: no class/method section; uses a table of test cases with "Test perspectives / Verification method" column instead of "Verification"
- Test perspectives — what behavioral aspects, conditions, or interactions are verified for this target. NOT a test technique name
Output markers — annotations that flag test case categories; append to the specified field only, not the Verification column:
(reproduction test) — append to the Test Method column when the test reproduces a reported bug (see Section 3, Reproduction tests)
(acceptance test) — append to the Test Method column when the test is the same-layer witness (see Section 5) for a requirement stated in the prompt: it must directly exercise the behavior the requirement describes — not a component that contributes to satisfying it. A requirement about on-screen display or user interaction requires an integration or visual verification test; a requirement about method-level behavior may be witnessed by a unit test.
(spec change) — append to the Test Method column ONLY when updating an existing test whose Verification (observable expected outcome) changes. A change to the SUT signature/type that requires only arrange/action construction updates (e.g., wrapping Foo→FooRef) while the expected observable behavior stays identical is NOT a spec change — leave such tests unmarked (construction details are a test-writing concern per Section 4, not a design concern). Litmus test: if the Verification column wording is unchanged, do NOT append (spec change).
Read the output format template for the project language and follow it exactly:
- Japanese:
${CLAUDE_SKILL_DIR}/assets/output-format-ja.md
- All other languages (default):
${CLAUDE_SKILL_DIR}/assets/output-format.md
If the project language is neither Japanese nor English, use output-format.md as the structural reference and write <Condition>, <Expected>, and Verification prose in the project language.
7. Testability Assessment
After designing all test cases, evaluate and output a Testability Assessment at the end of your response.
Use one of the following labels:
| Label |
Meaning |
TESTABILITY: PASS |
All public methods are independently testable; test case count is realistic |
TESTABILITY: WARN |
Localized concerns (e.g., too many test doubles, large integration tests, high FSM state combinations) |
TESTABILITY: FAIL |
Fundamental testability issues that require design revision |
FAIL criteria — flag FAIL if any of the following apply:
- Unit test boundaries cannot be drawn (SUT is too large)
- State is hidden and cannot be verified externally
- Combinatorial explosion: test case count grows faster than O(n) relative to the number of conditions
- Dependencies cannot be injected (static/global coupling,
new inside constructor, etc.)
Output format for the assessment section:
### Testability Assessment
TESTABILITY: PASS
or, for WARN/FAIL, include Testability Issues with specific problem locations and proposed remedies:
### Testability Assessment
TESTABILITY: FAIL
#### Testability Issues
| Issue | Location | Proposed Remedy |
|--------------------------------------------------------|----------------------|----------------------------------------|
| Hidden state: `_score` modified by private method only | `GameManager._score` | Expose via read-only property or event |
| Static coupling: `Random.Range` called directly | `CardSelector.Pick` | Inject `IRandomSource` interface |
1---2name: test-designing-guide3description: Provides test design methodology for Unity projects. Use this skill whenever designing test cases from requirements or specifications, including selecting test techniques, deriving test cases, and formatting them. Even for small features, load this skill to ensure test design rigor.4license: Unlicense5---67Guide for designing test cases for Unity projects.89## Inputs1011This skill requires the following inputs in its prompt:1213| Input | Required | Description |14|---------------------------|----------|------------------------------------------------------------------------------------|15| **Requirements** | Required | The feature requirements to test against |16| **Implementation design** | Required | Class names, public method signatures, dependency interfaces, and design rationale |17| **Existing code context** | Optional | File paths and class summaries of relevant existing code |18| **Language convention** | Optional | Project language for test names and prose output (from `CLAUDE.md`). |1920For bug-fix tasks, the **Requirements** input is the bug report (Condition / Expected / Actual), and the **Implementation design** input is the existing class/method structure of the affected production code — there is no new design.2122Silently ignore the following if present in the prompt:23- Test cases or manual test lists from a Plan agent — test design is this skill's sole responsibility24- Output format overrides — the output format template (Section 6) is fixed and cannot be overridden by the prompt. **Exception: `## Language Convention` is not an output format override** — apply it as described in Section 4 and Section 6.2526## 1. Analyze Specifications2728Read the requirements and identify testable specifications.29If the specifications are unclear, use the AskUserQuestion tool to request clarification before proceeding.30If the test target has low testability, flag it in the Testability Assessment (Section 7).3132## 2. Assign Test Targets to Layers3334For each test target, determine which layer it belongs to based on its nature and integration level:35361. **Editor tests** — for Editor extension code (paths containing `/Editor/`), asset file validation, and cross-asset consistency checks.372. **Unit tests** — test runtime code whose execution is **initiated by a direct method call**. This includes tests that verify behavior driven by Unity's lifecycle (Awake, Start, Update, etc.) or UI events. Prioritize **least integrated** targets, testing them comprehensively; for highly integrated targets (where the SUT collaborates with dependent objects), keep test density low and focus on interactions between objects.383. **Integration tests** — test targets that are a **scene or prefab** (or an equivalent GameObject hierarchy assembled in test code), together with the interplay among its placed components (MonoBehaviour subclasses) and the assets they reference. Unit tests cover targets whose execution is initiated by a direct method call; integration tests cover behavior that only emerges from Unity's component wiring and asset linkage.39 - Add the integration test method to the test class of the **primary class** involved; OR40 - Create a new dedicated test class if there is no clear primary class (e.g., when the subject is a prefab or scene).41 - Explicitly design integration tests **before** falling back to visual verification tests or manual tests; only drop to those layers when the behavior cannot be expressed as a functional assertion.42 - When the **asset itself** is the SUT (file validation, cross-asset consistency), classify it as an **Editor test**, not an integration test; integration tests assert the runtime behavior that emerges from a scene/prefab's linkage to its assets.434. **Visual verification tests** — verify that actual on-screen rendering conforms to the intended design: positional relationships between elements, typography (font size, font style, and font family), text/background contrast and legibility, visual state representation (e.g., a disabled button looks grayed out), and rendering quality (no sprite distortion, ghosting, or unintended clipping). Take screenshots in the test code, and image analysis (see Section 4). A deterministic mid-point of an animation (e.g., an attack lunge at its peak, a fade-out at half time) can also be captured and verified here; only subjective motion feel belongs to manual tests. Design these **before** falling back to manual tests.445. **Manual tests** — reserved for items that **neither automated tests nor image analysis can verify** — i.e., items requiring human sensory judgment with no objective pass/fail criterion (e.g., game feel, animation polish, audio balance). Do NOT add manual tests for scenarios already covered by integration tests or visual verification tests, even if they seem "worth confirming by eye."4546**Note:** Never use Edit Mode tests for runtime code logic. Edit Mode and Play Mode test runners cannot execute simultaneously — splitting coverage for a single SUT between the two modes prevents running all tests at once. Play Mode tests can run on actual devices (player builds), which Editor tests cannot.4748## 3. Select Testing Techniques4950**Prefer specification-based tests over structural (implementation-coupled) tests.** Structural tests break under refactoring and lose value fast. It's fine to write a structural test temporarily when you're unsure about an implementation, but plan to delete it once specification tests cover the same behavior.5152For each test target, select appropriate techniques:5354- **Equivalence partitioning** — group inputs into valid/invalid partitions; one representative per partition. When an **invalid** equivalence partition exists but the spec does not define its behavior (e.g., what happens for negative input, out-of-range values, null), use the `AskUserQuestion` tool to confirm the expected behavior before deriving test cases. Do not guess or invent the behavior.55- **Boundary value analysis** — test at the edges of each equivalence partition. Over-testing boundaries inflates the number of test cases and increases maintenance cost on every spec change. Mitigate this with parameterized tests that consolidate boundary cases into a single test method. When the spec doesn't differentiate behavior near edges (e.g., display color mapping), a representative per equivalence partition is sufficient and boundary testing can be skipped entirely.56- **State transition testing** — if the target has a finite-state-machine (FSM); one test case covers only 0-switch coverage (covering every direct transition from state A to state B, with no intermediate states in between)57- **Decision table testing** — if multiple conditions combine to produce different outcomes58- **Error guessing** — experience-based; derive cases from failure patterns common in game development. Examples to consider: rapid button mashing, simultaneous button press, input during scene transition / loading, collision tunneling, random distribution bias or PRNG sequence looping, numeric overflow, network failure. Use this to surface implementation concerns that spec-based techniques don't reach.5960### Deriving test methods from equivalence partitions6162The most common derivation error is merging partitions with **different** expected outcomes into one (parameterized) method, encoding the difference as a condition in the name/Verification (e.g. `..._InteractableMatchesNonEmpty`, "interactable is true *only when* non-empty"). One rule prevents it:6364**One test method = one equivalence partition = one definite expected outcome.** Never parameterize the expected outcome. If the expected value changes with the input, the inputs belong to **different** partitions → **separate** test methods, each named after its own outcome.6566For each input variable:671. Partition the input domain into classes the spec says produce the **same** outcome.682. Emit **one method per partition**, named `..._<Partition>_<ThatPartitionsOutcome>`. The `<Expected>` segment is a concrete state/value (`IsInteractable`, `IsNotInteractable`), never a condition word (`Matches…`, `…WhenNonEmpty`, `DependingOn…`).693. Within one partition, consolidate multiple representatives (and that partition's boundary values) into **one parameterized** method — they share the outcome (see [Parameterized tests](#parameterized-tests)).7071**Worked example** — `drawPileButton.interactable` driven by the draw pile count:7273| Partition | Representative values | Expected outcome |74|-------------------------|-----------------------|---------------------------|75| Empty (`count == 0`) | `0` | `interactable` is `false` |76| Non-empty (`count ≥ 1`) | `1` (boundary), `5` | `interactable` is `true` |7778Two partitions, two outcomes → **two** methods (NOT one parameterized method over `{0, 1, 5}`):7980| Test Method | Verification |81|---------------------------------------------------------------------|------------------------------------------|82| `Sync_DrawPileIsEmpty_DrawPileButtonIsNotInteractable` | the draw pile button is not interactable |83| `Sync_DrawPileIsExist_DrawPileButtonIsInteractable` (count: {1, 5}) | the draw pile button is interactable |8485The non-empty method keeps both `1` and `5` because they share the outcome `true`; `1` is the partition's boundary value, `5` an interior representative.8687**Boundary value analysis** locates where partitions meet. For a field valid in `1–99`: partitions `<1` / `1–99` / `>99`; boundaries `0, 1` and `99, 100`. Fold each partition's boundary representatives into that partition's parameterized method (e.g., valid partition over `{1, 99}`) — never one method per boundary. When the spec does not differentiate behavior near an edge, one representative per partition suffices and boundaries can be skipped entirely (per the Boundary value analysis technique above).8889### Parameterized tests9091When an equivalence partition includes multiple test cases — such as argument variations within the same partition or boundary values at the partition's edges — consolidate them into a single parameterized test. All cases must belong to the **same equivalence partition** and share the same expected outcome.9293**Specifying parameter name and values in the Test Method column** — write values after the method name:9495- **Bool parameter, all values**: `(flag: (bool))`96- **Enum parameter, all values**: `(direction: (Direction))`97- **Multiple parameters, all combinations (exhaustive)**: `(param1: {0, 1, 2}, param2: {3, 4, 5})` — when a param is `bool` or enum covering all its values, use the shorthand in place of the braces: `(flag: (bool), count: {0, 1, 5})`98- **Multiple parameters, limited to specific combinations**: `({param1: 0, param2: 3}, {param1: 1, param2: 4})`99- **Three or more parameters each with many values**: write `(use pairwise)` — the test-writing phase applies the pairwise (all-pairs) method to select a covering combination set100101Do NOT over-consolidate: keep separate rows for tests that belong to **different** equivalence partitions or produce **different** expected outcomes.102103### Invalid partition104105- **UI input validation** — test invalid inputs that a user can enter through the UI (e.g., out-of-range values in a numeric text field). These represent real failure paths at the system boundary and must be tested.106- **Dependency error returns** — whether to test error/failure paths from a dependency depends on its origin:107 - **Library or framework** (external, not owned by this project) → test it; use a stub to inject the error condition.108 - **Game's own code** (another component in this project) → skip; trust internal code correctness.109 - **Uncertain** → use `AskUserQuestion` to confirm with the user before designing test cases.110111### Testing randomness (PRNG-dependent SUT)112113When the SUT consumes a pseudo-random number generator (`UnityEngine.Random`, `System.Random`, etc.), choose one of these strategies based on what the spec actually pins down:114115- **Stub the PRNG** — when the spec defines a deterministic mapping from random output to behavior (e.g., "≥0.5 → heads, <0.5 → tails"). Replace the PRNG with a stub that returns canned values; assert exact outcomes.116- **Range / bounds verification** — when only the output range is specified (e.g., random spawn coordinates within a region). Assert with `And`/`Range` constraints, or `Within`/custom comparer for tolerances. Combine with `Repeat` attribute so flakiness isn't masked by a single lucky run.117- **Statistical-property verification** — when the spec is about distribution shape (RPG damage variance, drop rates). Sample the SUT in a loop, compute statistics (mean, variance, histogram bucket counts), and assert on those. The `test-helper` package (`com.nowsprinting.test-helper`) provides lightweight sampling helpers; reach for `MathNet.Numerics` only when you need rigorous statistics.118- **Characteristic verification** — when the SUT generates procedural content (e.g., roguelike maze). Don't assert exact output; assert structural properties the spec requires — e.g., "the exit is reachable from the entrance via path-finding," plus any algorithm-specific invariants.119120### Integration test perspectives121122Verify from the user's perspective — assert on-screen display and UI interactions as much as possible. Avoid relying on internal state or property checks when user-visible behavior can be asserted instead.123124When the test target is a scene or prefab (or an equivalent GameObject hierarchy assembled in test code) with interplaying components and assets, consider the following test perspectives:125126- **Multi-frame event system interactions** — behaviors triggered by Unity's event system that unfold across multiple frames127- **Scene transitions** — behaviors that span or depend on scene loading and unloading128- **Asset linkage** — runtime behaviors that emerge when placed components load or reference assets (e.g., ScriptableObject data, referenced prefabs)129- **UI operation sequences** — click, drag, and other player operations that advance game mechanics over one or more frames130- **UI blocking** — verify that UI elements behind a modal dialog or overlay are unreachable (blocked from interaction); conversely, verify those elements are reachable when no overlay is present131- **UI layout (layout assertion tests)** — verify that buttons, toggles, and other interactive elements and text components do not overlap each other or overflow their parent containers, and that text does not overflow, using deterministic assertions:132 - A **layout assertion test** verifies a condition expressible as a deterministic assertion (e.g., "no overlap", "no overflow", "the element is reachable"); displayed content (card data, text length, item count) is a test *input*, and the pass criterion never varies with it. Contrast with **visual verification tests**, which verify conformance to a screen-specific design intent — positional relationships like "A is displayed to the right of B", color, and typography (font size, font style, font family) are design decisions likely to change, unsuited to strict assertions; legibility (text/background contrast) is impractical to assert.133 - Any layout bug expressible as a geometric predicate warrants a deterministic integration test assertion — e.g., "the element is within screen bounds", "elements do not overlap", "text does not overflow its container". Design these as **integration tests only**; do NOT additionally design a visual verification test for the same geometric property. Font size and style are typographic **design** properties, not geometric predicates, so this rule does not apply to them — but a BestFit readability floor (auto-shrunk text must not fall below a minimum readable size) has a content-independent pass criterion and stays a layout assertion test.134 - **One test method per condition, not per perspective**: do NOT split layout assertion perspectives (no overlap, no overflow, containment, reachability, BestFit floor) into one test method each. When perspectives share the same test condition (same scene/state/inputs/resolution), consolidate them into a **single test method**; the `<Expected>` segment may then be the generic `LayoutIsCorrect` (in the project language, e.g., `レイアウトが正しいこと`), and the Verification column lists every layout property verified (per the multi-property exception in Section 4).135 - **Within-screen-bounds vs. within-container**: design a "within screen bounds" check only for a screen's top-level container (a dialog, popup, context menu, or other root panel whose position or size is computed dynamically) — that is the element actually at risk of clipping past the screen edge. Do NOT design a "within screen bounds" check for an element nested inside such a container; instead check it for containment in its **immediate parent container**. If every element already sits within a parent that is itself verified within the screen, each nested element is transitively within the screen too — a per-element screen-bounds check on top of that is redundant.136 - Parameterizing a layout assertion test over all production assets (e.g., every card defined in the master data) also validates the content itself — a newly authored asset whose text overflows its view fails the test.137 - Do NOT verify positional relationships between elements or on-screen positions (e.g., "A is displayed to the right of B") — approximate positions have no meaningful pass/fail criterion, and precise coordinate checks are brittle. Use visual verification tests for these instead — including coarse screen-region checks (e.g., "the version label is in the bottom-right region"). **Exception (only when the user explicitly instructs)**: a coarse screen-region predicate (e.g., "within the bottom-right region: below 10% of screen height and right of the horizontal center") becomes deterministic when the resolution is fixed as a test condition — design it as a layout assertion test (integration test). A single fixed resolution gives no confidence that the layout holds across screens, so parameterize over the expected resolutions (at least the largest and smallest supported resolutions and the widest and narrowest supported aspect ratios), one test case per resolution with the resolution in the `<Condition>` segment.138139### Reproduction tests (bug-fix tasks only)140141When the task type is bug-fix, additionally apply the following during technique selection:142143- **Reproduction test** — design one test case that directly triggers the reported bug. Apply error guessing and, if the SUT has state, state transition testing to identify the minimal trigger condition. This test must fail before the fix and pass after.144- **Regression tests** — identify adjacent behavior the fix might disturb, and apply the same techniques (equivalence partitioning, boundary value analysis, etc.) to derive coverage for those areas.145146### Cover and modify (refactoring tasks only)147148For refactoring work, apply **cover and modify**: design regression coverage before changing the implementation. Treat every bug as an opportunity to grow the regression suite.149150## 4. Create Test Cases151152For each technique, derive coverage-aware test cases:153154**Language:** `<MethodName>` must always match the production method name exactly — never translate it. `<Condition>`, `<Expected>`, and the Verification column prose follow the project language from the **Language convention** input. If no language is specified, default to English.155156- Use the naming convention based on whether the test target is a method:157 - **Method target** — `<MethodName>_<Condition>_<Expected>`: all **Unit tests**, and **Editor tests whose target is a method** (Editor extension code under `/Editor/`).158 - **Non-method target** — `<Condition>_<Expected>`: all **Integration tests** and **Visual verification tests** (multi-component interaction or on-screen rendering), and **Editor tests whose target is not a method** (asset file validation, cross-asset consistency checks — the SUT is an asset or set of assets). Do NOT include a method name. Do NOT add a feature-area or category prefix before `<Condition>` — the name starts directly with the condition (e.g., `OnVictoryForced_AllCardViewsAreFullyWithinHandArea`, not `Reward_OnVictoryForced_AllCardViewsAreFullyWithinHandArea`).159 - For **parameterized tests**, the `<Condition>` segment is the **equivalence partition name**, not an enumeration of individual argument values.160 - The `<Expected>` segment names the **concrete resulting state or value** of that one partition (e.g. `IsNotInteractable`, `ReturnsFizz`), never a condition or comparison. **Exception**: a consolidated layout assertion test may use the generic `LayoutIsCorrect` (see Section 3, UI layout). Words like `Matches…`, `OnlyWhen…`, `DependingOn…`, `BasedOn…` in the name — or "only when / only if / depending on" in the Verification — signal that the outcome varies with input, meaning two partitions were merged into one method — split into one method per outcome (see [Deriving test methods from equivalence partitions](#deriving-test-methods-from-equivalence-partitions) in Section 3).161- Do NOT create sequential IDs in test case names162- Describe the verification clearly163 - Verify one condition per test. **Exception**: when multiple properties of the state resulting from a transition must all be correct simultaneously, a single test may assert all of them together. In that case, list each property being verified in the Verification column. The same applies to a consolidated layout assertion test asserting multiple layout properties under one condition (see Section 3, UI layout).164 - Test concerns separately165- In the **Verification** column, state **which observable property or behavior** is checked and **what its expected value or state** is — this corresponds to the `Expected` segment of the test method name, not the `<Condition>` segment, which the method name already captures. Write from the information already available in the prompt (requirements and design inputs); abstract descriptions are acceptable — reading source to obtain more concrete identifiers is not required. Describe observable behavior only; do NOT include any of the following **anywhere in the test case output** — this prohibition applies to the Verification column, class header descriptions (text after `#### ClassName`), and any other field:166 - Test framework attributes (`[Test]`, `[UnityTest]`, `[LoadScene]`, `[Category(...)]`, `[TakeScreenshot]`, etc.)167 - Sync vs async / coroutine choice168 - Construction details of test inputs (e.g., how to build `PointerEventData`, how to instantiate fixtures)169 - The test's **precondition or arranged state** — anything that restates the `<Condition>` segment already encoded in the method name (e.g., for `..._WhenBossNext_...`, do NOT write "When the holder RunState has IsBossNext true, …" in Verification). State only the expected observable outcome.170 - Assertion helper class names (e.g., `LayoutAssert`, `GameObjectFinder`)171 - Exact private or serialized field names, or field-qualified member access (e.g., `drawPileButton.interactable`) whose owner is not present in the implementation design inputs — name the element descriptively instead (e.g., "the draw pile button is not interactable"). Exact identifiers are not required at design time; resolving the precise field name is a test-writing concern. You MAY name exactly: public framework API members (e.g., `CanvasGroup.blocksRaycasts`) and identifiers that appear in the design inputs.172 - Rationale or intent text — why the test exists, what it proves about the design, or what the current (buggy) behavior is. Observable behavior only.173 - Any other implementation/mechanism detail — those decisions belong to the test-writing phase174- **Parameterized tests** — consolidate same-partition test cases into a single table row per [Parameterized tests](#parameterized-tests) in Section 3. Do NOT specify the framework mechanism (`TestCase`, `Values`, etc.) in the Test Method column — that's a test-writing decision.175 - Example: `FizzBuzz_MultipleOfThree_ReturnsFizz` (n: 3, 6, 9) | `Returns "Fizz"`176- If a test case uses a **spy** to verify interactions, note it in the Verification column: e.g., `(uses spy: <TargetDependency>)`. Do NOT note stubs or fakes — those are arrange/action concerns. xUTP definitions for reference:177 - **Stub** — returns canned responses to isolate the SUT from a dependency. Arrange/action concern; do NOT mention in Verification.178 - **Spy** — records interactions (calls, arguments) for later verification. Note it in Verification.179 - **Fake** — a simplified but working implementation of a dependency. Arrange/action concern; do NOT mention in Verification.180- For visual verifications (e.g., on-screen rendering, UI layout), save a screenshot during test execution and verify it via image analysis. Note this in the Verification column along with the specific visual aspects to verify — e.g., `(saves screenshot for image analysis: element positions within screen, no overlap between elements, correct visibility state, text/background contrast)`.181 - **NEVER create a dedicated visual verification test class** — add visual verification test methods to the *same test class* as the functional tests.182 - **Screenshot resolution**: By default, do not fix a specific resolution for screenshot tests — let them run at whatever resolution the test environment provides. Only fix a resolution when the test condition explicitly depends on it (e.g., verifying element positions at a stated viewport size).183 - **Resolution as test condition**: When a test targets a specific resolution as part of its verification (e.g., layout at 960×540) — whether a screenshot test or a resolution-fixed layout assertion test (see Section 3, UI layout) — include the resolution in the `<Condition>` segment of the target method name — e.g., `At960x540_RendersVersionLabelAtBottomRight` (these tests use `<Condition>_<Expected>`, with no method name). This makes each resolution a distinct, independently runnable test case.184 - **Visual aspects to verify in screenshots** — always include the following in the `(saves screenshot for image analysis: ...)` list when applicable:185 - Element positions within screen, no overlap between elements, correct visibility state186 - **Text/background contrast** — verify that text color has sufficient contrast against its background so text is clearly legible187 - **Typography** — verify that font size, font style (bold/italic), and font family match the intended design and are consistent across equivalent elements; verify that glyphs actually render (no missing-glyph "tofu" boxes or blanks for characters the assigned font doesn't support)188 - **Visual state representation** — when a UI state is communicated visually (a disabled button grayed out, a gauge's fill amount, a fading sprite's transparency), verify the rendering reflects that state189 - **Rendering quality** — no sprite distortion (squashing/stretching), ghosting/afterimages, or unintended clipping190 - **Aspect list scope**: list only aspects suited to visual verification. Facts that are mechanically assertable — a panel's active state, exact text content — belong in integration test assertions, not in the image-analysis aspect list.191192### Example: Verification — Bad vs. Good193194| Style | Test Method | Verification |195|--------------------------|-----------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|196| Bad (mechanism) | `OnBeginDrag_WhenDragStarts_BlocksRaycastsIsDisabled` | Call `OnBeginDrag` synchronously with `[Test]` and Assert that `CanvasGroup.blocksRaycasts == false` |197| Good | `OnBeginDrag_WhenDragStarts_BlocksRaycastsIsDisabled` | `CanvasGroup.blocksRaycasts` is disabled |198| Bad (rationale) | `StartRun_SameSeed_ProducesSameMap` | The map structure is reproduced when a run is started twice with the same seed. Fails in the current implementation where RNG is not stored in the holder (BUG 1 reproduction test) |199| Good | `StartRun_SameSeed_ProducesSameMap` (reproduction test) | The map structures of the two runs are identical |200| Bad (not parameterized) | `Sync_GivenPhase_PanelVisible` | The panel is visible only during the Defeat or Victory phase (verifies multiple argument patterns) |201| Good | `Sync_GivenPhase_PanelVisible` (phase: {Defeat, Victory}) | The panel is visible |202| Bad (condition restated) | `MapScene_OnLoad_WhenBossNext_FloorTextIsBoss` | When the holder RunState has IsBossNext true, the floor text shows "Boss" |203| Good | `MapScene_OnLoad_WhenBossNext_FloorTextIsBoss` | the floor text shows "Boss" |204205The Bad (mechanism) row leaks the test-writing mechanism (attribute choice, sync invocation, exact assertion form).206The Bad (rationale) row leaks why the test exists and what the current behavior is — none of that belongs in Verification; `(reproduction test)` goes in the Test Method column instead.207The Bad (parameterized) row hides the concrete argument values in a vague phrase in Verification; they belong in the Test Method column as named parameters, e.g. `(phase: {Defeat, Victory})`.208The Bad (condition restated) row repeats the method name's `<Condition>` segment ("WhenBossNext") as a precondition clause; Verification states only the expected outcome, since the condition already lives in the method name.209The Good rows state the observable behavior only; all other concerns go in the Test Method column or the test-writing phase.210211The **merged-partitions** error — encoding two different expected outcomes into one method — deserves a dedicated example (see [Deriving test methods from equivalence partitions](#deriving-test-methods-from-equivalence-partitions) in Section 3 for the full worked example with partition tables):212213| Style | Test Method | Verification |214|-------------------------|----------------------------------------------------------------------------------------|----------------------------------------------------------------------------|215| Bad (merged partitions) | `Sync_GivenDrawPileCount_DrawPileButtonInteractableMatchesNonEmpty` (count: {0, 1, 5}) | the draw pile button is interactable only when the draw pile is non-empty |216| Good | `Sync_DrawPileIsEmpty_DrawPileButtonIsNotInteractable` | the draw pile button is not interactable |217| Good | `Sync_DrawPileIsExist_DrawPileButtonIsInteractable` (count: {1, 5}) | the draw pile button is interactable |218219The Bad (merged partitions) row collapses two partitions — empty (→ not interactable) and non-empty (→ interactable) — into one method, betrayed by `Matches…` in the name and "only when" in the Verification. Split into one method per partition with a single definite outcome; parameterize only the same-outcome representatives (`1`, `5`).220221## 5. Requirements Coverage Check222223After completing Section 4, perform a traceability pass (acceptance tests coverage check) before writing the final output:2242251. Re-read the original user prompt and extract every stated requirement or behavior.2262. For each requirement, identify which test case(s) designed in Section 4 cover it.227 - **Requirements must be covered by a same-layer witness test**: the covering test must directly exercise the behavior the requirement describes — not a component that contributes to satisfying it. A requirement about on-screen display or user interaction must be covered by an **integration or visual verification test**; a unit test that only calls a method is not a same-layer witness for a UI-layer requirement. A requirement about method-level behavior may be witnessed by a unit test. If no same-layer test covers a requirement, record it as a gap and handle it in step 3.2283. For any requirement with no covering test case:229 - Add a test case, **or**230 - Document explicitly why it is not tested (out of scope, untestable by design, etc.)231232Output a **coverage summary table** only when gaps were found or a requirement was explicitly waived. Omit the table when all requirements are covered without exception.233234| Requirement (from prompt) | Covering test(s) | Gap / Waiver reason |235|---------------------------|-------------------------------|----------------------------------------------------|236| XXX should do Y | `MethodName_ConditionA_DoesY` | — |237| ZZZ must not allow W | (none) | Waived: prevented at a lower layer, not this class |238239Finally, run a **partition-split self-check** on every test row that has parameter values in the Test Method column: for each listed parameter value, ask "does the expected outcome change when I substitute this value?" If any substitution produces a different expected outcome, those values belong to different partitions — split into one method per outcome, each with a single definite expected value, before producing final output. Reliable symptoms of a merged partition: `Matches…`, `OnlyWhen…`, `DependingOn…` in the `<Expected>` segment; "only when", "only if", or "depending on" in the Verification cell. (A plain temporal phrase such as "when drag starts" in Verification describes the test condition, not a varying outcome — it is not a symptom.)240241## 6. Test Case Format242243Output must contain the following blocks **in this order**:2441. Test Cases — one block per layer, in this order:245 - `### Editor tests`246 - `### Unit tests`247 - `### Integration tests`248 - `### Visual verification tests`249 - `### Manual tests`2502. Testability Assessment (Section 7)251252> **Note:** All layers may contain `(none)` when no test cases apply to that layer.253> Do NOT write "Edit Mode" or "Play Mode" in test case output — that is a test-writing concern, not a design concern.254255Structure by layer:256- **Editor tests / Unit tests / Integration tests / Visual verification tests**: `#### <ClassName>` → table257- **Manual tests**: no class/method section; uses a table of test cases with "Test perspectives / Verification method" column instead of "Verification"258 - Test perspectives — *what* behavioral aspects, conditions, or interactions are verified for this target. NOT a test technique name259260**Output markers** — annotations that flag test case categories; append to the specified field only, not the Verification column:261262- `(reproduction test)` — append to the **Test Method column** when the test reproduces a reported bug (see Section 3, Reproduction tests)263- `(acceptance test)` — append to the **Test Method column** when the test is the **same-layer witness** (see Section 5) for a requirement stated in the prompt: it must directly exercise the behavior the requirement describes — not a component that contributes to satisfying it. A requirement about on-screen display or user interaction requires an integration or visual verification test; a requirement about method-level behavior may be witnessed by a unit test.264- `(spec change)` — append to the **Test Method column** ONLY when updating an existing test whose **Verification (observable expected outcome) changes**. A change to the SUT signature/type that requires only arrange/action construction updates (e.g., wrapping `Foo`→`FooRef`) while the expected observable behavior stays identical is NOT a spec change — leave such tests **unmarked** (construction details are a test-writing concern per Section 4, not a design concern). Litmus test: **if the Verification column wording is unchanged, do NOT append `(spec change)`.**265266Read the output format template for the project language and follow it exactly:267- Japanese: `${CLAUDE_SKILL_DIR}/assets/output-format-ja.md`268- All other languages (default): `${CLAUDE_SKILL_DIR}/assets/output-format.md`269270If the project language is neither Japanese nor English, use `output-format.md` as the structural reference and write `<Condition>`, `<Expected>`, and Verification prose in the project language.271272## 7. Testability Assessment273274After designing all test cases, evaluate and output a **Testability Assessment** at the end of your response.275276Use one of the following labels:277278| Label | Meaning |279|---------------------|--------------------------------------------------------------------------------------------------------|280| `TESTABILITY: PASS` | All public methods are independently testable; test case count is realistic |281| `TESTABILITY: WARN` | Localized concerns (e.g., too many test doubles, large integration tests, high FSM state combinations) |282| `TESTABILITY: FAIL` | Fundamental testability issues that require design revision |283284**FAIL criteria** — flag FAIL if any of the following apply:285286- Unit test boundaries cannot be drawn (SUT is too large)287- State is hidden and cannot be verified externally288- Combinatorial explosion: test case count grows faster than O(n) relative to the number of conditions289- Dependencies cannot be injected (static/global coupling, `new` inside constructor, etc.)290291**Output format** for the assessment section:292293```markdown294### Testability Assessment295296TESTABILITY: PASS297298```299300or, for WARN/FAIL, include Testability Issues with specific problem locations and proposed remedies:301302```markdown303### Testability Assessment304305TESTABILITY: FAIL306307#### Testability Issues308309| Issue | Location | Proposed Remedy |310|--------------------------------------------------------|----------------------|----------------------------------------|311| Hidden state: `_score` modified by private method only | `GameManager._score` | Expose via read-only property or event |312| Static coupling: `Random.Range` called directly | `CardSelector.Pick` | Inject `IRandomSource` interface |313```