Borrowing it
Nothing to install: this file belongs to vlad-ryzhkov/ai-context-engineering-for-qa. Take a copy, put it at the same path in your own repository, and replace the rules that are about this project with yours.
curl -O https://raw.githubusercontent.com/vlad-ryzhkov/ai-context-engineering-for-qa/main/.claude/skills/api-tests/SKILL.mdgit clone --depth 1 https://github.com/vlad-ryzhkov/ai-context-engineering-for-qaWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/vlad-ryzhkov/ai-context-engineering-for-qa/api-tests)<a href="https://agentmods.dev/skills/vlad-ryzhkov/ai-context-engineering-for-qa/api-tests"><img src="https://agentmods.dev/badge/skills/vlad-ryzhkov/ai-context-engineering-for-qa/api-tests/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/vlad-ryzhkov/ai-context-engineering-for-qa/api-tests"><img src="https://agentmods.dev/badge/skills/vlad-ryzhkov/ai-context-engineering-for-qa/api-tests.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00055 | $0.04096 |
| Opus 5.5 | $0.00022 | $0.01638 |
| Sonnet 5.5 | $0.00011 | $0.00819 |
| Haiku 4.5 | $0.00006 | $0.00410 |
Grade A, and why
api-tests scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 1mo ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 167 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Recommended Flow
Main pipeline: /repo-scout → /api-test-cases → /api-tests.
For single-endpoint deep-dive: /spec-audit → /api-isolated-tests → /api-tests.
Running directly on a specification also works — the skill will generate tests without a scenario matrix, but traceability @Link annotations will reference the spec instead of scenario IDs.
🔒 SYSTEM REQUIREMENTS
Before execution the agent MUST load: .claude/protocols/gardener.md
SDET: API Automation (Kotlin)
When to Use
- There is
audit/test-scenarios.mdwith a scenario matrix — cover them with automated tests - Need to write tests for a new endpoint from scratch
- Review existing tests for standards compliance (
reviewarg)
Input Context (Process Isolation)
context: fork — you cannot see chat history before your invocation.
Allowed inputs: audit/test-scenarios.md, specification, CLAUDE.md, build.gradle.kts, existing src/ (style reference only).
Forbidden: Assumptions from "previous agent context", inventing endpoint contracts.
Protocol
- Stack: Locked in CLAUDE.md → Tech Stack. Kotlin-specific additions: Ktor HttpClient(CIO) via
by lazy(LazyThreadSafetyMode.SYNCHRONIZED), Awaitility (seconds only), Faker (TestData generators), JSON Schema Validator. - BANNED:
Thread.sleep,delay,runBlocking(userunTest),HttpClient(in*Tests.kt(inline HTTP in tests), manual@AllureId,shouldBe(useassertEquals),assert((Kotlin builtin — useassertEquals/assertTruefromorg.junit.jupiter.api.Assertions),LocalDateTime.now()in strict assertions. Zero-comment policy://and/* */in generated code are FORBIDDEN. 2a. Coroutine Tests: Preferred:fun test(): Unit = runTest { }fromkotlinx-coroutines-test. IfrunBlockingis unavoidable — explicit return type required:fun test(): Unit = runBlocking { }. FORBIDDEN:delay()as timing substitute — use Awaitility. 2b. Test Lifecycle:@BeforeEach/@AfterEachfor setup/teardown.lateinit varfor resources requiring cleanup. FORBIDDEN:@TestInstance(PER_CLASS)with field initialization — JUnit skips class init on constructor failure. 2c. DRY API Clients: FORBIDDEN: duplicating client method bodies to return different response types (e.g.,registerUser(): RegisterResponse+registerUserExpectError(): ErrorResponsewith identical request construction). Generate a single method returningHttpResponseor a genericsuspend inline fun <reified T> request(...)and let the test parse the body as needed. (ref:api/dry-api-client.md) 2d. Fail Fast in Test Clients: FORBIDDEN: wrapping API client HTTP calls or JSON deserialization intry/catchblocks that return empty stub objects (catch (e: Exception) { return RegisterResponse() }). Exceptions MUST propagate so the test runner reports the infrastructure failure at the point of failure, not on a later assertion. (ref:api/silent-catch.md) 2e. Ktor Body Extraction Rule: FORBIDDEN:response.toString()to obtain response body — in Ktor this returns object metadata, not the body. Useresponse.body<T>()(typed, viaContentNegotiationplugin) orresponse.bodyAsText()if raw string is required. ManualJson.decodeFromString(response.toString())is a guaranteed runtime crash. (ref:api/ktor-body-extraction.md) 2f. Single Serialization Framework Rule: Use exactly one JSON framework across the entire generation — either Jackson OR kotlinx.serialization. FORBIDDEN: mixing Jackson annotations (@JsonProperty,@JsonNaming,@JsonIgnoreProperties) withkotlinx.serializationparsing (Json.decodeFromString,@Serializable). If using Ktor withContentNegotiation(jackson()), deserialize viaresponse.body<T>()— never parse raw strings manually. If the stack isjackson, all DTOs use@JsonNaming/@JsonProperty. If the stack iskotlinx.serialization, all DTOs use@Serializableand no Jackson annotations appear anywhere. 2g. Time-Dependent Scenarios (TTL/Cache): FORBIDDEN: UsingThread.sleepordelay()to simulate time passing for cache expiration, idempotency TTLs, or rate limits. Do not blindly execute sequential requests expecting time to advance instantly. For short asynchronous state changes, use Awaitility. For long temporal conditions (e.g., 5-minute cache expiration), if the specification does NOT explicitly provide a testability hook (e.g.,X-Test-Advance-Timeheader or cache invalidation endpoint), you MUST generate the complete test logic and annotate the test method with@Disabled("Time-dependent scenario: {Wait Time}. Requires testability hook (time-travel/cache-clear) or manual execution."). 2h. Timestamp Response Validation: If the specification defines a time-based response field (e.g.,expires_at = request_time + N minutes, JWTexpclaim), the test MUST validate it with a relative drift check:assertTrue(abs(actual - expected) < driftToleranceSeconds, "timestamp drift"). UsingInstant.now()+ offset is acceptable; usingisNotBlank()or> 0alone is INSUFFICIENT. FORBIDDEN:LocalDateTime.now()in assertions. 2i. WireMock Integration for External Services: When a test configures WireMock stubs for external services (SMS gateway, payment provider, etc.), the test MUST connect the mock to the application under test. At minimum: set a system property or environment variable (e.g.,System.setProperty("SMS_GATEWAY_URL", "http://localhost:${wireMockServer.port()}")) in@BeforeEachand clear it in@AfterEach. A disconnected WireMock server (started but not referenced by the app) is a SILENT TEST BUG — the test passes/fails based on real service state, not mock behavior. 2k. Eventual Consistency Writes: Ifrepo-scout-report§12 marks a write→read pair as "Eventual", FORBIDDEN to assert the read immediately after write. Use Awaitility polling with bounded timeout. (ref:api/eventual-consistency-writes.md) 2l. Batch Partial Failure: Ifrepo-scout-report§12 lists batch operations, include a mixed valid+invalid input case to verify error propagation strategy (atomic rollback vs partial 207 Multi-Status). Testing only all-valid and all-invalid is INSUFFICIENT. (ref:api/batch-partial-failure.md) 2j. Configurable BASE_URL: Use a computed property so any CI/CD environment can override the target server without recompilation:val BASE_URL: String get() = System.getProperty("BASE_URL", "http://localhost:8080"). IfConnectExceptionappears in Smoke Run and no live server is available → run/api-mocksto generate an in-process mock, then re-run. TLS-enforcement tests cannot pass with an HTTP mock — acceptable as documented infra limitation. 2m. TLS/HTTPS Enforcement Tests: FORBIDDEN: generating a test that replaceshttps://withhttp://and asserts a 4xx rejection — when both URLs hit the same HTTP-only mock, the test structurally passes regardless of TLS state (silent false-positive). If a scenario requires verifying TLS enforcement and no HTTPS infrastructure exists: generate the test skeleton, immediately annotate@Disabled("TLS enforcement: requires HTTPS-capable server or WireMock HTTPS mode. HTTP mock cannot simulate certificate/protocol rejection."), and add a code comment explaining the correct infrastructure requirement. Do NOT generate a functionally broken test. 2n. HTTP Client Timeout (Mandatory): EveryHttpClientinstantiation MUST include:install(HttpTimeout) { requestTimeoutMillis = 30_000L; connectTimeoutMillis = 10_000L; socketTimeoutMillis = 30_000L }. Tests without timeout configuration hang indefinitely on infrastructure failures and block CI pipelines. - Security Headers Rule: Every positive test (POST/PUT/DELETE with 2xx) MUST verify
Content-Type,X-Content-Type-Options,Strict-Transport-SecurityviaassertEqualsonresponse.headers. (ref:api/missing-security-headers.md) - Structure:
requests/: DTOs + Request/Response objects. ALL data classes mapped to snake_case JSON (request AND response) — apply@JsonNaming(SnakeCaseStrategy::class)on all DTOs — omitting it on response DTOs causes silent null fields. Also add@JsonIgnoreProperties(ignoreUnknown = true).helpers/:@Stepannotated flows.tests/:@Epic(from feature/package name),@Feature(from endpoint name),@Severity,@DisplayName.@AllureId— NOT generated: assigned manually or via utility after TMS binding. MANDATORY TAGS: Analyze business logic — add@Tag("CRITICAL")+@Severity(SeverityLevel.CRITICAL)for Money flows, Security/Auth, or Data integrity endpoints; add@Tag("REGRESSION")for all others.- External Integrations: If the endpoint under test calls 3rd-party services (payments, SMS, email providers), configure a WireMock stub in
@BeforeEachso the test does not make real HTTP calls to external domains.
- Gates:
compileTestKotlin,ktlintCheck.
What ships with it
3 files beside SKILL.md in the same directory: the scripts, references and assets a skill reads on demand. Not counted in the per-session cost; read them before you install if any of them is executable.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 1mo ago Changed · +142 lines · +34 tokens per session e434bd9a9d29
- 1mo ago First seen · 25 lines · 21 tokens per session scan A 2d17a848602a
api-tests is a skill published in the GitHub repository vlad-ryzhkov/ai-context-engineering-for-qa (6 stars, last pushed 1mo ago), licensed Unlicense. It adds 55 tokens to every session and 4,096 once invoked, about $0.0002 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.
Other skills, from other repositories
Kotlin Testing Patterns
Kotlin testing with JUnit 5, MockK, Kotest, coroutine testing, Android testing with Espresso, and Kotlin-specific assertion libraries.
effective-kotlin
Apply Effective Kotlin best practices (Marcin Moskała, 2nd Ed). Covers Safety (Items 1-10: mutability, scope, nulls, types, expectations, errors, resources, tests), Readability (Items 11-18: operators, receivers, properties, naming), Reusability (Items 19-25: DRY, generics, delegation, variance), Abstraction (Items…
kotlin-in-action
Apply Kotlin In Action practices (Elizarov, Isakova, Aigner, Jemerov, 2nd Ed). Covers Basics (Ch 1-3: functions, extensions, default args), Classes (Ch 4: sealed, data, delegation, companion objects), Lambdas (Ch 5-6: functional APIs, sequences, scope functions), Nullability (Ch 7-8: safe calls, Elvis, platform types…
exploratory-nightly-verification
Operational rules for a 60-minute single-shot exploratory verification of a Kotlin project's main branch (Android / JVM / KMP / Compose / server-side Kotlin). Runs sequentially through cat1–cat5 inside a single CI job (e.g. a nightly GitHub Actions workflow), writes findings Markdown-by-Markdown to…
kotlin-testing
Kotlin testing patterns with Kotest, MockK, coroutine testing, property-based testing, and Kover coverage. Follows TDD methodology with idiomatic Kotlin practices.
swift-testing-pro
Writes, reviews, and improves Swift Testing code using modern APIs and best practices. Use when reading, writing, or reviewing projects that use Swift Testing.