| name | ut-analyst |
| description | Analyze a class or function and produce a structured JSON test plan. Classifies all dependencies (interface, abstract, valueObject, dto, primitive), detects non-deterministic calls, enumerates test cases using black-box techniques (Equivalence Partitioning, Boundary Value Analysis, Decision Table, State Transition), and lists constructor null-guard requirements. Use when asked to analyze a class for testing, create a test plan, classify dependencies, or produce test case inventory. Also invoked as Phase 1 by the unit-test-generator agent. |
| argument-hint | class name or attach source file |
Unit Test Analyst
Analyze the source structure, classify all dependencies, detect non-determinism, and produce a structured JSON test plan. This is Phase 1 of the unit test generation pipeline.
Standalone vs. orchestrated — This skill can run independently to produce a test plan for human review or downstream use, or it can be invoked as Phase 1 by the unit-test-generator agent, which passes the output to the Architect (Phase 2).
Prerequisites: Class Context Check
Before analyzing, verify that you have a target class, function, or component. You need one of these:
- The user specified a name (e.g., "analyze
MyService")
- A source file is open in the editor or attached to the conversation
- The user referenced a class or function in the conversation history
If none of these are true, respond with:
Please specify the class or function you want to analyze. You can either:
- Provide the name (e.g., "analyze
MyService")
- Open the source file in the editor
- Attach the source file to the conversation
Do not produce a test plan without a concrete target.
Preparation
- Read the source file — understand all public methods, constructors, properties, dependencies (constructor-injected interfaces or function parameters), and edge cases
- Detect the programming language — use the file extension or explicit user context:
.cs → C# | .java → Java | .py → Python | .ts / .tsx → TypeScript
- If the language is ambiguous, ask the user before proceeding
- Read
references/project-patterns.md — note the project's frameworks, assertion style, and null-exception conventions. This context informs accurate exception type classification (e.g., ArgumentNullException vs NullPointerException vs TypeError)
Analyst Actions
-
Identify all constructor parameters and classify each as:
interface — declared as an interface type
abstract — declared as an abstract class
valueObject — immutable type with value semantics (e.g., Money, Address, Email)
dto — data transfer object / request / response class
primitive — value type or string
-
Detect non-deterministic calls — scan every method for calls that produce different results on each execution (see table below)
-
For each public method, enumerate test cases applying black-box techniques (see sections below), including boundary values
-
For each constructor parameter classified as interface or abstract, add a constructorNullGuards entry specifying the expected exception type
Rule: Classify Before Mocking
Classify every dependency before any mock strategy is assigned. Never infer mock strategy from the type name alone — classification drives strategy. This constraint exists so the Architect phase has accurate, consistent input.
Black-Box Test Design Techniques
Apply these techniques systematically to every public method or exported function:
Equivalence Partitioning
Divide input domains into groups that should behave the same way. Write at least one test per partition. Typical partitions include: valid inputs, invalid inputs, boundary-adjacent values, and special values (null, empty, zero, negative).
Boundary Value Analysis
Test at the exact boundaries of input domains. For a range [min, max], test: min-1, min, min+1, max-1, max, max+1. For strings: empty string, single char, very long string. For collections: empty, single item, many items.
Decision Table Testing
When a method's behavior depends on combinations of conditions, enumerate the meaningful combinations. Each unique combination of inputs that produces a distinct outcome gets its own test case. Use the language's parameterized test feature to keep these compact.
State Transition Testing
When the class has internal state that affects behavior (e.g., initialization state, connection status, mode flags), test:
- Each valid state transition
- Invalid transitions (calling methods in wrong order/state)
- The behavior of the same method in different states
Not every technique applies to every method — use judgment. A simple utility method might only need Equivalence Partitioning and Boundary Value Analysis. A stateful service might need all four.
Test Case Coverage Requirements
For each public method or exported function, cover all three categories:
Happy Path
- Typical valid inputs that produce the expected successful outcome
- Cover the most common use cases a real caller would exercise
Edge Cases
null / None / undefined inputs
- Empty string, empty collection, empty object
- Whitespace-only strings
- Zero, negative numbers, very large numbers,
NaN, Infinity
- Default / zero-value objects
- Single-element collections
- Very long strings or collections (near limits)
Error Cases
- Invalid input values (wrong type, out of range, malformed)
- Missing required dependencies or resource not found
- Expected exceptions — verify the exception type, message, and parameter name where applicable
- Async methods must test both resolved and rejected/thrown paths
Non-Deterministic Call Detection
Scan the source for calls that produce different results on each execution:
| Category | C# | Java | Python | TypeScript |
|---|
| Current time | DateTime.Now, DateTime.UtcNow, DateTimeOffset.Now | LocalDateTime.now(), Instant.now(), System.currentTimeMillis() | datetime.now(), datetime.utcnow() | Date.now(), new Date() |
| Random IDs | Guid.NewGuid() | UUID.randomUUID() | uuid4(), uuid.uuid4() | crypto.randomUUID(), uuidv4() |
| Random numbers | new Random(), Random.Shared | new Random(), Math.random() | random.random(), random.randint() | Math.random() |
When a non-deterministic call is detected:
- Warn — include a
nonDeterministicCalls entry in the JSON plan with the location and call type, plus a stability warning
- Suggest abstraction — provide the interface definition and a concrete real implementation the user can add to their source
⚠️ This skill does not modify source files automatically. Abstractions are shown as suggestions only.
Output
Emit the complete JSON test plan following the schema in references/analyst-test-plan-schema.md.
If running standalone (not skipReview: true): After emitting the JSON, stop and ask:
"Analyst phase complete. Review the test plan above. Reply 'continue' to proceed to the Architect phase, or provide feedback to adjust the plan."
If skipReview: true (passed by user or orchestrator): Emit the JSON and continue without pausing.
What NOT to Do
- Don't make complex mock strategy decisions — the Analyst pre-populates
mockStrategy using the deterministic classification rule only (interface/abstract → mock; others → real). Strategic decisions such as non-determinism abstractions or mock overrides are the Architect's responsibility
- Don't generate any test code — that is the Coder's responsibility
- Don't define assertion style or test file location — that is the Architect's responsibility
- Don't force all four design techniques onto every method — a simple pure function may only need EP and BVA
- Don't skip constructor null-guard entries for any
interface or abstract constructor parameter