skills/specops-contract-tests/SKILL.md
Generate framework-agnostic contract tests from a SpecOps analysis file. Use when: 'generate contract tests', 'spec-to-gate tests', 'create tests from analysis', 'contract tests for this analysis', 'test this spec', 'generate tests from specops'.
npx skillsauth add ryan-mahoney/ryan-llm-skills specops-contract-testsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Generate a framework-agnostic pytest test file from a SpecOps analysis file. The tests are derived from sections 2 (interfaces), 3 (data models), 4A (policy rules), 4B (behavioral scenarios), 6 (dependencies), 8 (error handling), and 10 (edge cases). The output is a single test file that can run against any implementation of the analyzed component.
If $ARGUMENTS is provided, treat it as the path to the analysis file.
If $ARGUMENTS is not provided, ask the user which analysis file to use.
analysis-file -- path to the analysis markdown file (e.g., docs/specops/analysis/topic-subscribe.md)# SpecOps Analysis: {target-name}. This becomes the test module name by replacing hyphens with underscores (e.g., topic-subscribe becomes test_topic_subscribe.py).POST, GET, PUT, DELETE, PATCH) with URL paths, an "HTTP Route" or "HTTP Surface" subsection, or status codes in the context of an endpoint.docs/specops/spec-to-gate.md exists in the project, read it for test infrastructure conventions (client factory pattern, mock configuration, fixture names). Adapt to those conventions.tests/contracts/conftest.py exists, read it to understand available fixtures. Do not duplicate fixtures already defined there.Read and extract from these sections:
Section 2 (Public Interfaces):
Section 3 (Data Models):
Section 4A (Decision Logic & Policy Surface):
Section 4B (Policy Tests & Behavioral Scenarios):
Section 6 (Dependencies):
datetime.now) when they affect determinism.Section 8 (Error Handling):
Section 10 (Edge Cases):
From Section 6 extraction, build the mock target list:
acm_server.py calls messaging.send_each, the mock path is firebase_admin.messaging.send_each.async_client_messaging_app.api.resources.connection_pool.get_azure_tables_client.Use monkeypatch.setattr for all mocks. Do not use @patch decorators -- monkeypatch keeps mock scope explicit and avoids import-order issues across framework migrations.
Organize the test file as:
Module docstring:
"""
Contract tests for {target name}.
Derived from: {analysis file path}
SpecOps target: {target name from header}
Sections used: 2 (Interfaces), 3 (Data Models), 4A (Policy), 4B (Scenarios), 8 (Errors), 10 (Edge Cases)
"""
Test classes grouped by scenario category:
| Class | Source | Purpose |
|-------|--------|---------|
| TestHappyPath | 4B happy-path scenarios | All inputs valid, all operations succeed |
| Test{RuleName} | 4A rules with testable boundaries | One class per significant rule (e.g., TestTokenExpiry, TestBatchSizeLimit) |
| TestValidation | 3 validation rules, 4B validation scenarios | Input validation rejects malformed requests |
| TestErrorPropagation | 8 failure modes, 4B error scenarios | Exception handling produces correct behavior |
| TestEdgeCases | 10 edge cases | Surprising or implicit behavior |
Not all classes are required. Only create classes that have test methods. If a category has no scenarios, omit it.
Test methods:
test_{what_happens}_when_{condition} or test_{condition}_{expected_outcome}. Keep names readable as behavioral descriptions.Write to tests/contracts/test_{target_name}.py. Create the tests/contracts/ directory if it does not exist.
For HTTP surface targets, each test method follows:
def test_scenario_description(self, client, mock_fixture):
"""Section 4B.N: Scenario title from analysis."""
# Arrange: configure mocks for this scenario
mock_fixture.return_value = ...
# Act: HTTP request
resp = client.post("/v1/path", json={...})
# Assert: status code and response body
assert resp.status_code == 207
body = resp.json()
assert body[0]["responseStatusCode"] == 200
For behavioral surface targets, each test method follows:
def test_scenario_description(self, mock_fixture):
"""Section 4B.N: Scenario title from analysis."""
# Arrange: configure mocks, instantiate target
mock_fixture.return_value = ...
target = TargetClass()
# Act: direct method call
result = target.method(arg1, arg2)
# Assert: return value and mock interactions
assert result == expected
mock_fixture.assert_called_once_with(...)
Fixture handling:
conftest.py exists and defines the needed fixtures, use them by name.conftest.py does not exist or lacks needed fixtures, define fixtures at the top of the test file with a comment noting they should be moved to conftest.py when shared across test files.mock_firebase fixture for all Firebase SDK methods, one mock_azure_tables for the table client).Mock return value realism:
TopicManagementResponse with .errors list, BatchResponse with .responses list).MagicMock with the required attributes set.After writing the file, verify and report:
Report the coverage summary to the user after writing the file.
specops-analysis skill.tests/contracts/ named test_{target_name}.py where target_name is the analysis file basename with hyphens replaced by underscores.Test prefix + scenario category in PascalCase.conftest.py for fixtures shared across multiple test files.monkeypatch.setattr for all mocks.'responseStatusCode', 'TOKEN MANAGEMENT ERROR'). Do not rename or abstract.documentation
This skill should be used when the user asks to "write a spec", "create a spec", "spec this out", "plan this feature", or "write an implementation plan" for a feature or change. Creates a structured implementation spec in .specs/<slug>/spec.md and mirrors it to GitHub only when the current repository is hosted on GitHub.
data-ai
This skill should be used when the user asks to "execute the spec", "run the plan", "implement the spec", "implement the issue", "run all steps", or "run spec". Implements all steps from .specs/<slug>/spec.md, using a subagent per step when the harness supports subagents.
testing
This skill should be used when the user asks to "review a spec", "review an issue", "check the plan", "review the implementation plan", "find gaps in the spec", or "review spec". Reviews .specs/<slug>/spec.md for gaps and viability, edits it when needed, and mirrors changes to GitHub only when a GitHub mirror exists.
development
This skill should be used when the user asks to "remediate the audit findings", "fix the spec violations", "close the audit findings", "fix conformance violations", or "spec remediate". Reads a spec-audit report, drives one smart subagent per VIOLATION to converge the code back to the frozen spec, and re-audits until clean. Edits production code; never rewrites the spec.