api-test-restassure
Use this skill when you need to parse multi-format API definitions and generate Rest Assured Java test classes; triggers include Rest Assured, RestAssured, and Java API automation.
Install
npx skills add https://github.com/naodeng/awesome-qa-skills/tree/main/skills/en/testing-types/api-test-restassure
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install naodeng-awesome-qa-skills@llmmart
git clone https://github.com/naodeng/awesome-qa-skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole naodeng/awesome-qa-skills collection as a plugin from our marketplace. Git is the plain clone.
README
api-test-restassure (EN)
Skill Overview
Need API outputs that should land in REST Assured based automation; The project is Java-based or already uses REST Assured.
How to Use
- Open
SKILL.mdin this folder and confirm this skill fits your task. - In your AI tool, call
@skill api-test-restassure, then add your real project context and goal. - If you need a specific output format (table, checklist, report), include it directly in your request.
One-Click Install Script
Run from the repository root:
macOS / Linux
bash ./scripts/install-skills-mac.sh --tool codex --lang en --skill api-test-restassure
Windows PowerShell
powershell -ExecutionPolicy Bypass -File .\scripts\install-skills-windows.ps1 -Tool codex -Lang en -Skill api-test-restassure
Skill manifest
api-test-restassure (EN)
Chinese version: See the corresponding Chinese skill.
When to Use
- Need API outputs that should land in REST Assured based automation.
- The project is Java-based or already uses REST Assured.
Workflow
- Read and follow the main prompt listed under Progressive disclosure (coverage, structure, quality bar).
- Add only project context that changes the result: scope, environment, constraints, risks, dependencies, expected deliverable.
- If input is incomplete, return a usable first draft and explicitly mark assumptions and gaps.
- Default to Markdown; switch formats only when the user asks.
Core Constraints
- Prioritize by risk / business impact — do not treat everything equally.
- Separate confirmed facts from current assumptions.
- Do not invent endpoints, fields, environments, or root causes the user did not provide.
- Use placeholders or env-var semantics for auth/secrets; never hardcode real credentials.
- Keep output executable: concrete scenarios, clear priority, clear next steps.
Progressive Disclosure
- Before producing output, read and follow
prompts/api-test-restassure.md(minimum coverage, output structure, quality bar). - When a ready-made template fits: use matching files under
output-templates/. - When the user wants examples or alignment with existing assets: read relevant
examples/. - For deep framework/troubleshoot/schema notes: read only the relevant file(s) under
references/, do not load the whole directory. - For format conversion or helper checks: prefer existing
scripts/over reinventing. - For evaluating/regressing this skill: use
evals/with skill-up.
Pre-delivery Checklist
- Followed the main prompt's output structure
- Minimum coverage focus: suite structure, common setup, auth handling, priority endpoints, positive scenarios, negative and boundary scenarios, assertion focus, test data strategy, ... (details in main prompt)
- Covered the minimum checklist, or explained omissions
- High-risk items have explicit priority
- Did not invent details the user did not provide
- Assumptions and gaps are marked
Common Pitfalls
- Do not pretend completeness when scope/context is missing.
- Do not treat every item as equally important.
- Do not skip assumptions and information gaps.
- Do not dump generic theory unrelated to the current toolchain.
Files (awesome-qa-skills)
-
agents
-
openai.yaml 486 B
version: 1 metadata: key: "api-test-restassure" last_verified: "2026-03-24" interface: display_name: "API Test RestAssure" short_description: "Use this skill when you need to parse multi-format API definitions and generate Rest Assured Java test classes; triggers include Rest Assured, RestAssured, and…" default_prompt: "Use api-test-restassure to complete the task with local scripts, prompts, and examples in this skill folder." policy: allow_implicit_invocation: true
-
-
evals
-
cases
-
basic-success.yaml 902 B
id: basic-success title: "RestAssured: OpenAPI/curl yields suite structure" description: | With a short OpenAPI and curl snippet, produce REST Assured Java suite/base setup/assertion structure. input: prompt: | Use api-test-restassure. Env: SIT. Auth: Bearer {{token}} (do not hardcode real tokens). Stack: Java + Maven. OpenAPI snippet: POST /v1/orders GET /v1/orders/{id} Desensitized curl: curl -X GET https://api.example.com/v1/orders/ORD-1 -H "Authorization: Bearer $TOKEN" Produce a REST Assured plan: package layout, BaseApiTest/common setup, priority cases and assertion focus. Avoid long code dumps. expect: must_contain: - "REST Assured" - "BaseApiTest" must_not_contain: - "TODO" - "I cannot" judge: type: rule_based success: - output_contains: all: - "Task Understanding" - "REST Assured" -
edge-bad-or-neighbor.yaml 735 B
id: edge-bad-or-neighbor title: "RestAssured: broken YAML or pytest neighbor" description: | With broken YAML input or a pytest neighbor request, correct and stay on REST Assured. input: prompt: | I activated api-test-restassure. Input is incomplete YAML (not a valid OpenAPI): paths: /orders: post: And I also asked: write a pytest suite too. Call out the incomplete input, still draft a REST Assured plan, and explain why pytest is out of this skill. expect: must_contain: - "REST Assured" - "pytest" must_not_contain: - "TODO" - "I cannot" judge: type: rule_based success: - output_contains: all: - "REST Assured" - "Open Questions" -
edge-incomplete-input.yaml 663 B
id: edge-incomplete-input title: "RestAssured: one-line ask still yields draft" description: | With only one sentence and no schema, still draft RestAssured structure and list gaps/assumptions. input: prompt: | Use api-test-restassure. I only know: automate points redemption. No OpenAPI and no existing Maven layout notes. Give a usable REST Assured draft structure and list required gaps and assumptions. expect: must_contain: - "assumption" - "Open Questions" must_not_contain: - "TODO" - "I cannot" judge: type: rule_based success: - output_contains: all: - "assumption" - "REST Assured"
-
-
eval.yaml 559 B
schema_version: v1alpha1 environment: type: none skills: - source: local_path path: . engine: name: claude_code # model is optional; omit to use engine default # model: # provider: anthropic # name: claude-sonnet-4-6 cases: files: - evals/cases/basic-success.yaml - evals/cases/edge-incomplete-input.yaml - evals/cases/edge-bad-or-neighbor.yaml defaults: timeout_seconds: 180 max_turns: 8 expect: exit_code: 0 must_not_contain: - "TODO" - "I cannot" report: formats: [json]
-
-
examples
-
bruno
-
sample.bru 137 B · in bundle
-
-
ci
-
github-actions-restassure.yml 905 B
name: API RestAssured CI on: workflow_dispatch: pull_request: paths: - "explore/api-test-restassure/**" jobs: test: runs-on: ubuntu-latest defaults: run: working-directory: explore/api-test-restassure/scripts/templates/restassured steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Java uses: actions/setup-java@v4 with: distribution: temurin java-version: "17" cache: maven - name: Run tests env: BASE_URL: ${{ secrets.API_BASE_URL }} API_TOKEN: ${{ secrets.API_TOKEN }} run: mvn -q test - name: Upload surefire reports if: always() uses: actions/upload-artifact@v4 with: name: surefire-reports path: explore/api-test-restassure/scripts/templates/restassured/target/surefire-reports/** -
Jenkinsfile.restassure 605 B · in bundle
-
-
sample.curl 212 B · in bundle
-
sample.insomnia.json 502 B
{ "_type": "export", "__export_format": 4, "__export_date": "2026-03-23T00:00:00.000Z", "__export_source": "insomnia.desktop.app:v9.0.0", "resources": [ { "_id": "req_1", "_type": "request", "name": "List Products", "method": "GET", "url": "https://api.example.com/v1/products" }, { "_id": "req_2", "_type": "request", "name": "Create Product", "method": "POST", "url": "https://api.example.com/v1/products" } ] } -
sample.openapi.yaml 240 B
openapi: 3.0.3 info: title: Sample API version: 1.0.0 paths: /v1/users: get: summary: list users post: summary: create user /v1/users/{id}: get: summary: get user delete: summary: delete user -
sample.opencollection.json 243 B
{ "name": "OpenCollection Sample", "requests": [ { "name": "Get Orders", "method": "GET", "path": "/v1/orders" }, { "name": "Create Order", "method": "POST", "path": "/v1/orders" } ] } -
sample.postman_collection.json 704 B
{ "info": { "name": "Sample API Collection", "_postman_id": "d89a0d30-4444-4444-9999-111133335555", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, "item": [ { "name": "Get Users", "request": { "method": "GET", "url": { "raw": "https://api.example.com/v1/users", "path": [ "v1", "users" ] } } }, { "name": "Create User", "request": { "method": "POST", "url": { "raw": "https://api.example.com/v1/users", "path": [ "v1", "users" ] } } } ] } -
sample.wsdl 534 B · in bundle
-
-
output-templates
-
template-markdown.md 83 B
# Output Template ## Summary - Scope: - Key Points: ## Details - Item 1 - Item 2
-
-
prompts
-
api-test-restassure.md 5.4 KB
# API Test REST Assured Prompt From the materials the user provides, produce a REST Assured (JUnit 5) API automation plan or test-asset structure for direct implementation. ## Role - Act as a senior QA and API automation expert who turns API materials into a maintainable Java / REST Assured suite. ## Input parsing order Parse in this priority order. Higher priority wins on conflicts; when sources disagree, state the conflict and source — **do not silently invent a merged “truth”**: 1. Existing Java test assets (`src/test/java`, base classes, `pom.xml` / Gradle, TestNG/JUnit) 2. OpenAPI / Swagger 3. Postman Collection, Insomnia, Bruno, or OpenCollection 4. curl examples 5. Loose notes (tables, Markdown, verbal endpoint lists) Also absorb when present: business scope, auth, environments, release priority, CI, dependency versions. Extract only paths, methods, params, fields, and sample values that **actually appear** in the materials. Put gaps in “missing information”. ## Defaults (use these unless the user specifies otherwise) Prefer defaults; do not present a framework menu. **Directory layout (Maven default)** ```text src/test/java/com/example/api/ BaseApiTest.java # shared RequestSpecification <Resource>ApiTest.java # per resource or critical flow src/test/resources/ test.properties # non-secret defaults; secrets prefer env vars ``` Build: Maven + JUnit 5 + REST Assured by default. If the project already uses Gradle/TestNG, **align to it** — do not force a stack change. **Naming** - classes: `PascalCase` + `ApiTest` suffix (e.g. `OrdersApiTest`) - methods: `camelCase` behavior (e.g. `createOrderShouldReturn201`, `getUserWithoutTokenShouldReturn401`) - package: reuse the project package; otherwise `com.example.api` **Shared setup and auth** - `BaseApiTest` builds `RequestSpecification`: `baseUri`, JSON Content-Type, Authorization - `BASE_URL` / `API_TOKEN`: prefer `System.getenv`, then `test.properties`; property files may only hold placeholders (`replace-me`) — never real secrets - Cases call `given().spec(requestSpec)` **Assertion style** - Fluent: `.statusCode(...)` + `.body("field", equalTo(...))` (fields must come from materials) - Minimum: status + critical fields; Hamcrest matchers - Unknown error bodies: assert status family only and mark the assumption — do not invent errorCode **Layers (default)** - JUnit 5 tags: `smoke` / `contract` / `negative`; CI runs `@Tag("smoke")` first If a base class or layering already exists, **align to it**. ## Gotchas - **Never** hardcode real tokens, passwords, or cookies in `test.properties`, sample code, or output. - When migrating from curl/Postman: redact sensitive headers. - **Do not invent** paths, fields, status codes, or JSON paths the user did not provide. - Do not switch to Spring MockMvc / Karate / a non-Java stack unless the user asks. - If materials give relative paths without a host, use a placeholder `baseUrl` and list the gap — do not invent a gateway hostname as confirmed fact. - If information is incomplete, still ship a usable first version (package layout + Base + confirmed case outlines) and list assumptions. - Unless the user asks for runnable files, prefer structure and method outlines over huge full class dumps. ## Minimum coverage checklist Unless the user explicitly narrows scope, the result must cover: - suite / package structure and Base class responsibilities - shared `RequestSpecification` and config sources - how auth and permission cases are organized - high-priority endpoints (P0/P1) - positive scenarios - negative and boundary scenarios - assertion focus (status + body) - test-data strategy - CI or local runs (including tag filters) - missing information and assumptions ## Output Return results in this order: ### 1. Task Understanding - API / domain under test - test goal - in-scope endpoints or flows - out-of-scope or unclear areas - input sources and conflict handling ### 2. REST Assured Test Plan or Structure - proposed packages and class list - `BaseApiTest` / config responsibilities - env vars and `test.properties` keys (no real secrets) - tag / layer strategy - alignment with existing Maven/Gradle suites (if any) ### 3. Priority Coverage For each P0/P1 case: - class and method names - method / path (confirmed only) - priority and risk rationale - positive / negative / boundary points - assertion focus (`statusCode`, body JSON paths) - dependencies on `requestSpec` or data ### 4. Setup and Data Notes - how auth is injected (Bearer placeholder, etc.) - test-data setup and cleanup - multi-environment switching ### 5. Execution Suggestions - local: `mvn test` / tag-filter examples - smoke vs regression scope - minimal CI steps and secret variable names - release-blocking checks ### 6. Open Questions - gaps and assumptions used this round ## Pre-delivery checklist - [ ] Inputs followed the parsing order; conflicts and gaps are called out - [ ] Package layout / Base / env placeholders match defaults (or explain reuse of existing) - [ ] No real secrets; no invented paths/fields/JSON paths - [ ] P0/P1 cases have concrete class/method names and assertion focus - [ ] Smoke tags and CI path are actionable ## Quality bar - Stay REST Assured + JUnit 5 specific (or the user’s equivalent existing stack). - Prioritize by risk. - Separate confirmed facts from assumptions. - Avoid huge Java dumps unless the user asks for runnable files.
-
-
references
-
local
-
api-testing_EN.md 492 B
# Archived Local Reference This file is a lightweight legacy note. The previous long snapshot was removed to avoid duplicate and outdated guidance. ## Use Instead - Main prompt: `prompts/api-test-restassure.md` - Main entry: `SKILL.md` ## Notes - Keep using the current prompt and `SKILL.md` as the source of truth. - Load `references/`, `examples/`, or `scripts/` only when the task really needs extra detail. - Do not rely on this file for the latest prompt wording or workflow rules.
-
-
framework-spec.md 1.5 KB
# Rest Assured Framework Specification ## 1. Directory Convention - `scripts/parse_api_sources.py`: multi-format API source parser - `scripts/generate_restassured_tests.py`: normalized endpoint -> Java test class - `scripts/templates/restassured/`: runnable Maven test template - `generated-tests/`: output Java tests generated from parsed endpoints ## 2. Test Layer Convention - `smoke`: core endpoint availability - `contract`: status code + response shape checks - `business`: key API flows and state transitions - `negative`: invalid params, auth failure, boundary inputs ## 3. Assertion Rules - status code assertions are mandatory - key response field assertions are mandatory - latency checks on critical APIs are recommended - negative tests should validate error payload structure ## 4. Data and Environment Rules - use environment/properties for base URL and token - never commit secrets in test sources - use deterministic data or isolated test fixtures - define cleanup strategy for mutable endpoints ## 5. Parsing Scope Rules Supported parser inputs: - curl - Postman collections - Swagger/OpenAPI (including v3) - Bruno - OpenCollection - Insomnia - WSDL - ZIP containing any supported format Parser output must be normalized endpoint JSON with: - method - path - source format - optional base URL, headers, query/body hints ## 6. CI Guidance - run smoke tests on each PR - run full suite on main/nightly - fail on P0 regression - export surefire/junit XML for trend tracking -
report-schema.md 800 B
# Unified API Test Report Schema Use these fields for all generated API test reports: - `run_id`: unique run identifier - `tool`: `supertest` / `pytest` / `bruno` / `restassured` - `env`: environment name (staging/prod-like) - `case_id`: stable case identifier - `api_name`: human-readable endpoint name - `method`: HTTP method - `path`: endpoint path - `status`: `pass` / `fail` / `skip` - `status_code`: actual HTTP status code - `expected_status_code`: expected status code or range - `latency_ms`: measured request latency - `error_rate`: optional aggregated failure rate per run - `assertions_total`: total assertions - `assertions_passed`: passed assertions - `message`: failure or debug message - `timestamp`: ISO8601 UTC timestamp Recommended rule: - P0 failures should fail CI pipelines. -
setup-and-ci.md 420 B
# Setup and CI Guide ## Local ```bash cd scripts/templates/restassured mvn -q test ``` ## One-Click Flow ```bash cd scripts ./run.sh ../examples ``` ## CI Recommendation - PR: run smoke/generated subset - main/nightly: run full suite - archive surefire reports ## CI Template - `examples/ci/github-actions-restassure.yml` - `examples/ci/Jenkinsfile.restassure` ## Report Schema - `references/report-schema.md`
-
-
scripts
-
templates
-
restassured
-
src
-
test
-
java
-
com
-
example
-
api
-
BaseApiTest.java 1.1 KB · in bundle
-
HealthApiTest.java 456 B · in bundle
-
-
-
-
-
resources
-
test.properties 49 B · in bundle
-
-
-
-
pom.xml 1.3 KB · in bundle
-
-
-
generate_restassured_tests.py 2.7 KB
#!/usr/bin/env python3 import argparse import json import re from pathlib import Path def _safe_method(m: str) -> str: return m.upper() if m.upper() in {"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"} else "GET" def _safe_name(method: str, path: str, idx: int) -> str: s = f"{idx}_{method}_{path}".lower() return re.sub(r"[^a-z0-9]+", "_", s).strip("_") def _invoke_line(method: str, path: str) -> str: m = method.lower() if m in {"post", "put", "patch"}: return ( f'given().spec(requestSpec).body("{{}}").when().{m}("{path}")' '.then().statusCode(anyOf(is(200), is(201), is(202), is(204), is(400), is(401), is(403), is(404)))' '.time(lessThan(3000L));' ) return ( f'given().spec(requestSpec).when().{m}("{path}")' '.then().statusCode(anyOf(is(200), is(201), is(202), is(204), is(400), is(401), is(403), is(404)))' '.time(lessThan(3000L));' ) def build_java_class(endpoints): lines = [ "package com.example.api;", "", "import org.junit.jupiter.api.Test;", "", "import static io.restassured.RestAssured.given;", "import static org.hamcrest.Matchers.anyOf;", "import static org.hamcrest.Matchers.is;", "import static org.hamcrest.Matchers.lessThan;", "", "public class GeneratedApiTest extends BaseApiTest {", "", " @Test", " void generatedCollectionNotEmpty() {", f" org.junit.jupiter.api.Assertions.assertTrue({len(endpoints)} >= 0);", " }", "", ] for idx, ep in enumerate(endpoints, start=1): method = _safe_method(str(ep.get("method", "GET"))) path = str(ep.get("path", "/")) name = _safe_name(method, path, idx) lines.extend( [ " @Test", f" void test_{name}() {{", f" {_invoke_line(method, path)}", " }", "", ] ) lines.append("}") lines.append("") return "\n".join(lines) def main() -> None: parser = argparse.ArgumentParser(description="Generate Rest Assured tests from normalized endpoint JSON") parser.add_argument("--input", required=True, type=Path, help="Normalized endpoint JSON") parser.add_argument("--output", required=True, type=Path, help="Output Java test class path") args = parser.parse_args() payload = json.loads(args.input.read_text(encoding="utf-8")) endpoints = payload.get("endpoints", []) java = build_java_class(endpoints) args.output.parent.mkdir(parents=True, exist_ok=True) args.output.write_text(java, encoding="utf-8") print(str(args.output)) if __name__ == "__main__": main() -
parse_api_sources.py 9.1 KB
#!/usr/bin/env python3 import argparse import json import re import zipfile from pathlib import Path from typing import Dict, List, Optional from xml.etree import ElementTree as ET try: import yaml # type: ignore except Exception: yaml = None METHODS = {"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"} def _safe_text(raw: bytes) -> str: return raw.decode("utf-8", errors="ignore") def _append_endpoint(out: List[Dict], method: str, path: str, source: str, **extra) -> None: method = method.upper().strip() path = (path or "").strip() if method not in METHODS or not path: return rec = {"method": method, "path": path, "source": source} rec.update({k: v for k, v in extra.items() if v is not None}) out.append(rec) def _parse_curl(text: str, source: str) -> List[Dict]: out: List[Dict] = [] for line in [x.strip() for x in text.splitlines() if "curl " in x]: m_method = re.search(r"-X\s+([A-Za-z]+)", line) method = m_method.group(1).upper() if m_method else "GET" m_url = re.search(r"(https?://[^\s'\"\\]+)", line) if not m_url: continue url = m_url.group(1) m_path = re.match(r"https?://[^/]+(.*)", url) path = m_path.group(1) if m_path else "/" if not path: path = "/" _append_endpoint(out, method, path, source, raw_url=url, format="curl") return out def _parse_postman(obj: Dict, source: str) -> List[Dict]: out: List[Dict] = [] def walk(items: List[Dict]) -> None: for it in items or []: if "request" in it: req = it.get("request", {}) method = str(req.get("method", "GET")).upper() url_obj = req.get("url", {}) path = "/" raw_url = None if isinstance(url_obj, dict): raw_url = url_obj.get("raw") path_parts = url_obj.get("path") if isinstance(path_parts, list) and path_parts: path = "/" + "/".join(str(p) for p in path_parts) elif isinstance(raw_url, str): m = re.match(r"https?://[^/]+(.*)", raw_url) path = m.group(1) if m and m.group(1) else "/" elif isinstance(url_obj, str): raw_url = url_obj m = re.match(r"https?://[^/]+(.*)", url_obj) path = m.group(1) if m and m.group(1) else "/" _append_endpoint(out, method, path, source, raw_url=raw_url, format="postman") if isinstance(it.get("item"), list): walk(it["item"]) walk(obj.get("item", [])) return out def _parse_openapi(obj: Dict, source: str) -> List[Dict]: out: List[Dict] = [] paths = obj.get("paths", {}) if not isinstance(paths, dict): return out for path, methods in paths.items(): if not isinstance(methods, dict): continue for m in methods.keys(): method = str(m).upper() if method in METHODS: _append_endpoint(out, method, str(path), source, format="openapi") return out def _parse_insomnia(obj: Dict, source: str) -> List[Dict]: out: List[Dict] = [] resources = obj.get("resources", []) if not isinstance(resources, list): return out for r in resources: if not isinstance(r, dict): continue if r.get("_type") == "request": method = str(r.get("method", "GET")).upper() url = str(r.get("url", "")) path = "/" m = re.match(r"https?://[^/]+(.*)", url) if m and m.group(1): path = m.group(1) elif url.startswith("/"): path = url _append_endpoint(out, method, path, source, raw_url=url, format="insomnia") return out def _parse_opencollection(obj: Dict, source: str) -> List[Dict]: out: List[Dict] = [] requests = obj.get("requests") if isinstance(requests, list): for r in requests: if not isinstance(r, dict): continue method = str(r.get("method", "GET")).upper() path = str(r.get("path") or r.get("url") or "/") _append_endpoint(out, method, path, source, format="opencollection") return out def _parse_wsdl(text: str, source: str) -> List[Dict]: out: List[Dict] = [] try: root = ET.fromstring(text.encode("utf-8")) except Exception: return out ns = { "wsdl": "http://schemas.xmlsoap.org/wsdl/", "soap": "http://schemas.xmlsoap.org/wsdl/soap/", } soap_address = root.find(".//soap:address", ns) location = soap_address.attrib.get("location") if soap_address is not None else None for op in root.findall(".//wsdl:operation", ns): name = op.attrib.get("name") if not name: continue path = f"/soap/{name}" _append_endpoint(out, "POST", path, source, raw_url=location, format="wsdl", operation=name) return out def _parse_bruno(text: str, source: str) -> List[Dict]: out: List[Dict] = [] method = None url = None for line in text.splitlines(): s = line.strip() block = re.match(r"^(get|post|put|patch|delete|head|options)\s*\{", s, re.IGNORECASE) if block: method = block.group(1).upper() continue m = re.match(r"method:\s*([A-Za-z]+)", s, re.IGNORECASE) if m: method = m.group(1).upper() continue u = re.match(r"url:\s*(.+)$", s, re.IGNORECASE) if u: url = u.group(1).strip() if method and url: m = re.match(r"https?://[^/]+(.*)", url) path = m.group(1) if m and m.group(1) else (url if url.startswith("/") else f"/{url}") _append_endpoint(out, method, path, source, raw_url=url, format="bruno") return out def _load_structured(path: Path, raw: str) -> Optional[Dict]: if path.suffix.lower() == ".json": try: return json.loads(raw) except Exception: return None if path.suffix.lower() in {".yaml", ".yml"} and yaml is not None: try: obj = yaml.safe_load(raw) return obj if isinstance(obj, dict) else None except Exception: return None return None def parse_file(path: Path, raw: str) -> List[Dict]: lower_name = path.name.lower() ext = path.suffix.lower() if ext == ".wsdl" or (ext == ".xml" and "<definitions" in raw and "wsdl" in raw.lower()): return _parse_wsdl(raw, str(path)) if ext == ".bru": return _parse_bruno(raw, str(path)) if ext in {".curl", ".sh", ".txt"}: return _parse_curl(raw, str(path)) obj = _load_structured(path, raw) if obj is not None: if "openapi" in obj or "swagger" in obj: return _parse_openapi(obj, str(path)) if lower_name.endswith(".postman_collection.json") or "info" in obj and "item" in obj: return _parse_postman(obj, str(path)) if "resources" in obj: return _parse_insomnia(obj, str(path)) if lower_name.endswith(".opencollection.json") or "requests" in obj: return _parse_opencollection(obj, str(path)) return [] return _parse_curl(raw, str(path)) def parse_zip(path: Path) -> List[Dict]: out: List[Dict] = [] with zipfile.ZipFile(path) as zf: for info in zf.infolist(): if info.is_dir(): continue p = Path(info.filename) raw = _safe_text(zf.read(info)) if p.suffix.lower() == ".zip": continue out.extend(parse_file(p, raw)) return out def parse_input(path: Path) -> List[Dict]: if path.is_dir(): out: List[Dict] = [] for f in path.rglob("*"): if f.is_file(): raw = f.read_text(encoding="utf-8", errors="ignore") out.extend(parse_file(f, raw)) return out if path.suffix.lower() == ".zip": return parse_zip(path) raw = path.read_text(encoding="utf-8", errors="ignore") return parse_file(path, raw) def dedupe(endpoints: List[Dict]) -> List[Dict]: seen = set() out = [] for e in endpoints: key = (e.get("method"), e.get("path"), e.get("source")) if key in seen: continue seen.add(key) out.append(e) return out def main() -> None: parser = argparse.ArgumentParser(description="Parse API sources into normalized endpoint inventory") parser.add_argument("--input", required=True, type=Path, help="Input file/folder/zip path") parser.add_argument("--output", type=Path, help="Output JSON path") args = parser.parse_args() endpoints = dedupe(parse_input(args.input)) payload = { "input": str(args.input), "count": len(endpoints), "endpoints": endpoints, } if args.output: args.output.write_text(json.dumps(payload, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") print(str(args.output)) else: print(json.dumps(payload, ensure_ascii=False, indent=2)) if __name__ == "__main__": main() -
run.sh 647 B
#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" INPUT_PATH="${1:-$ROOT_DIR/examples}" TMP_JSON="$ROOT_DIR/.tmp.normalized.json" OUT_JAVA="$SCRIPT_DIR/templates/restassured/src/test/java/com/example/api/GeneratedApiTest.java" python3 "$SCRIPT_DIR/parse_api_sources.py" --input "$INPUT_PATH" --output "$TMP_JSON" python3 "$SCRIPT_DIR/generate_restassured_tests.py" --input "$TMP_JSON" --output "$OUT_JAVA" if ! command -v mvn >/dev/null 2>&1; then echo "mvn not found. Test class generated at: $OUT_JAVA" exit 0 fi cd "$SCRIPT_DIR/templates/restassured" mvn -q test
-
-
README.md 814 B
# api-test-restassure (EN) ## Skill Overview Need API outputs that should land in REST Assured based automation; The project is Java-based or already uses REST Assured. ## How to Use 1. Open `SKILL.md` in this folder and confirm this skill fits your task. 2. In your AI tool, call `@skill api-test-restassure`, then add your real project context and goal. 3. If you need a specific output format (table, checklist, report), include it directly in your request. ## One-Click Install Script Run from the repository root: ### macOS / Linux ```bash bash ./scripts/install-skills-mac.sh --tool codex --lang en --skill api-test-restassure ``` ### Windows PowerShell ```powershell powershell -ExecutionPolicy Bypass -File .\scripts\install-skills-windows.ps1 -Tool codex -Lang en -Skill api-test-restassure ``` -
SKILL.md 2.6 KB
--- name: api-test-restassure description: Use this skill when you need to parse multi-format API definitions and generate Rest Assured Java test classes; triggers include Rest Assured, RestAssured, and Java API automation. --- # api-test-restassure (EN) **Chinese version:** See the corresponding Chinese skill. ## When to Use - Need API outputs that should land in REST Assured based automation. - The project is Java-based or already uses REST Assured. ## Workflow 1. Read and follow the main prompt listed under Progressive disclosure (coverage, structure, quality bar). 2. Add only project context that changes the result: scope, environment, constraints, risks, dependencies, expected deliverable. 3. If input is incomplete, return a usable first draft and explicitly mark assumptions and gaps. 4. Default to Markdown; switch formats only when the user asks. ## Core Constraints - Prioritize by risk / business impact — do not treat everything equally. - Separate confirmed facts from current assumptions. - Do not invent endpoints, fields, environments, or root causes the user did not provide. - Use placeholders or env-var semantics for auth/secrets; never hardcode real credentials. - Keep output executable: concrete scenarios, clear priority, clear next steps. ## Progressive Disclosure - Before producing output, read and follow `prompts/api-test-restassure.md` (minimum coverage, output structure, quality bar). - When a ready-made template fits: use matching files under `output-templates/`. - When the user wants examples or alignment with existing assets: read relevant `examples/`. - For deep framework/troubleshoot/schema notes: read only the relevant file(s) under `references/`, do not load the whole directory. - For format conversion or helper checks: prefer existing `scripts/` over reinventing. - For evaluating/regressing this skill: use `evals/` with skill-up. ## Pre-delivery Checklist - [ ] Followed the main prompt's output structure - [ ] Minimum coverage focus: suite structure, common setup, auth handling, priority endpoints, positive scenarios, negative and boundary scenarios, assertion focus, test data strategy, ... (details in main prompt) - [ ] Covered the minimum checklist, or explained omissions - [ ] High-risk items have explicit priority - [ ] Did not invent details the user did not provide - [ ] Assumptions and gaps are marked ## Common Pitfalls - Do not pretend completeness when scope/context is missing. - Do not treat every item as equally important. - Do not skip assumptions and information gaps. - Do not dump generic theory unrelated to the current toolchain.
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.