ado-sync 0.1.24 → 0.1.27
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 +240 -678
- package/dist/azure/client.d.ts +3 -0
- package/dist/azure/client.js +6 -0
- package/dist/azure/client.js.map +1 -1
- package/dist/azure/test-cases.d.ts +8 -3
- package/dist/azure/test-cases.js +406 -25
- package/dist/azure/test-cases.js.map +1 -1
- package/dist/cli.js +51 -4
- package/dist/cli.js.map +1 -1
- package/dist/config.js +111 -5
- package/dist/config.js.map +1 -1
- package/dist/parsers/csharp.d.ts +30 -0
- package/dist/parsers/csharp.js +257 -0
- package/dist/parsers/csharp.js.map +1 -0
- package/dist/parsers/gherkin.d.ts +4 -1
- package/dist/parsers/gherkin.js +19 -4
- package/dist/parsers/gherkin.js.map +1 -1
- package/dist/parsers/java.d.ts +40 -0
- package/dist/parsers/java.js +329 -0
- package/dist/parsers/java.js.map +1 -0
- package/dist/parsers/javascript.d.ts +33 -0
- package/dist/parsers/javascript.js +261 -0
- package/dist/parsers/javascript.js.map +1 -0
- package/dist/parsers/markdown.d.ts +4 -1
- package/dist/parsers/markdown.js +5 -3
- package/dist/parsers/markdown.js.map +1 -1
- package/dist/parsers/python.d.ts +34 -0
- package/dist/parsers/python.js +305 -0
- package/dist/parsers/python.js.map +1 -0
- package/dist/parsers/shared.d.ts +18 -0
- package/dist/parsers/shared.js +40 -0
- package/dist/parsers/shared.js.map +1 -1
- package/dist/sync/engine.js +114 -5
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync/publish-results.d.ts +49 -0
- package/dist/sync/publish-results.js +476 -0
- package/dist/sync/publish-results.js.map +1 -0
- package/dist/sync/writeback.d.ts +57 -1
- package/dist/sync/writeback.js +243 -0
- package/dist/sync/writeback.js.map +1 -1
- package/dist/types.d.ts +159 -2
- package/docs/advanced.md +350 -0
- package/docs/configuration.md +293 -0
- package/docs/publish-test-results.md +317 -0
- package/docs/spec-formats.md +595 -0
- package/package.json +1 -1
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# publish-test-results
|
|
2
|
+
|
|
3
|
+
Parses test result files (TRX, NUnit XML, JUnit, Cucumber JSON) and publishes them to an Azure DevOps Test Run, linking results back to Test Cases either directly by TC ID (when available in the result file) or by `AutomatedTestName` matching.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
ado-sync publish-test-results \
|
|
11
|
+
--testResult results/test-results.trx \
|
|
12
|
+
--runName "CI run #42"
|
|
13
|
+
|
|
14
|
+
# Multiple result files
|
|
15
|
+
ado-sync publish-test-results \
|
|
16
|
+
--testResult results/unit.trx \
|
|
17
|
+
--testResult results/integration.xml \
|
|
18
|
+
--testResultFormat junit
|
|
19
|
+
|
|
20
|
+
# Dry run — parse and summarise without publishing
|
|
21
|
+
ado-sync publish-test-results --testResult results/test.trx --dry-run
|
|
22
|
+
|
|
23
|
+
# Associate with a build
|
|
24
|
+
ado-sync publish-test-results \
|
|
25
|
+
--testResult results/test.trx \
|
|
26
|
+
--buildId 12345
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Options
|
|
30
|
+
|
|
31
|
+
| Option | Description |
|
|
32
|
+
|--------|-------------|
|
|
33
|
+
| `--testResult <path>` | Path to a result file. Repeatable. |
|
|
34
|
+
| `--testResultFormat <format>` | `trx` · `nunitXml` · `junit` · `cucumberJson`. Auto-detected from file extension/content when omitted. |
|
|
35
|
+
| `--runName <name>` | Name for the Test Run in Azure DevOps. Defaults to `ado-sync <ISO timestamp>`. |
|
|
36
|
+
| `--buildId <id>` | Build ID to associate with the Test Run. |
|
|
37
|
+
| `--dry-run` | Parse results and print summary without creating a run in Azure. |
|
|
38
|
+
| `--config-override` | Override config values (repeatable, same as other commands). |
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Supported formats
|
|
43
|
+
|
|
44
|
+
| Format | Extension | Auto-detected | TC ID in file? |
|
|
45
|
+
|--------|-----------|---------------|----------------|
|
|
46
|
+
| TRX (MSTest / VSTest) | `.trx` | Yes (`<TestRun>` root) | Yes — via `[TestProperty("tc","ID")]` in `TestDefinitions` |
|
|
47
|
+
| NUnit XML (native) | `.xml` | Yes (`<test-run>` root) | Yes — via `[Property("tc","ID")]` on each `test-case` |
|
|
48
|
+
| JUnit XML | `.xml` | Yes (`<testsuites>` / `<testsuite>` root) | Optional — via `<property name="tc" value="ID"/>` (see below) |
|
|
49
|
+
| Cucumber JSON | `.json` | Yes (JSON array) | Yes — via `@tc:ID` tag on scenario |
|
|
50
|
+
|
|
51
|
+
> **NUnit via TRX**: when NUnit tests are run through the VSTest adapter (`--logger trx`), `[Property]` values are **not** included in the TRX output. Use `--logger "nunit3;LogFileName=results.xml"` to get the native NUnit XML format, which does include property values.
|
|
52
|
+
|
|
53
|
+
### How TC linking works
|
|
54
|
+
|
|
55
|
+
Results are linked to Azure Test Cases in priority order:
|
|
56
|
+
|
|
57
|
+
1. **TC ID from file** (preferred) — when the result file contains a TC ID (`[TestProperty]`, `[Property]`, `<property name="tc">`, or `@tc:` tag), the result is posted with `testCase.id` set directly. This is robust to class/method renames.
|
|
58
|
+
2. **AutomatedTestName matching** (fallback) — when no TC ID is found, the result is posted with `automatedTestName` = the fully-qualified method name. Azure DevOps links it to a TC whose `AutomatedTestName` field matches. Requires `sync.markAutomated: true` on push.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Per-framework guide
|
|
63
|
+
|
|
64
|
+
### C# MSTest
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
dotnet test --logger "trx;LogFileName=results.trx"
|
|
68
|
+
ado-sync publish-test-results --testResult results/results.trx
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
TC IDs are read from `[TestProperty("tc","ID")]` embedded in the TRX — no extra config needed.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
### C# NUnit
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Use native NUnit XML (includes [Property] values)
|
|
79
|
+
dotnet test --logger "nunit3;LogFileName=results.xml"
|
|
80
|
+
ado-sync publish-test-results --testResult results/results.xml
|
|
81
|
+
|
|
82
|
+
# TRX via VSTest adapter (TC IDs NOT included — uses AutomatedTestName matching)
|
|
83
|
+
dotnet test --logger "trx;LogFileName=results.trx"
|
|
84
|
+
ado-sync publish-test-results --testResult results/results.trx
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
### Java JUnit 4 / JUnit 5 (Maven Surefire)
|
|
90
|
+
|
|
91
|
+
Maven Surefire generates JUnit XML with `classname` = FQCN and `name` = method name. ado-sync builds `automatedTestName` as `FQCN.methodName` on push, which matches the `classname.name` format in the JUnit XML automatically.
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# Run tests (Surefire writes target/surefire-reports/TEST-*.xml)
|
|
95
|
+
mvn test
|
|
96
|
+
|
|
97
|
+
# Publish — TC linking uses AutomatedTestName matching
|
|
98
|
+
ado-sync publish-test-results \
|
|
99
|
+
--testResult "target/surefire-reports/TEST-*.xml" \
|
|
100
|
+
--testResultFormat junit
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Recommended config:
|
|
104
|
+
```json
|
|
105
|
+
{ "sync": { "markAutomated": true } }
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Optional — write TC IDs into JUnit XML** for direct linking (more reliable):
|
|
109
|
+
|
|
110
|
+
Add a JUnit 5 extension or JUnit 4 rule that reads the `@Tag("tc:ID")` / `// @tc:ID` value and calls `recordProperty` to embed it into the XML. With Surefire, test properties are written as `<property>` elements inside each `<testcase>`.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
### Java TestNG
|
|
115
|
+
|
|
116
|
+
TestNG's Surefire reporter generates the same JUnit XML format. Same commands as JUnit above.
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
mvn test # or: ./gradlew test
|
|
120
|
+
|
|
121
|
+
ado-sync publish-test-results \
|
|
122
|
+
--testResult "target/surefire-reports/TEST-*.xml" \
|
|
123
|
+
--testResultFormat junit
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
### Python pytest
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# Run tests and generate JUnit XML
|
|
132
|
+
pytest --junitxml=results/junit.xml
|
|
133
|
+
|
|
134
|
+
# Publish — uses AutomatedTestName matching (classname.name from JUnit XML)
|
|
135
|
+
ado-sync publish-test-results --testResult results/junit.xml --testResultFormat junit
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Recommended config:
|
|
139
|
+
```json
|
|
140
|
+
{ "sync": { "markAutomated": true } }
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Optional — embed TC IDs into JUnit XML** for direct linking.
|
|
144
|
+
|
|
145
|
+
Add the following to your `conftest.py`:
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
# conftest.py
|
|
149
|
+
def pytest_runtest_makereport(item, call):
|
|
150
|
+
"""Write @pytest.mark.tc(N) as a JUnit XML property for ado-sync to pick up."""
|
|
151
|
+
for marker in item.iter_markers("tc"):
|
|
152
|
+
if marker.args:
|
|
153
|
+
item.user_properties.append(("tc", str(marker.args[0])))
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
With this hook, pytest writes:
|
|
157
|
+
```xml
|
|
158
|
+
<testcase name="test_foo" classname="tests.module.TestClass">
|
|
159
|
+
<properties>
|
|
160
|
+
<property name="tc" value="1041"/>
|
|
161
|
+
</properties>
|
|
162
|
+
</testcase>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
ado-sync will extract the `tc` property and link the result directly to TC 1041, without needing AutomatedTestName matching.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
### JavaScript / TypeScript — Jest
|
|
170
|
+
|
|
171
|
+
Install `jest-junit`:
|
|
172
|
+
```bash
|
|
173
|
+
npm install --save-dev jest-junit
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Run tests:
|
|
177
|
+
```bash
|
|
178
|
+
JEST_JUNIT_OUTPUT_DIR=results JEST_JUNIT_OUTPUT_NAME=junit.xml \
|
|
179
|
+
npx jest --reporters=default --reporters=jest-junit
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Publish:
|
|
183
|
+
```bash
|
|
184
|
+
ado-sync publish-test-results --testResult results/junit.xml --testResultFormat junit
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
> **TC linking for Jest**: jest-junit does not embed TC IDs in the XML. Linking uses `AutomatedTestName` matching. Set `sync.markAutomated: true` and ensure the `JEST_JUNIT_CLASSNAME` and `JEST_JUNIT_TITLE` env vars match the `automatedTestName` format stored in the TC (`{fileBasename} > {describe} > {testTitle}`).
|
|
188
|
+
>
|
|
189
|
+
> Set these env vars to align the format:
|
|
190
|
+
> ```
|
|
191
|
+
> JEST_JUNIT_CLASSNAME="{classname}" # default: suite hierarchy
|
|
192
|
+
> JEST_JUNIT_TITLE="{title}" # default: test title
|
|
193
|
+
> ```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### JavaScript / TypeScript — WebdriverIO
|
|
198
|
+
|
|
199
|
+
WebdriverIO supports JUnit XML via `@wdio/junit-reporter`:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
# Install (if not already present)
|
|
203
|
+
npm install --save-dev @wdio/junit-reporter
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Add to `wdio.conf.ts`:
|
|
207
|
+
```typescript
|
|
208
|
+
reporters: [['junit', { outputDir: './results', outputFileFormat: () => 'junit.xml' }]]
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Run tests:
|
|
212
|
+
```bash
|
|
213
|
+
npx wdio run wdio.conf.ts
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Publish:
|
|
217
|
+
```bash
|
|
218
|
+
ado-sync publish-test-results --testResult results/junit.xml --testResultFormat junit
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
### Gherkin / Cucumber (JS)
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
# Run with Cucumber JSON reporter
|
|
227
|
+
npx cucumber-js --format json:results/cucumber.json
|
|
228
|
+
|
|
229
|
+
# Publish — TC IDs are read from @tc:ID tags on each scenario
|
|
230
|
+
ado-sync publish-test-results --testResult results/cucumber.json
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
TC IDs from `@tc:12345` tags on scenarios are extracted directly from the JSON — no AutomatedTestName matching needed.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
| Framework | Result format | TC ID in file | Fallback |
|
|
238
|
+
|-----------|---------------|---------------|---------|
|
|
239
|
+
| C# MSTest | TRX | ✅ `[TestProperty("tc","ID")]` | — |
|
|
240
|
+
| C# NUnit | NUnit XML | ✅ `[Property("tc","ID")]` | — |
|
|
241
|
+
| Java JUnit 4/5 | JUnit XML | ⚠️ optional (see above) | AutomatedTestName |
|
|
242
|
+
| Java TestNG | JUnit XML | ⚠️ optional (see above) | AutomatedTestName |
|
|
243
|
+
| Python pytest | JUnit XML | ⚠️ optional (conftest.py) | AutomatedTestName |
|
|
244
|
+
| Jest | JUnit XML | ❌ | AutomatedTestName |
|
|
245
|
+
| WebdriverIO | JUnit XML | ❌ | AutomatedTestName |
|
|
246
|
+
| Cucumber JS | Cucumber JSON | ✅ `@tc:ID` tag | — |
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Outcome mapping
|
|
251
|
+
|
|
252
|
+
| Source outcome | Azure outcome |
|
|
253
|
+
|----------------|---------------|
|
|
254
|
+
| `passed` / `pass` / `success` | `Passed` |
|
|
255
|
+
| `failed` / `fail` / `failure` / `error` | `Failed` |
|
|
256
|
+
| `skipped` / `ignored` / `pending` / `notExecuted` | `NotExecuted` |
|
|
257
|
+
| `inconclusive` | `Inconclusive` (or override with `treatInconclusiveAs`) |
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Configuration
|
|
262
|
+
|
|
263
|
+
Results can also be configured in the config file under `publishTestResults`:
|
|
264
|
+
|
|
265
|
+
```json
|
|
266
|
+
{
|
|
267
|
+
"publishTestResults": {
|
|
268
|
+
"testResult": {
|
|
269
|
+
"sources": [
|
|
270
|
+
{ "value": "results/unit.trx", "format": "trx" },
|
|
271
|
+
{ "value": "results/integration.xml", "format": "junit" }
|
|
272
|
+
]
|
|
273
|
+
},
|
|
274
|
+
"treatInconclusiveAs": "Failed",
|
|
275
|
+
"testRunSettings": {
|
|
276
|
+
"name": "My CI Run",
|
|
277
|
+
"comment": "Automated sync run",
|
|
278
|
+
"runType": "Automated"
|
|
279
|
+
},
|
|
280
|
+
"testResultSettings": {
|
|
281
|
+
"comment": "Published by ado-sync"
|
|
282
|
+
},
|
|
283
|
+
"testConfiguration": {
|
|
284
|
+
"name": "Default"
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### `publishTestResults` fields
|
|
291
|
+
|
|
292
|
+
| Field | Description |
|
|
293
|
+
|-------|-------------|
|
|
294
|
+
| `testResult.sources` | Array of `{ value, format }` objects. `value` is a path relative to config dir. |
|
|
295
|
+
| `treatInconclusiveAs` | Override inconclusive outcome. e.g. `"Failed"` or `"NotExecuted"`. |
|
|
296
|
+
| `flakyTestOutcome` | How to handle flaky tests: `"lastAttemptOutcome"` *(default)* · `"firstAttemptOutcome"` · `"worstOutcome"`. |
|
|
297
|
+
| `testConfiguration.name` | Name of the Azure test configuration to associate. |
|
|
298
|
+
| `testConfiguration.id` | ID of the Azure test configuration. |
|
|
299
|
+
| `testRunSettings.name` | Name for the Test Run. |
|
|
300
|
+
| `testRunSettings.comment` | Comment attached to the Test Run. |
|
|
301
|
+
| `testRunSettings.runType` | `"Automated"` *(default)* · `"Manual"`. |
|
|
302
|
+
| `testResultSettings.comment` | Comment applied to every test result. |
|
|
303
|
+
| `publishAttachmentsForPassingTests` | `"none"` *(default)* · `"files"` · `"all"`. |
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Output
|
|
308
|
+
|
|
309
|
+
```
|
|
310
|
+
ado-sync publish-test-results
|
|
311
|
+
Config: ado-sync.json
|
|
312
|
+
|
|
313
|
+
Total results: 42
|
|
314
|
+
38 passed 3 failed 1 other
|
|
315
|
+
Run ID: 9876
|
|
316
|
+
URL: https://dev.azure.com/my-org/MyProject/_testManagement/runs?runId=9876
|
|
317
|
+
```
|