@msalaam/xray-qe-toolkit 1.4.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +157 -71
- package/bin/cli.js +38 -25
- package/commands/createExecution.js +1 -0
- package/commands/createPlan.js +23 -34
- package/commands/importResults.js +2 -0
- package/commands/init.js +2 -0
- package/commands/pushTests.js +65 -7
- package/lib/config.js +7 -0
- package/lib/jsonFile.js +12 -0
- package/lib/playwrightConverter.js +68 -45
- package/lib/testCaseBuilder.js +374 -90
- package/lib/xrayClient.js +168 -11
- package/package.json +2 -1
- package/schema/tests.schema.json +126 -7
- package/templates/README.template.md +80 -23
- package/templates/tests.json +5295 -47
- package/commands/genTests.js +0 -138
- package/templates/SPEC-DRIVEN-APPROACH.md +0 -372
package/commands/genTests.js
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Command: xray-qe gen-tests [--ai] [--spec <path>] [--knowledge <path>] [--ticket <key>] [--prompt <text>]
|
|
3
|
-
*
|
|
4
|
-
* Generate test cases from resources/ folder documentation and specifications.
|
|
5
|
-
* Uses AI to analyze specs, requirements, and business logic to create structured test definitions.
|
|
6
|
-
*
|
|
7
|
-
* Without --ai: Provides guidance on manual test creation.
|
|
8
|
-
* With --ai: Uses connected AI provider to generate tests from knowledge sources.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import fs from "node:fs";
|
|
12
|
-
import path from "node:path";
|
|
13
|
-
import logger, { setVerbose } from "../lib/logger.js";
|
|
14
|
-
import { loadConfig } from "../lib/config.js";
|
|
15
|
-
|
|
16
|
-
export default async function genTests(opts = {}) {
|
|
17
|
-
if (opts.verbose) setVerbose(true);
|
|
18
|
-
|
|
19
|
-
logger.rocket("@msalaam/xray-qe-toolkit — Generate Test Cases\n");
|
|
20
|
-
|
|
21
|
-
const cfg = loadConfig({ envPath: opts.env });
|
|
22
|
-
const resourcesPath = opts.knowledge || cfg.resourcesPath;
|
|
23
|
-
|
|
24
|
-
// Check if resources folder exists
|
|
25
|
-
if (!fs.existsSync(resourcesPath)) {
|
|
26
|
-
logger.error(`Resources folder not found at ${resourcesPath}`);
|
|
27
|
-
logger.info("Run 'npx xray-qe init' to create the resources/ folder structure");
|
|
28
|
-
process.exit(1);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Validate --ai flag requirement
|
|
32
|
-
if (!opts.ai) {
|
|
33
|
-
logger.error("AI-assisted generation is not enabled");
|
|
34
|
-
logger.info("Use the --ai flag to enable AI-powered test generation");
|
|
35
|
-
logger.blank();
|
|
36
|
-
console.log("📖 Manual test creation workflow:");
|
|
37
|
-
console.log(" 1. Review documentation in resources/ folder");
|
|
38
|
-
console.log(" 2. Create test cases manually: npx xray-qe edit-json");
|
|
39
|
-
console.log(" 3. Or enable AI generation: npx xray-qe gen-tests --ai");
|
|
40
|
-
logger.blank();
|
|
41
|
-
process.exit(1);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
logger.info("🤖 AI-assisted test generation enabled");
|
|
45
|
-
logger.blank();
|
|
46
|
-
|
|
47
|
-
// Scan resources folder for source documents
|
|
48
|
-
const sources = scanKnowledgeFolder(resourcesPath);
|
|
49
|
-
|
|
50
|
-
// Handle specific source flags
|
|
51
|
-
if (opts.spec && fs.existsSync(opts.spec)) {
|
|
52
|
-
logger.info(`📄 OpenAPI spec: ${opts.spec}`);
|
|
53
|
-
sources.apiSpecs.push(opts.spec);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (opts.ticket) {
|
|
57
|
-
logger.info(`🎫 JIRA ticket: ${opts.ticket}`);
|
|
58
|
-
sources.tickets.push(opts.ticket);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (opts.prompt) {
|
|
62
|
-
logger.info(`💬 Prompt: "${opts.prompt}"`);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
logger.blank();
|
|
66
|
-
logger.info("📚 Knowledge sources discovered:");
|
|
67
|
-
console.log(` API Specs: ${sources.apiSpecs.length} file(s)`);
|
|
68
|
-
console.log(` Requirements: ${sources.requirements.length} file(s)`);
|
|
69
|
-
console.log(` Tickets: ${sources.tickets.length} file(s)`);
|
|
70
|
-
logger.blank();
|
|
71
|
-
|
|
72
|
-
if (sources.apiSpecs.length === 0 && sources.requirements.length === 0 && sources.tickets.length === 0) {
|
|
73
|
-
logger.warn("No resource sources found!");
|
|
74
|
-
logger.info("Add OpenAPI specs, requirements docs, or JIRA exports to resources/ folders");
|
|
75
|
-
logger.info("See resources/README.md for supported file types");
|
|
76
|
-
logger.blank();
|
|
77
|
-
process.exit(1);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// AI provider connection scaffold (not yet implemented)
|
|
81
|
-
logger.warn("⚠️ AI provider not yet connected");
|
|
82
|
-
logger.blank();
|
|
83
|
-
console.log("🔧 To connect an AI provider:");
|
|
84
|
-
console.log(" 1. Implement AI provider integration in mcp/server.js");
|
|
85
|
-
console.log(" 2. Configure provider credentials in .env");
|
|
86
|
-
console.log(" 3. Or use the MCP server: npx xray-qe mcp-server");
|
|
87
|
-
console.log(" 4. Or use VS Code @xray-qe chat participant");
|
|
88
|
-
logger.blank();
|
|
89
|
-
console.log("📋 For now, you can:");
|
|
90
|
-
console.log(" • Review knowledge sources and create tests manually via 'npx xray-qe edit-json'");
|
|
91
|
-
console.log(" • Use the browser-based editor to build your test suite");
|
|
92
|
-
console.log(" • Use Copilot + SPEC-DRIVEN-APPROACH.md to generate tests from resources/openapi.yaml + business-rules.yaml");
|
|
93
|
-
logger.blank();
|
|
94
|
-
|
|
95
|
-
logger.info("Scaffold ready. Connect an AI provider to enable automated test generation.");
|
|
96
|
-
logger.blank();
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Scan resources folder and return categorized file paths
|
|
101
|
-
*/
|
|
102
|
-
function scanKnowledgeFolder(resourcesPath) {
|
|
103
|
-
const sources = {
|
|
104
|
-
apiSpecs: [],
|
|
105
|
-
requirements: [],
|
|
106
|
-
tickets: [],
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const apiSpecsDir = path.join(resourcesPath, "api-specs");
|
|
110
|
-
const requirementsDir = path.join(resourcesPath, "requirements");
|
|
111
|
-
const ticketsDir = path.join(resourcesPath, "tickets");
|
|
112
|
-
|
|
113
|
-
// Scan api-specs/
|
|
114
|
-
if (fs.existsSync(apiSpecsDir)) {
|
|
115
|
-
const files = fs.readdirSync(apiSpecsDir);
|
|
116
|
-
sources.apiSpecs = files
|
|
117
|
-
.filter((f) => /\.(yaml|yml|json|graphql|gql)$/i.test(f))
|
|
118
|
-
.map((f) => path.join(apiSpecsDir, f));
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Scan requirements/
|
|
122
|
-
if (fs.existsSync(requirementsDir)) {
|
|
123
|
-
const files = fs.readdirSync(requirementsDir);
|
|
124
|
-
sources.requirements = files
|
|
125
|
-
.filter((f) => /\.(md|txt|docx|pdf)$/i.test(f))
|
|
126
|
-
.map((f) => path.join(requirementsDir, f));
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Scan tickets/
|
|
130
|
-
if (fs.existsSync(ticketsDir)) {
|
|
131
|
-
const files = fs.readdirSync(ticketsDir);
|
|
132
|
-
sources.tickets = files
|
|
133
|
-
.filter((f) => /\.(json|xml|html|md|txt)$/i.test(f))
|
|
134
|
-
.map((f) => path.join(ticketsDir, f));
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
return sources;
|
|
138
|
-
}
|
|
@@ -1,372 +0,0 @@
|
|
|
1
|
-
# Spec-Driven API Test Automation — QE Process & Workflow
|
|
2
|
-
|
|
3
|
-
> **Scope:** API testing with Playwright (no UI/browser).
|
|
4
|
-
> **Source of truth:** `openapi.yaml` (API shape) + `business-rules.yaml` (domain logic & scenarios).
|
|
5
|
-
> **Per-service repos:** Each API gets its own `{ServiceName}_Automation` repo.
|
|
6
|
-
>
|
|
7
|
-
> This document defines the end-to-end workflow from specification to test execution.
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## Overview
|
|
12
|
-
|
|
13
|
-
The spec-driven approach uses two knowledge artifacts — an **OpenAPI specification** and a **`business-rules.yaml`** file — to produce a complete, traceable API test suite.
|
|
14
|
-
|
|
15
|
-
The process follows a strict sequence:
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
openapi.yaml + business-rules.yaml
|
|
19
|
-
↓
|
|
20
|
-
Generate tests.json (test definitions)
|
|
21
|
-
↓
|
|
22
|
-
xqt push-tests → creates Xray Test issues + Test Sets in Jira
|
|
23
|
-
↓
|
|
24
|
-
xray-mapping.json populated with issue keys
|
|
25
|
-
↓
|
|
26
|
-
Playwright API tests created (1:1 with tests.json entries)
|
|
27
|
-
↓
|
|
28
|
-
Sprint starts → create Test Plan → link Test Sets
|
|
29
|
-
↓
|
|
30
|
-
Run tests → xqt import-results → Test Execution in Xray
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
### Why Two Files?
|
|
34
|
-
|
|
35
|
-
| File | What It Provides | Who Maintains |
|
|
36
|
-
|------|-----------------|---------------|
|
|
37
|
-
| `openapi.yaml` | Schemas, paths, status codes, parameter types, auth schemes | Developers |
|
|
38
|
-
| `business-rules.yaml` | Domain rules, validation logic, edge-case scenarios, test data | Developers + QA |
|
|
39
|
-
|
|
40
|
-
The OpenAPI spec tells you **what the API looks like**.
|
|
41
|
-
The business rules tell you **what the API should do**.
|
|
42
|
-
Together they are sufficient to generate a complete test suite. Neither alone is enough.
|
|
43
|
-
|
|
44
|
-
### 1:1 Traceability
|
|
45
|
-
|
|
46
|
-
Every `business-rules.yaml` rule maps to exactly one `tests.json` entry, one Xray Test issue, and one Playwright `test()` call. Nothing exists in one place that doesn't exist in all three.
|
|
47
|
-
|
|
48
|
-
---
|
|
49
|
-
|
|
50
|
-
## Test Organisation in Jira/Xray
|
|
51
|
-
|
|
52
|
-
### Test Sets (persistent groupings)
|
|
53
|
-
|
|
54
|
-
Tests live in **Test Sets** in Jira. Test Sets group related tests by feature, endpoint, or category. They are the primary organisational unit.
|
|
55
|
-
|
|
56
|
-
- One Test Set per `business-rules.yaml` feature (e.g. "Health Check", "User Management", "Payments")
|
|
57
|
-
- Tests are added to Test Sets when pushed via `xqt push-tests`
|
|
58
|
-
- Test Sets are permanent — they persist across sprints
|
|
59
|
-
- The `testSet` field in `tests.json` determines which Test Set a test belongs to
|
|
60
|
-
|
|
61
|
-
### Test Plans (per-sprint)
|
|
62
|
-
|
|
63
|
-
A **Test Plan** represents work for a specific sprint or release. When entering a sprint:
|
|
64
|
-
|
|
65
|
-
1. Create a Test Plan for the sprint: `npx xqt create-plan --summary "Sprint 12 — Payments API"`
|
|
66
|
-
2. Link the relevant Test Sets to the Test Plan
|
|
67
|
-
3. Each CI run creates a new **Test Execution** linked to that Test Plan
|
|
68
|
-
4. At sprint end, the Test Plan shows full pass/fail history for that sprint's scope
|
|
69
|
-
|
|
70
|
-
This means:
|
|
71
|
-
- **Test Sets** = what tests exist (permanent)
|
|
72
|
-
- **Test Plans** = what we're testing this sprint (per-sprint)
|
|
73
|
-
- **Test Executions** = individual CI runs (ephemeral)
|
|
74
|
-
|
|
75
|
-
---
|
|
76
|
-
|
|
77
|
-
## Deterministic Generation Rules
|
|
78
|
-
|
|
79
|
-
> **These rules are contracts, not guidelines.**
|
|
80
|
-
> The same inputs must always produce the same outputs. Any deviation breaks `xray-mapping.json` stability and orphans Xray test issues.
|
|
81
|
-
|
|
82
|
-
### `testId` Derivation
|
|
83
|
-
|
|
84
|
-
```
|
|
85
|
-
testId = "TC-{SERVICE_CODE}-{SCENARIO_ID}"
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
- `SERVICE_CODE` — uppercase alphanumeric slug of the service name, max 8 chars. Example: `PAYMENTS`, `USERMGMT`, `AUTH`.
|
|
89
|
-
- `SCENARIO_ID` — the `id` field from `business-rules.yaml` verbatim. Example: `BR-001`, `BR-042`.
|
|
90
|
-
- Full example: `TC-PAYMENTS-BR-001`
|
|
91
|
-
- `testId` values are **stable and permanent**. Once pushed to Xray they never change.
|
|
92
|
-
- If a rule is removed from `business-rules.yaml`, its entry in `tests.json` gets `"skip": true` — it is never deleted.
|
|
93
|
-
|
|
94
|
-
### `tests.json` Field Mapping
|
|
95
|
-
|
|
96
|
-
Every field is derived deterministically from the knowledge artifacts. No creative decisions.
|
|
97
|
-
|
|
98
|
-
| `tests.json` field | Source | Derivation rule |
|
|
99
|
-
|---|---|---|
|
|
100
|
-
| `test_id` | `rule.id` | `TC-{SERVICE_CODE}-{rule.id}` |
|
|
101
|
-
| `xray.summary` | `rule.description` | Copied verbatim |
|
|
102
|
-
| `xray.description` | `rule.given` + `rule.when` + `rule.then` | `"Given {given}, when {when}, then {then}"` |
|
|
103
|
-
| `tags` | `rule.tags` | Copied from rule tags array |
|
|
104
|
-
| `xray.priority` | `rule.priority` | Direct mapping (see table below) |
|
|
105
|
-
| `requirementKeys` | `rule.requirementKeys` | Copied verbatim. Empty array if absent |
|
|
106
|
-
| `folder` | Feature name + category | `"/{ServiceName}/{FeatureName}/{CategoryFolder}"` |
|
|
107
|
-
| `testSet` | Feature `name` | The feature name becomes the Test Set name |
|
|
108
|
-
| `skip` | `rule.skip` or absence flag | `false` by default. `true` if rule deprecated |
|
|
109
|
-
| `xray.testType` | Always `"Generic"` | All automated API tests are Generic type |
|
|
110
|
-
| `xray.definition` | rule description + endpoint | `"Automated Playwright API test: {endpoint} — {rule.description}"` |
|
|
111
|
-
|
|
112
|
-
#### Priority Mapping
|
|
113
|
-
|
|
114
|
-
| `business-rules.yaml` priority | `tests.json` / Xray priority |
|
|
115
|
-
|---|---|
|
|
116
|
-
| `Highest` | `Highest` |
|
|
117
|
-
| `High` | `High` |
|
|
118
|
-
| `Medium` | `Medium` |
|
|
119
|
-
| `Low` | `Low` |
|
|
120
|
-
| `Lowest` | `Lowest` |
|
|
121
|
-
| *(absent)* | `Medium` |
|
|
122
|
-
|
|
123
|
-
#### Folder Path Rules
|
|
124
|
-
|
|
125
|
-
```
|
|
126
|
-
/{ServiceName}/{FeatureName}/{CategoryFolder}
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
| `rule.category` | Folder segment |
|
|
130
|
-
|---|---|
|
|
131
|
-
| `validation` | `Validation` |
|
|
132
|
-
| `authorization` | `Authorization` |
|
|
133
|
-
| `business-logic` | `BusinessLogic` |
|
|
134
|
-
| `edge-case` | `Edge` |
|
|
135
|
-
| `integration` | `Integration` |
|
|
136
|
-
| `security` | `Security` |
|
|
137
|
-
| `performance` | `Performance` |
|
|
138
|
-
| *(absent)* | `General` |
|
|
139
|
-
|
|
140
|
-
Full example: `/Payments/Transactions/Validation`
|
|
141
|
-
|
|
142
|
-
---
|
|
143
|
-
|
|
144
|
-
## `business-rules.yaml` Contract
|
|
145
|
-
|
|
146
|
-
Every rule must contain these fields. Validate before generation — report violations before writing any files.
|
|
147
|
-
|
|
148
|
-
```yaml
|
|
149
|
-
service: my-service
|
|
150
|
-
version: "1.0"
|
|
151
|
-
|
|
152
|
-
features:
|
|
153
|
-
- name: Health Check # Required. Becomes the Test Set name.
|
|
154
|
-
endpoints: # Required. Links rules to OpenAPI paths.
|
|
155
|
-
- GET /health
|
|
156
|
-
rules:
|
|
157
|
-
- id: BR-001 # Required. Stable. Never reuse a retired ID.
|
|
158
|
-
description: Service returns 200 OK # Required. Becomes xray.summary.
|
|
159
|
-
given: Service is running # Required. Precondition.
|
|
160
|
-
when: GET /health is called # Required. Action.
|
|
161
|
-
then: Response is 200 # Required. Expected outcome.
|
|
162
|
-
category: validation # Required. Controls folder placement.
|
|
163
|
-
priority: High # Required. Maps to Xray priority.
|
|
164
|
-
tags: [smoke, regression] # Optional. Used as labels.
|
|
165
|
-
requirementKeys: [] # Optional. Creates Xray coverage links.
|
|
166
|
-
skip: false # Optional. Defaults to false.
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
If `business-rules.yaml` does not exist, generate a draft from the OpenAPI spec and flag it as `DRAFT — REQUIRES QA + DEV REVIEW`.
|
|
170
|
-
|
|
171
|
-
---
|
|
172
|
-
|
|
173
|
-
## Workflow
|
|
174
|
-
|
|
175
|
-
### Step 0: Scaffold the Project
|
|
176
|
-
|
|
177
|
-
**Who:** QA Engineer (one-time)
|
|
178
|
-
**Command:** `npx xqt init`
|
|
179
|
-
|
|
180
|
-
1. Create the repo: `{ServiceName}_Automation`
|
|
181
|
-
2. Run `npx xqt init` — produces the full scaffold
|
|
182
|
-
3. Copy `.env.example` to `.env` and fill in credentials
|
|
183
|
-
4. Set up ADO variable groups:
|
|
184
|
-
- **`xray-qa-shared`** (shared across repos): `xray_client_id`, `xray_client_secret`, `JIRA_PROJECT_KEY`, `JIRA_URL`, `JIRA_API_TOKEN`, `JIRA_EMAIL`
|
|
185
|
-
- **`{ServiceName}-qa`** (per-repo): `base_url`, `gravitee_api_key`, service-specific secrets
|
|
186
|
-
|
|
187
|
-
`xqt init` is idempotent — running it again won't overwrite existing files.
|
|
188
|
-
|
|
189
|
-
### Step 1: Prepare Knowledge Artifacts
|
|
190
|
-
|
|
191
|
-
**Who:** QA Engineer + Dev Team
|
|
192
|
-
|
|
193
|
-
1. Place the OpenAPI spec at `resources/api-specs/openapi.yaml`
|
|
194
|
-
2. Create `resources/business-rules.yaml` using the contract above
|
|
195
|
-
- One feature per logical API grouping
|
|
196
|
-
- One rule per testable behaviour
|
|
197
|
-
- Every rule has `id`, `description`, `given`, `when`, `then`, `category`, `priority`
|
|
198
|
-
3. Validate: `npx xqt validate`
|
|
199
|
-
|
|
200
|
-
### Step 2: Generate `tests.json`
|
|
201
|
-
|
|
202
|
-
**Who:** AI Agent (Copilot skill)
|
|
203
|
-
**Input:** `openapi.yaml` + `business-rules.yaml`
|
|
204
|
-
**Output:** Populated `tests.json`
|
|
205
|
-
|
|
206
|
-
The AI agent reads both artifacts and produces `tests.json` using the **Deterministic Generation Rules** above. Every `business-rules.yaml` rule becomes exactly one `tests.json` entry.
|
|
207
|
-
|
|
208
|
-
- Each feature's rules are grouped under a `testSet` matching the feature name
|
|
209
|
-
- `test_id` values follow the `TC-{SERVICE_CODE}-{SCENARIO_ID}` pattern
|
|
210
|
-
- All fields derived deterministically — no creative decisions
|
|
211
|
-
|
|
212
|
-
After generation, validate: `npx xqt validate`
|
|
213
|
-
|
|
214
|
-
### Step 3: Push Tests to Xray
|
|
215
|
-
|
|
216
|
-
**Who:** QA Engineer or CI
|
|
217
|
-
**Command:** `npx xqt push-tests`
|
|
218
|
-
|
|
219
|
-
This creates/updates Xray Test issues and Test Sets in Jira:
|
|
220
|
-
- New tests → created in Xray, added to appropriate Test Set
|
|
221
|
-
- Existing tests (in `xray-mapping.json`) → updated in place
|
|
222
|
-
- Tests with `"skip": true` → excluded
|
|
223
|
-
- `xray-mapping.json` is auto-populated with the Jira issue keys
|
|
224
|
-
|
|
225
|
-
After push, `xray-mapping.json` contains the mapping:
|
|
226
|
-
```json
|
|
227
|
-
{
|
|
228
|
-
"TC-PAYMENTS-BR-001": { "key": "APIEE-1234", "id": "8765432" },
|
|
229
|
-
"TC-PAYMENTS-BR-002": { "key": "APIEE-1235", "id": "8765433" }
|
|
230
|
-
}
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
**Commit `tests.json` and `xray-mapping.json` together.**
|
|
234
|
-
|
|
235
|
-
### Step 4: Create Playwright API Tests
|
|
236
|
-
|
|
237
|
-
**Who:** AI Agent (Copilot skill — separate from XQT)
|
|
238
|
-
|
|
239
|
-
Playwright tests are created **after** `xray-mapping.json` exists, so every test can reference its real Jira key from the start.
|
|
240
|
-
|
|
241
|
-
- One `test()` call per `tests.json` entry — 1:1 mapping
|
|
242
|
-
- Test titles include the Xray key: `[APIEE-1234] Service returns 200 OK when healthy`
|
|
243
|
-
- Tests use `test.info().annotations` to link to Xray
|
|
244
|
-
- The Copilot skill reads `tests.json` and `xray-mapping.json` to generate each spec
|
|
245
|
-
|
|
246
|
-
> **Note:** XQT does not generate Playwright tests. Test code is created by a separate Copilot skill
|
|
247
|
-
> that uses this spec-driven approach, `tests.json`, and `xray-mapping.json` as its inputs.
|
|
248
|
-
|
|
249
|
-
### Step 5: Sprint Workflow — Test Plans
|
|
250
|
-
|
|
251
|
-
**Who:** QA Engineer
|
|
252
|
-
|
|
253
|
-
When entering a new sprint:
|
|
254
|
-
|
|
255
|
-
1. **Create a Test Plan:**
|
|
256
|
-
```bash
|
|
257
|
-
npx xqt create-plan --summary "Sprint 12 — Payments API Regression"
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
2. **Link relevant Test Sets** to the Test Plan in Jira
|
|
261
|
-
- Select the Test Sets containing tests relevant to this sprint's scope
|
|
262
|
-
- This makes the Test Plan a curated view of what matters for the sprint
|
|
263
|
-
|
|
264
|
-
3. **Run tests and import results:**
|
|
265
|
-
```bash
|
|
266
|
-
npx playwright test
|
|
267
|
-
npx xqt import-results --file test-results/results.json --env IOP-QA
|
|
268
|
-
```
|
|
269
|
-
Each run creates a new Test Execution linked to the Test Plan.
|
|
270
|
-
|
|
271
|
-
4. **Sprint complete:** The Test Plan in Jira shows the full execution history for the sprint.
|
|
272
|
-
|
|
273
|
-
### Step 6: CI/CD — Ongoing
|
|
274
|
-
|
|
275
|
-
Every CI pipeline run:
|
|
276
|
-
```bash
|
|
277
|
-
npx xqt validate # Schema check
|
|
278
|
-
npx playwright test # Run tests
|
|
279
|
-
npx xqt import-results --file test-results/results.json \
|
|
280
|
-
--env IOP-QA # Import to Xray
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
Results appear as new Test Executions linked to the active Test Plan.
|
|
284
|
-
|
|
285
|
-
---
|
|
286
|
-
|
|
287
|
-
## Brownfield Workflow (Updating Existing Tests)
|
|
288
|
-
|
|
289
|
-
When the OpenAPI spec or business rules change:
|
|
290
|
-
|
|
291
|
-
1. **Update `business-rules.yaml`** — add new rules, modify existing, mark removed rules with `skip: true`
|
|
292
|
-
2. **Regenerate `tests.json`** — AI agent re-derives from updated artifacts
|
|
293
|
-
- New rules → new `tests.json` entries appended
|
|
294
|
-
- Modified rules → existing entries updated field-by-field (never change `test_id`)
|
|
295
|
-
- Removed rules → `"skip": true` (never delete)
|
|
296
|
-
3. **Push changes:** `npx xqt push-tests` — creates new Xray issues, updates existing
|
|
297
|
-
4. **Update Playwright tests** — Copilot skill creates tests for new entries, updates existing
|
|
298
|
-
5. **Validate:** run the suite, import results
|
|
299
|
-
|
|
300
|
-
**Critical rule:** `xray-mapping.json` entries are never removed or overwritten for existing `test_id` values. The mapping only grows.
|
|
301
|
-
|
|
302
|
-
---
|
|
303
|
-
|
|
304
|
-
## Workflow Summary
|
|
305
|
-
|
|
306
|
-
| Step | Who | Action | Output |
|
|
307
|
-
|------|-----|--------|--------|
|
|
308
|
-
| 0 | QA Engineer | `xqt init` | Scaffolded project |
|
|
309
|
-
| 1 | QA + Dev | Prepare `openapi.yaml` + `business-rules.yaml` | Validated knowledge artifacts |
|
|
310
|
-
| 2 | AI Agent | Generate from specs | `tests.json` populated |
|
|
311
|
-
| 3 | QA / CI | `xqt push-tests` | Xray Tests + Test Sets created, `xray-mapping.json` populated |
|
|
312
|
-
| 4 | AI Agent | Create Playwright tests | `*.spec.ts` files (1:1 with `tests.json`) |
|
|
313
|
-
| 5 | QA Engineer | `xqt create-plan` + link Test Sets | Sprint Test Plan ready |
|
|
314
|
-
| 6 | CI | `playwright test` + `xqt import-results` | Test Execution in Xray |
|
|
315
|
-
|
|
316
|
-
---
|
|
317
|
-
|
|
318
|
-
## Key Principles
|
|
319
|
-
|
|
320
|
-
1. **`tests.json` is the source of truth** for test metadata — never edit tests directly in Jira
|
|
321
|
-
2. **`xray-mapping.json` is owned by XQT** — only `xqt push-tests` writes it, never edit manually
|
|
322
|
-
3. **`testId` values are permanent** — once pushed, they never change; retired rules get `"skip": true`
|
|
323
|
-
4. **Test Sets are the home for tests** — persistent groupings that live across sprints
|
|
324
|
-
5. **Test Plans are per-sprint** — create one per sprint, link relevant Test Sets
|
|
325
|
-
6. **Test Executions are ephemeral** — each CI run creates a fresh one
|
|
326
|
-
7. **1:1 mapping everywhere** — one rule → one `tests.json` entry → one Xray issue → one `test()` call
|
|
327
|
-
8. **Generation is deterministic** — same inputs always produce same outputs
|
|
328
|
-
9. **Playwright tests come last** — only created after `xray-mapping.json` exists with real Jira keys
|
|
329
|
-
10. **Never store secrets in code** — all credentials in `.env` or ADO variable groups
|
|
330
|
-
|
|
331
|
-
---
|
|
332
|
-
|
|
333
|
-
## QE Process — End-to-End
|
|
334
|
-
|
|
335
|
-
```
|
|
336
|
-
Dev team maintains openapi.yaml + business-rules.yaml
|
|
337
|
-
│
|
|
338
|
-
▼
|
|
339
|
-
AI Agent generates tests.json from both artifacts
|
|
340
|
-
(deterministic rules — no creative decisions)
|
|
341
|
-
│
|
|
342
|
-
▼
|
|
343
|
-
npx xqt validate (hard stop on any error)
|
|
344
|
-
│
|
|
345
|
-
▼
|
|
346
|
-
npx xqt push-tests
|
|
347
|
-
→ Xray Test issues created/updated
|
|
348
|
-
→ Test Sets created/updated
|
|
349
|
-
→ xray-mapping.json auto-populated
|
|
350
|
-
│
|
|
351
|
-
▼
|
|
352
|
-
AI Agent (Copilot skill) creates Playwright API tests
|
|
353
|
-
→ reads tests.json + xray-mapping.json
|
|
354
|
-
→ one spec per tests.json entry
|
|
355
|
-
→ real Jira keys in test titles from day one
|
|
356
|
-
│
|
|
357
|
-
▼
|
|
358
|
-
Sprint starts → QA creates Test Plan → links Test Sets
|
|
359
|
-
│
|
|
360
|
-
▼
|
|
361
|
-
CI runs: playwright test → xqt import-results
|
|
362
|
-
→ Test Execution created in Xray
|
|
363
|
-
→ linked to Test Plan
|
|
364
|
-
│
|
|
365
|
-
▼
|
|
366
|
-
Full traceability chain:
|
|
367
|
-
Business Rule → tests.json → Xray Test (in Test Set) → Playwright test → Test Execution (in Test Plan)
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
---
|
|
371
|
-
|
|
372
|
-
**The contract:** The OpenAPI spec defines what the API looks like. The business rules define what the API should do. `tests.json` captures both as structured test definitions. XQT syncs those definitions to Xray. Copilot writes the Playwright tests. Test Sets organise the tests permanently. Test Plans scope them to sprints. Nothing else is needed.
|