$npx -y skills add PramodDutta/qaskills --skill api-test-suite-generatorAutomatically generate comprehensive API test suites from OpenAPI specifications covering CRUD operations, error handling, authentication, pagination, and edge cases
| 1 | # API Test Suite Generator Skill |
| 2 | |
| 3 | You are an expert QA automation engineer specializing in generating comprehensive API test suites from OpenAPI (Swagger) specifications. When the user asks you to generate, review, or enhance API tests from an OpenAPI spec, follow these detailed instructions. |
| 4 | |
| 5 | ## Core Principles |
| 6 | |
| 7 | 1. **Spec-driven testing** -- The OpenAPI specification is the single source of truth. Every test should trace back to a documented endpoint, schema, or constraint in the spec. |
| 8 | 2. **Complete CRUD coverage** -- Generate tests for all Create, Read, Update, and Delete operations for every resource. Never leave an endpoint untested. |
| 9 | 3. **Negative testing first** -- Error paths outnumber happy paths. For every successful scenario, generate at least three failure scenarios covering invalid input, missing authentication, and resource conflicts. |
| 10 | 4. **Contract fidelity** -- Validate response schemas strictly against the OpenAPI definitions. A 200 response with a missing required field is a test failure. |
| 11 | 5. **Environment independence** -- Tests must run against any environment (local, staging, production) by externalizing base URLs, credentials, and test data. |
| 12 | 6. **Idempotent test suites** -- Each test run should leave the system in the same state it found it. Create what you need, clean up what you created. |
| 13 | 7. **Deterministic ordering** -- Tests should not depend on execution order. Use setup and teardown hooks to establish preconditions explicitly. |
| 14 | |
| 15 | ## Project Structure |
| 16 | |
| 17 | Organize your API test suite with clear separation between configuration, test logic, and utilities: |
| 18 | |
| 19 | ``` |
| 20 | tests/ |
| 21 | api/ |
| 22 | specs/ |
| 23 | openapi.yaml |
| 24 | openapi.json |
| 25 | generated/ |
| 26 | users.api.spec.ts |
| 27 | products.api.spec.ts |
| 28 | orders.api.spec.ts |
| 29 | auth.api.spec.ts |
| 30 | helpers/ |
| 31 | api-client.ts |
| 32 | schema-validator.ts |
| 33 | auth-helper.ts |
| 34 | pagination-helper.ts |
| 35 | test-data-factory.ts |
| 36 | fixtures/ |
| 37 | users.fixture.ts |
| 38 | products.fixture.ts |
| 39 | config/ |
| 40 | environments.ts |
| 41 | api.config.ts |
| 42 | postman/ |
| 43 | collection.json |
| 44 | environment.json |
| 45 | rest-assured/ |
| 46 | src/test/java/api/ |
| 47 | UsersApiTest.java |
| 48 | ProductsApiTest.java |
| 49 | BaseApiTest.java |
| 50 | playwright.config.ts |
| 51 | ``` |
| 52 | |
| 53 | ## OpenAPI Spec Parsing |
| 54 | |
| 55 | The foundation of automated test generation is reliable spec parsing. Extract endpoints, methods, parameters, request bodies, response schemas, and authentication requirements. |
| 56 | |
| 57 | ### Parsing an OpenAPI Specification |
| 58 | |
| 59 | ```typescript |
| 60 | import * as fs from 'fs'; |
| 61 | import * as yaml from 'js-yaml'; |
| 62 | |
| 63 | interface OpenApiEndpoint { |
| 64 | path: string; |
| 65 | method: string; |
| 66 | operationId: string; |
| 67 | summary: string; |
| 68 | parameters: OpenApiParameter[]; |
| 69 | requestBody?: OpenApiRequestBody; |
| 70 | responses: Record<string, OpenApiResponse>; |
| 71 | security: OpenApiSecurity[]; |
| 72 | tags: string[]; |
| 73 | } |
| 74 | |
| 75 | interface OpenApiParameter { |
| 76 | name: string; |
| 77 | in: 'query' | 'path' | 'header' | 'cookie'; |
| 78 | required: boolean; |
| 79 | schema: OpenApiSchema; |
| 80 | description?: string; |
| 81 | } |
| 82 | |
| 83 | interface OpenApiSchema { |
| 84 | type: string; |
| 85 | format?: string; |
| 86 | enum?: string[]; |
| 87 | minimum?: number; |
| 88 | maximum?: number; |
| 89 | minLength?: number; |
| 90 | maxLength?: number; |
| 91 | pattern?: string; |
| 92 | required?: string[]; |
| 93 | properties?: Record<string, OpenApiSchema>; |
| 94 | items?: OpenApiSchema; |
| 95 | } |
| 96 | |
| 97 | interface OpenApiRequestBody { |
| 98 | required: boolean; |
| 99 | content: Record<string, { schema: OpenApiSchema }>; |
| 100 | } |
| 101 | |
| 102 | interface OpenApiResponse { |
| 103 | description: string; |
| 104 | content?: Record<string, { schema: OpenApiSchema }>; |
| 105 | } |
| 106 | |
| 107 | interface OpenApiSecurity { |
| 108 | [scheme: string]: string[]; |
| 109 | } |
| 110 | |
| 111 | function parseOpenApiSpec(filePath: string): OpenApiEndpoint[] { |
| 112 | const content = fs.readFileSync(filePath, 'utf-8'); |
| 113 | const spec = filePath.endsWith('.yaml') || filePath.endsWith('.yml') |
| 114 | ? yaml.load(content) as any |
| 115 | : JSON.parse(content); |
| 116 | |
| 117 | const endpoints: OpenApiEndpoint[] = []; |
| 118 | |
| 119 | for (const [path, methods] of Object.entries(spec.paths || {})) { |
| 120 | for (const [method, operation] of Object.entries(methods as Record<string, any>)) { |
| 121 | if (['get', 'post', 'put', 'patch', 'delete'].includes(method)) { |
| 122 | endpoints.push({ |
| 123 | path, |
| 124 | method: method.toUpperCase(), |
| 125 | operationId: operation.operationId || `${method}_${path}`, |
| 126 | summary: operation.summary || '', |
| 127 | parameters: [ |
| 128 | ...(spec.paths[path].parameters || []), |
| 129 | ...(operation.parameters || [] |