test-authoring
npx machina-cli add skill zircote/auto-harness/test-authoring --openclawMemory
Search first: /mnemonic:search {relevant_keywords}
Capture after: /mnemonic:capture {namespace} "{title}"
Run /mnemonic:list --namespaces to see available namespaces from loaded ontologies.
Test Authoring for Hook-Driven Frameworks
Write effective test definitions for the hook-driven automated test framework.
Mnemonic Integration
Before authoring tests, check mnemonic for test patterns:
# Search for test authoring memories
rg -i "test|expectation|contains|regex|depends_on" ~/.claude/mnemonic/ ./.claude/mnemonic/ --glob "*.memory.md" -l | head -5
# Check patterns namespace
rg -l "." ~/.claude/mnemonic/*/patterns/ --glob "*.memory.md" 2>/dev/null | xargs grep -l -i "test" 2>/dev/null | head -5
Apply recalled patterns:
- Effective expectation strategies
- Variable capture patterns that worked
- Test organization preferences
- Common ID naming conventions used
Test Definition Schema
Every test requires these fields:
| Field | Required | Type | Purpose |
|---|---|---|---|
id | Yes | string | Unique identifier (snake_case) |
description | Yes | string | Human-readable explanation |
action | Yes | string | Instruction for Claude to execute |
expect | Yes | array | Validation expectations |
category | No | string | Grouping for filtering |
save_as | No | string | Variable name to capture output |
depends_on | No | string | ID of prerequisite test |
tags | No | array | Labels for filtering |
Expectation Types
contains - Substring Match
Use for flexible text matching when exact format may vary.
expect:
- contains: "successfully"
- contains: "Memory created"
When to use:
- Success messages
- Partial output validation
- UI text that may have surrounding content
not_contains - Negative Match
Ensure unwanted content is absent.
expect:
- not_contains: "error"
- not_contains: "failed"
- not_contains: "undefined"
When to use:
- Error detection
- Ensuring deprecated patterns removed
- Security validation (no sensitive data exposed)
regex - Pattern Match
Use for structured data with predictable patterns.
expect:
- regex: "ID:\\s+([a-f0-9]{12})"
- regex: "Count:\\s+\\d+"
- regex: "(success|complete)"
When to use:
- ID extraction
- Numeric validation
- Multiple acceptable values
- Structured output parsing
Capture groups: Use () to capture values for save_as.
Variable Capture and Substitution
Capturing Values
Use save_as with a regex capture group:
- id: create_item
action: "Create a new item named 'test'"
expect:
- regex: "ID:\\s+([a-f0-9]+)"
save_as: item_id
The first capture group () value is stored in the variable.
Using Captured Values
Reference with ${variable_name}:
- id: retrieve_item
action: "Retrieve item ${item_id}"
depends_on: create_item
expect:
- contains: "test"
Dependency Chains
Build test sequences:
# Test 1: Create
- id: crud_create
action: "Create memory with content 'test data'"
expect:
- regex: "ID:\\s+(\\w+)"
save_as: memory_id
# Test 2: Read (depends on create)
- id: crud_read
action: "Retrieve memory ${memory_id}"
depends_on: crud_create
expect:
- contains: "test data"
# Test 3: Update (depends on read)
- id: crud_update
action: "Update memory ${memory_id} with content 'updated'"
depends_on: crud_read
expect:
- contains: "updated"
# Test 4: Delete (depends on update)
- id: crud_delete
action: "Delete memory ${memory_id}"
depends_on: crud_update
expect:
- contains: "deleted"
- not_contains: "error"
Writing Effective Actions
Be Specific
Good:
action: "Call subcog_capture with content: 'Test pattern', namespace: 'patterns'"
Avoid:
action: "Create a memory" # Too vague
Match Tool Names Exactly
For MCP tools, use the full tool name:
action: "Call mcp__plugin_subcog_subcog__subcog_capture with content: 'test'"
Include Required Parameters
action: "Call subcog_recall with query: 'authentication', limit: 5, mode: 'hybrid'"
Test Organization
Categories
Group tests by component or functionality:
| Category | Use For |
|---|---|
initialization | Setup and init tests |
crud | Create, read, update, delete |
search | Query and filter operations |
validation | Input validation tests |
error-handling | Error condition tests |
integration | Cross-component tests |
commands | Slash command tests |
skills | Skill trigger tests |
hooks | Hook behavior tests |
Tags
Use tags for filtering test runs:
| Tag | Meaning |
|---|---|
smoke | Quick sanity checks |
critical | Must-pass tests |
regression | Bug fix verification |
slow | Long-running tests |
flaky | Known intermittent failures |
ID Naming Convention
Pattern: category_component_action_variant
Examples:
init_basic- Basic initializationcrud_memory_create- Create memorysearch_semantic_empty- Semantic search with no resultscmd_review_with_args- Review command with arguments
Common Patterns
Smoke Test Pattern
Quick validation that component works:
- id: component_smoke
description: "Basic smoke test for component"
category: smoke
action: "Minimal invocation of component"
expect:
- not_contains: "error"
tags: [smoke, critical]
CRUD Test Pattern
Full lifecycle test:
- id: entity_create
action: "Create entity"
save_as: entity_id
tags: [crud]
- id: entity_read
action: "Read entity ${entity_id}"
depends_on: entity_create
- id: entity_update
action: "Update entity ${entity_id}"
depends_on: entity_read
- id: entity_delete
action: "Delete entity ${entity_id}"
depends_on: entity_update
Error Handling Pattern
Validate error responses:
- id: invalid_input_error
description: "Verify error on invalid input"
action: "Call tool with invalid_param: 'not-valid'"
expect:
- contains: "error"
- regex: "(invalid|not found|failed)"
tags: [error-handling]
Search Results Pattern
Validate search functionality:
- id: search_with_results
action: "Search for 'known term'"
expect:
- contains: "results"
- regex: "found\\s+\\d+"
- not_contains: "no results"
Additional Resources
Reference Files
For detailed patterns and advanced techniques:
references/expectation-patterns.md- Regex patterns for common outputs
Source
git clone https://github.com/zircote/auto-harness/blob/main/skills/test-authoring/SKILL.mdView on GitHub Overview
This skill guides you to write structured test definitions for a hook-driven automated framework. It covers mandatory fields such as id, description, action, and expect, how to express validation with contains, not_contains, and regex, and how to capture values for reuse and chain tests with depends_on.
How This Skill Works
Tests are defined as records with fields such as id, description, action, expect, and optional save_as depends_on and tags. Expectation types drive validation contains not_contains and regex, with regex supporting capture groups saved as save_as. Captured variables are referenced later as ${variable}, enabling dependency chains like create, read, and update.
When to Use It
- When you need to write a new test case or add coverage for a hook driven workflow
- When you must decide between contains vs regex for output validation
- When you want to chain multiple dependent tests such as create read update
- When you are defining the test schema and mandatory fields like id description action and expect
- When organizing tests with tags categories and reusable patterns for consistency
Quick Start
- Step 1: Define a test with id description action and expect
- Step 2: Pick an expectation type (contains not_contains or regex) and add save_as if capturing
- Step 3: Build dependency chains with depends_on to link tests
Best Practices
- Define mandatory fields first: id, description, action, expect
- Choose the right expectation type for robust validation (contains not_contains regex)
- Use regex capture groups to save values with save_as for later steps
- Keep dependency chains clear with depends_on and stable ids
- Write readable deterministic tests with focused actions and descriptive descriptions
Example Use Cases
- crud_create: Create memory with content test data and capture the ID as memory_id using a regex
- crud_read: Retrieve memory using ${memory_id} and verify it contains test data
- crud_update: Update memory ${memory_id} with updated content and verify
- create_item: Create an item and capture its ID as item_id for later steps
- dependency chain: crud_create -> crud_read -> crud_update to demonstrate chaining