xcodebuild-axi 0.1.10 → 0.1.12

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/CHANGELOG.md CHANGED
@@ -4,6 +4,161 @@ Notable changes to `xcodebuild-axi`. Versions follow
4
4
  [semver](https://semver.org/); the format follows
5
5
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
 
7
+ ## [Unreleased]
8
+
9
+ ## [0.1.12] - 2026-09-21
10
+
11
+ ### Added
12
+
13
+ - **`sim` sets up the state a UI test needs.** `privacy`, `push`,
14
+ `status-bar` and `ui` — the last four simctl subcommands worth wrapping.
15
+
16
+ `sim privacy "iPhone 17 Pro" grant photos` answers a permission prompt
17
+ before it appears, which is the difference between a UI test that runs
18
+ unattended and one that waits for a tap. The bundle id is optional here too,
19
+ and `reset` is the one action that takes no app at all.
20
+
21
+ `sim push "iPhone 17 Pro" --message "Your order shipped"` writes the `aps`
22
+ dictionary simctl demands and sends it, rather than making the caller keep a
23
+ JSON file around for one line of text. A payload path still works, in either
24
+ order with the bundle id. simctl delivers a push addressed to an app that is
25
+ not installed and exits 0 — indistinguishable from a notification the app
26
+ ignored — so the app is checked first and the silence becomes a sentence.
27
+
28
+ `sim status-bar "iPhone 17 Pro" pin` freezes the clock at 9:41 with full
29
+ signal and a full battery, so two screenshots differ only where the app
30
+ does; `--time`, `--battery` and `--bars` override one piece at a time, and
31
+ `clear` hands the status bar back. Read back, simctl reports its overrides
32
+ as enum ordinals (`Battery State: 2`) and prints the words only inside its
33
+ own `--help`; every value was checked against what it accepts, so the
34
+ report reads in the same vocabulary the flags are written in.
35
+
36
+ `sim ui "iPhone 17 Pro"` reports appearance, contrast and content size
37
+ together, and `sim ui "iPhone 17 Pro" dark` is shorthand for setting the
38
+ one of the three anyone asks for.
39
+
40
+ That closes the coverage map: every leaf of xcodebuild, `xcresulttool`,
41
+ `xccov` and `simctl` is now either reached by a command or declined on the
42
+ record, with nothing left marked missing.
43
+
44
+ - **`sim` can run the app a build just produced.** Five simctl subcommands:
45
+ `sim apps`, `install`, `launch`, `terminate` and `uninstall`.
46
+
47
+ The app is optional in all four mutations. Without one, it is worked out
48
+ from the project in the current directory — `-showBuildSettings` against the
49
+ simulator's own destination answers both the `.app` path and the bundle id,
50
+ and answers them for the right platform, which a hand-typed DerivedData path
51
+ routinely does not. That resolution is most of the point: `build`, then
52
+ `sim install "iPhone 17 Pro"`, then `sim launch "iPhone 17 Pro"`, with
53
+ nothing pasted between the steps.
54
+
55
+ The mutations are idempotent where simctl's are not: terminating an app that
56
+ is not running and uninstalling one that is not installed are the state
57
+ being asked for, so both are a no-op at exit 0. `sim apps` filters out the
58
+ four dozen apps Apple ships — a typical device answers with 46 apps of which
59
+ two are the developer's — and `--system` puts them back.
60
+
61
+ `simctl listapps` prints an old-style NeXTSTEP plist rather than JSON, and
62
+ offers no `-j`; it goes through `plutil` to become readable.
63
+
64
+ - **`sim` makes devices, unmakes them, and shows what one looks like.**
65
+ `create`, `delete`, `screenshot`, `video` and `open`.
66
+
67
+ `sim create "Test iPhone" "iPhone 17 Pro"` takes the model by the name
68
+ `sim list` prints rather than by the
69
+ `com.apple.CoreSimulator.SimDeviceType.iPhone-17-Pro` identifier simctl
70
+ documents, and an unknown model comes back with the models that nearly
71
+ match. `--runtime` picks the OS.
72
+
73
+ `sim delete <name>` removes one and `--unavailable` removes every device
74
+ whose runtime is gone, which is the safe form of reclaiming disk. Deleting
75
+ _everything_ needs `--yes` on top of `--all`: a simulator is gigabytes of
76
+ state and recreating it is not the same device, so it gets the same guard
77
+ `migrate --format` has.
78
+
79
+ `sim screenshot` and `sim video` write to `~/Library/Caches` and report the
80
+ path and size. `simctl io recordVideo` records until it is sent SIGINT,
81
+ which is a contract for a person at a terminal — an agent cannot press
82
+ Control-C inside its own subprocess — so `--seconds` sets the length and the
83
+ interrupt is this tool's job. The clock starts when simctl says
84
+ `Recording started` rather than at spawn, so a slow start does not eat the
85
+ recording.
86
+
87
+ `sim open <url>` is how a deep link gets tested.
88
+
89
+ ## [0.1.11] - 2026-09-21
90
+
91
+ ### Added
92
+
93
+ - **`result --export <what>` gets files out of a bundle**: `attachments`,
94
+ `diagnostics`, `metrics`, or `evaluations`. A UI test's screenshots, the
95
+ diagnostics report `test --diagnostics` collects, and the CSVs behind a
96
+ performance measurement were all in the bundle and reachable only by shelling
97
+ out to `xcresulttool`.
98
+
99
+ It writes under `~/Library/Caches/xcodebuild-axi/exports/` by default, or
100
+ wherever `--to` says — never into the working tree, so asking what is in a CI
101
+ artifact cannot dirty the checkout it sits in. `--test`, `--filter '*.png'`
102
+ and `--failures` narrow what comes out, and each is **refused** where it does
103
+ not apply rather than ignored: a diagnostics report covers the whole run, so
104
+ `--test` beside it would answer a different question than the one asked.
105
+
106
+ The report is what landed and where, with each exported file tied back to the
107
+ test that produced it — a screenshot's filename is a UUID, and the manifest
108
+ is the only thing that makes it findable. `xcresulttool` narrates an
109
+ attachment export with one "Skipped export for <test>: no matching
110
+ attachments" per test, which is dropped.
111
+
112
+ - **`result --against <baseline.xcresult>`** answers the question CI actually
113
+ asks — not "did this run fail" but "did it fail in a way the last one did
114
+ not". It reports the counts on both sides and their direction
115
+ (`failures: 0 → 1 (+1 -0)`), then the tests that newly fail, the ones that
116
+ now pass, the ones added and removed, and any new warning. A failure the
117
+ baseline did not have is listed first, because it is the only part of a
118
+ comparison that stops a merge.
119
+
120
+ Two bundles with nothing in common — a build against a test run — get an
121
+ explicit answer saying so. `xcresulttool` prints a bare `null` there, which
122
+ is otherwise indistinguishable from a clean comparison.
123
+
124
+ - **`result <a> <b> [...] --merge`** combines the bundles of a sharded test run
125
+ into one, which is the only way that run gets a single verdict. The merged
126
+ bundle is read back and reported from, rather than described from its
127
+ inputs. It lands under `~/Library/Caches` unless `--to` says otherwise, and a
128
+ `--to` that already exists is refused rather than written over — the bundle
129
+ under our own cache directory is ours to clear, one the caller named is not.
130
+
131
+ With these two, **`xcresulttool` coverage is 81% of its leaves** and every
132
+ remaining one is deprecated by Xcode or superseded here.
133
+
134
+ - **`coverage` sees everything `xccov` sees.** Five leaves, and the command's
135
+ path argument now also takes an `.xccovreport` or an `.xccovarchive`:
136
+
137
+ - `--functions <file>` is per-function coverage, which is where an uncovered
138
+ branch finally gets a name. A file at 60% says a test is missing; it does
139
+ not say which one.
140
+ - `--lines <file>` is how many times each line ran, read out of the archive
141
+ rather than the report. Consecutive lines that never ran collapse into one
142
+ range — a 400-line file was 400 rows to find the eight that matter.
143
+ - `--against <path>` answers "did coverage drop" from two bundles this tool
144
+ wrote, reporting which way it moved overall and then per file, worst
145
+ first.
146
+ - `--merge` combines the coverage of a sharded run. `xccov merge` takes
147
+ report/archive **pairs** rather than result bundles, so each bundle is
148
+ unpacked with `xcresulttool export coverage` first — that two-step is the
149
+ reason merging coverage across shards is something people give up on.
150
+
151
+ With them, **`xccov` coverage is 100%** and companion coverage overall is
152
+ 43.7%.
153
+
154
+ ### Fixed
155
+
156
+ - `xccov`'s refusals are no longer wrapped in NSError. A bad path came back as
157
+ `Error: Error Domain=XCCovErrorDomain Code=0 "Failed to load result bundle"
158
+ UserInfo={NSLocalizedDescription=Failed to load result bundle,
159
+ NSUnderlyingError=0x… {…}}` — 400 characters around a five-word answer that
160
+ was already in there.
161
+
7
162
  ## [0.1.10] - 2026-09-21
8
163
 
9
164
  ### Added
@@ -370,7 +525,9 @@ First release.
370
525
  - 100% of the 117 options `xcodebuild -help` lists are covered, declared in
371
526
  `src/surface.ts` and checked against the installed Xcode in CI.
372
527
 
373
- [unreleased]: https://github.com/alexrrouse/xcodebuild-axi/compare/v0.1.10...HEAD
528
+ [unreleased]: https://github.com/alexrrouse/xcodebuild-axi/compare/v0.1.12...HEAD
529
+ [0.1.12]: https://github.com/alexrrouse/xcodebuild-axi/compare/v0.1.11...v0.1.12
530
+ [0.1.11]: https://github.com/alexrrouse/xcodebuild-axi/compare/v0.1.10...v0.1.11
374
531
  [0.1.10]: https://github.com/alexrrouse/xcodebuild-axi/compare/v0.1.9...v0.1.10
375
532
  [0.1.9]: https://github.com/alexrrouse/xcodebuild-axi/compare/v0.1.8...v0.1.9
376
533
  [0.1.8]: https://github.com/alexrrouse/xcodebuild-axi/compare/v0.1.7...v0.1.8
package/README.md CHANGED
@@ -204,44 +204,13 @@ The one action left out is `installsrc` — it copies sources into `SRCROOT` as
204
204
 
205
205
  ### Companion tools
206
206
 
207
- `xcresulttool`, `xccov` and `simctl` are not xcodebuild, so they are not in the number above — but this tool wraps all three, and an agent that has to shell out to one directly has dropped back down. **28.2% of 71 leaves**, counted the same way:
207
+ `xcresulttool`, `xccov` and `simctl` are not xcodebuild, so they are not in the number above — but this tool wraps all three, and an agent that has to shell out to one directly has dropped back down. **62% of 71 leaves**, counted the same way:
208
208
 
209
209
  | Tool | Leaves | Covered |
210
210
  | -------------- | ------ | ---------- |
211
- | `xcresulttool` | 21 | 11 (52.4%) |
212
- | `xccov` | 9 | 4 (44.4%) |
213
- | `simctl` | 41 | 5 (12.2%) |
214
-
215
- ### Still open
216
-
217
- 24 leaves are known gaps rather than decisions — each one a reason someone would still reach for the raw tool:
218
-
219
- | Leaf | Unreachable from | What that costs |
220
- | ------------------------------------------ | ---------------- | --------------------------------------------------------------------------- |
221
- | `xcresulttool export diagnostics` | `result` | `test --diagnostics` collects a diagnostics report that cannot be extracted |
222
- | `xcresulttool export attachments` | `result` | UI test screenshots and attachments cannot be got out of the bundle |
223
- | `xcresulttool export metrics` | `result` | performance measurements cannot be exported as CSV |
224
- | `xcresulttool export evaluations` | `result` | evaluation attachments cannot be exported |
225
- | `xcresulttool compare` | `result` | two runs cannot be diffed, which is the question CI asks most |
226
- | `xcresulttool merge` | `result` | the bundles of a sharded test run cannot be combined |
227
- | `xccov view --report --functions-for-file` | `coverage` | coverage stops at the file, so the uncovered function has no name |
228
- | `xccov view --archive` | `coverage` | a standalone .xccovarchive cannot be read, only a result bundle |
229
- | `xccov view --file` | `coverage` | the per-line coverage of one file cannot be printed |
230
- | `xccov diff` | `coverage` | 'did coverage drop' cannot be answered from two bundles this tool wrote |
231
- | `xccov merge` | `coverage` | the coverage of a sharded run cannot be combined |
232
- | `simctl install` | `sim` | a built .app cannot be put on the simulator it was built for |
233
- | `simctl launch` | `sim` | the app a build just produced cannot be run |
234
- | `simctl terminate` | `?` | a running app cannot be stopped |
235
- | `simctl uninstall` | `?` | an installed app cannot be removed |
236
- | `simctl listapps` | `sim` | what is installed on a simulator cannot be listed |
237
- | `simctl create` | `?` | a missing device cannot be created |
238
- | `simctl delete` | `sim` | stale devices cannot be reclaimed, and they cost gigabytes |
239
- | `simctl io` | `sim` | a screenshot of a failing UI cannot be taken |
240
- | `simctl openurl` | `sim` | a deep link cannot be opened, which is how deep links are tested |
241
- | `simctl privacy` | `sim` | a permission prompt cannot be granted ahead of a UI test |
242
- | `simctl push` | `sim` | a push notification cannot be simulated |
243
- | `simctl status_bar` | `sim` | the status bar cannot be pinned, which screenshot tests need |
244
- | `simctl ui` | `sim` | dark mode and content size cannot be set for a test run |
211
+ | `xcresulttool` | 21 | 17 (81%) |
212
+ | `xccov` | 9 | 9 (100%) |
213
+ | `simctl` | 41 | 18 (43.9%) |
245
214
 
246
215
  The denominator is read from `xcodebuild -help` rather than hand-maintained, and this table is written against **Xcode 27.0** — the option list moves between releases. `npm run coverage:check` fails on that Xcode if an option here is unclassified or has been dropped, and reports the difference without failing on any other.
247
216
 
@@ -1,3 +1,14 @@
1
- export declare const COVERAGE_HELP = "usage: xcodebuild-axi coverage <path.xcresult> [flags]\nReads code coverage out of a result bundle \u2014 one percentage per target, not the\nthousands of per-file lines xccov prints by default.\nflags[4]:\n --files list per-file coverage as well as per-target\n --target <name> only this target\n --below <percent> only files under this coverage, e.g. --below 50\n --max <n> rows to list before summarizing the rest (default: 25)\nnote:\n Coverage has to have been collected. Run the tests with\n `xcodebuild-axi test --coverage` if the bundle has none.\nexamples:\n xcodebuild-axi coverage ~/Library/Caches/xcodebuild-axi/MyApps-1a2b3c4d/MyApp-test.xcresult\n xcodebuild-axi coverage build/MyApp.xcresult --files --below 50\n";
2
- export declare const COVERAGE_FLAGS: readonly ["--files", "--target", "--below", "--max"];
1
+ import { type CoverageLine } from "../xccov.js";
2
+ export declare const COVERAGE_HELP = "usage: xcodebuild-axi coverage <path> [flags]\nReads code coverage out of a result bundle \u2014 one percentage per target, not the\nthousands of per-file lines xccov prints by default. The path can also be an\n.xccovreport or .xccovarchive.\nflags[9]:\n --files list per-file coverage as well as per-target\n --target <name> only this target\n --below <percent> only files under this coverage, e.g. --below 50\n --functions <file> per-function coverage for one file, so an uncovered\n branch has a name\n --lines <file> how many times each line of one file ran\n --against <path> compare coverage with an earlier run: what moved, and\n which files went with it\n --merge combine the coverage of two or more runs into one report\n --to <path> where --merge writes (default: under ~/Library/Caches)\n --max <n> rows to list before summarizing the rest (default: 25)\nnote:\n Coverage has to have been collected. Run the tests with\n `xcodebuild-axi test --coverage` if the bundle has none.\n\n --lines reads the archive rather than the report: the report knows what\n percentage of a file ran, the archive knows how many times each line did.\nexamples:\n xcodebuild-axi coverage ~/Library/Caches/xcodebuild-axi/MyApps-1a2b3c4d/MyApp-test.xcresult\n xcodebuild-axi coverage build/MyApp.xcresult --files --below 50\n xcodebuild-axi coverage build/MyApp.xcresult --functions Checkout.swift\n xcodebuild-axi coverage build/MyApp.xcresult --against build/baseline.xcresult\n";
3
+ export declare const COVERAGE_FLAGS: readonly ["--files", "--target", "--below", "--functions", "--lines", "--against", "--merge", "--to", "--max"];
3
4
  export declare function coverageCommand(args: string[]): Promise<string>;
5
+ /** Consecutive lines that never ran, as ranges rather than one row each. */
6
+ export declare function uncoveredRanges(lines: CoverageLine[]): Array<Record<string, unknown>>;
7
+ /**
8
+ * Which way coverage moved, in words.
9
+ *
10
+ * Words rather than a signed percentage because TOON quotes any scalar that
11
+ * starts with `-`, and `"-2.1%"` costs more in quotes than `down 2.1%` costs
12
+ * in letters.
13
+ */
14
+ export declare function movement(delta: number): string;
@@ -1,31 +1,59 @@
1
- import { resolve } from "node:path";
1
+ import { existsSync, mkdirSync, rmSync } from "node:fs";
2
+ import { dirname, resolve } from "node:path";
2
3
  import { AxiError } from "../errors.js";
3
- import { percent, readCoverage } from "../xccov.js";
4
+ import { coverageSource, mergeCoverage, percent, readArchiveFiles, readCoverage, readCoverageDiff, readFileLines, readFunctions, } from "../xccov.js";
4
5
  import { relativize } from "../xcresult.js";
6
+ import { mergedCoveragePath } from "../xcodebuild.js";
5
7
  import { renderFields, renderHelp, renderList, renderOutput, tildePath, } from "../toon.js";
6
8
  import { getFlag, getIntFlag, hasFlag, positionals, rejectUnknownFlags, } from "../args.js";
7
- export const COVERAGE_HELP = `usage: xcodebuild-axi coverage <path.xcresult> [flags]
9
+ export const COVERAGE_HELP = `usage: xcodebuild-axi coverage <path> [flags]
8
10
  Reads code coverage out of a result bundle — one percentage per target, not the
9
- thousands of per-file lines xccov prints by default.
10
- flags[4]:
11
+ thousands of per-file lines xccov prints by default. The path can also be an
12
+ .xccovreport or .xccovarchive.
13
+ flags[9]:
11
14
  --files list per-file coverage as well as per-target
12
15
  --target <name> only this target
13
16
  --below <percent> only files under this coverage, e.g. --below 50
17
+ --functions <file> per-function coverage for one file, so an uncovered
18
+ branch has a name
19
+ --lines <file> how many times each line of one file ran
20
+ --against <path> compare coverage with an earlier run: what moved, and
21
+ which files went with it
22
+ --merge combine the coverage of two or more runs into one report
23
+ --to <path> where --merge writes (default: under ~/Library/Caches)
14
24
  --max <n> rows to list before summarizing the rest (default: 25)
15
25
  note:
16
26
  Coverage has to have been collected. Run the tests with
17
27
  \`xcodebuild-axi test --coverage\` if the bundle has none.
28
+
29
+ --lines reads the archive rather than the report: the report knows what
30
+ percentage of a file ran, the archive knows how many times each line did.
18
31
  examples:
19
32
  xcodebuild-axi coverage ~/Library/Caches/xcodebuild-axi/MyApps-1a2b3c4d/MyApp-test.xcresult
20
33
  xcodebuild-axi coverage build/MyApp.xcresult --files --below 50
34
+ xcodebuild-axi coverage build/MyApp.xcresult --functions Checkout.swift
35
+ xcodebuild-axi coverage build/MyApp.xcresult --against build/baseline.xcresult
21
36
  `;
22
37
  export const COVERAGE_FLAGS = [
23
38
  "--files",
24
39
  "--target",
25
40
  "--below",
41
+ "--functions",
42
+ "--lines",
43
+ "--against",
44
+ "--merge",
45
+ "--to",
46
+ "--max",
47
+ ];
48
+ const VALUE_FLAGS = [
49
+ "--target",
50
+ "--below",
51
+ "--functions",
52
+ "--lines",
53
+ "--against",
54
+ "--to",
26
55
  "--max",
27
56
  ];
28
- const VALUE_FLAGS = ["--target", "--below", "--max"];
29
57
  export async function coverageCommand(args) {
30
58
  rejectUnknownFlags(args, "coverage", COVERAGE_FLAGS, VALUE_FLAGS);
31
59
  const [rawPath] = positionals(args, VALUE_FLAGS);
@@ -38,6 +66,14 @@ export async function coverageCommand(args) {
38
66
  const path = resolve(expandTilde(rawPath));
39
67
  const below = getIntFlag(args, "--below");
40
68
  const max = getIntFlag(args, "--max") ?? 25;
69
+ const mode = soleMode(args);
70
+ if (mode)
71
+ return readMode(mode, path, args, max);
72
+ // An archive holds raw execution counts and no report at all, so the
73
+ // percentages the default view is made of do not exist for one. What it can
74
+ // answer is which files it covers, which is also what --lines takes.
75
+ if (coverageSource(path) === "archive")
76
+ return reportArchive(path, max);
41
77
  const targetFilter = getFlag(args, "--target")?.toLowerCase();
42
78
  // A --below filter is meaningless without the files it filters, so imply it
43
79
  // rather than returning an empty list the agent has to debug.
@@ -100,7 +136,7 @@ export async function coverageCommand(args) {
100
136
  : "files", shown));
101
137
  }
102
138
  }
103
- blocks.push(renderFields({ bundle: tildePath(path) }));
139
+ blocks.push(renderFields(sourceField(path)));
104
140
  const hints = [];
105
141
  if (!wantFiles) {
106
142
  hints.push(`Run \`xcodebuild-axi coverage ${rawPath} --files\` for per-file coverage`);
@@ -109,6 +145,277 @@ export async function coverageCommand(args) {
109
145
  blocks.push(renderHelp(hints));
110
146
  return renderOutput(blocks);
111
147
  }
148
+ /**
149
+ * Name the path by what it is. A `.xccovreport` reported as `bundle:` is a
150
+ * path the next call cannot reuse the same way.
151
+ */
152
+ function sourceField(path) {
153
+ const kind = coverageSource(path);
154
+ return { [kind]: tildePath(path) };
155
+ }
156
+ /** What an .xccovarchive can answer on its own: which files it holds. */
157
+ async function reportArchive(path, max) {
158
+ const files = await readArchiveFiles(path);
159
+ const shown = files.slice(0, max).map((file) => ({ file: relativize(file) }));
160
+ return renderOutput([
161
+ renderFields({ archive: tildePath(path), files: files.length }),
162
+ files.length > 0
163
+ ? renderList(files.length > shown.length
164
+ ? `files (${shown.length} of ${files.length})`
165
+ : "files", shown)
166
+ : renderFields({ files: "none — this archive holds no coverage" }),
167
+ renderHelp([
168
+ `Run \`xcodebuild-axi coverage ${tildePath(path)} --lines <file>\` for the lines that never ran`,
169
+ ]),
170
+ ]);
171
+ }
172
+ /** The one coverage question this invocation is for, if not the default. */
173
+ const MODES = ["--functions", "--lines", "--against", "--merge"];
174
+ function soleMode(args) {
175
+ const asked = MODES.filter((mode) => args.includes(mode));
176
+ if (asked.length > 1) {
177
+ throw new AxiError(`${asked.join(" and ")} ask different questions — pass one`, "VALIDATION_ERROR", [`each is its own read of the coverage data: ${MODES.join(", ")}`]);
178
+ }
179
+ return asked[0];
180
+ }
181
+ async function readMode(mode, path, args, max) {
182
+ switch (mode) {
183
+ case "--functions":
184
+ return reportFunctions(path, requireValue(args, "--functions"), max);
185
+ case "--lines":
186
+ return reportLines(path, requireValue(args, "--lines"), max);
187
+ case "--against":
188
+ return reportDiff(path, resolve(expandTilde(requireValue(args, "--against"))), max);
189
+ case "--merge":
190
+ return runMerge(path, args, max);
191
+ }
192
+ }
193
+ function requireValue(args, flag) {
194
+ const value = getFlag(args, flag);
195
+ if (value === undefined) {
196
+ throw new AxiError(`${flag} needs a value`, "VALIDATION_ERROR", [
197
+ `xcodebuild-axi coverage <path> ${flag} <value>`,
198
+ ]);
199
+ }
200
+ return value;
201
+ }
202
+ /**
203
+ * Per-function coverage, which is where an uncovered branch gets a name.
204
+ *
205
+ * A file at 60% says a test is missing; it does not say which one. The
206
+ * function list does, and it is sorted with the least covered first because
207
+ * that is the row someone is looking for.
208
+ */
209
+ async function reportFunctions(path, file, max) {
210
+ const found = await readFunctions(path, file);
211
+ const functions = found.flatMap((entry) => entry.functions);
212
+ if (functions.length === 0) {
213
+ return renderOutput([
214
+ renderFields({
215
+ functions: `no coverage recorded for a file named '${file}'`,
216
+ }),
217
+ renderFields(sourceField(path)),
218
+ renderHelp([
219
+ `Run \`xcodebuild-axi coverage ${tildePath(path)} --files\` to see which files the report covers`,
220
+ "The name is matched against the path the file had when the report was written",
221
+ ]),
222
+ ]);
223
+ }
224
+ const sorted = functions
225
+ .slice()
226
+ .sort((a, b) => a.lineCoverage - b.lineCoverage);
227
+ const shown = sorted.slice(0, max).map(functionRow);
228
+ return renderOutput([
229
+ renderFields({
230
+ file: relativize(found[0]?.file ?? file),
231
+ functions: functions.length,
232
+ uncovered: functions.filter((fn) => fn.executionCount === 0).length,
233
+ }),
234
+ renderList(sorted.length > shown.length
235
+ ? `functions (${shown.length} of ${sorted.length})`
236
+ : "functions", shown),
237
+ renderFields(sourceField(path)),
238
+ ]);
239
+ }
240
+ function functionRow(fn) {
241
+ return {
242
+ function: fn.name,
243
+ line: fn.lineNumber,
244
+ coverage: percent(fn.lineCoverage),
245
+ lines: `${fn.coveredLines}/${fn.executableLines}`,
246
+ runs: fn.executionCount,
247
+ };
248
+ }
249
+ /**
250
+ * Per-line execution counts, reported as the ranges that did not run.
251
+ *
252
+ * Printing one row per line is the thing `xccov` already does and the thing
253
+ * nobody can read: a 400-line file is 400 rows to find the eight that matter.
254
+ * Consecutive uncovered lines collapse into a range instead.
255
+ */
256
+ async function reportLines(path, file, max) {
257
+ const lines = await readFileLines(path, file).catch(async (error) => {
258
+ // xccov answers an unknown file with a load failure rather than a list, so
259
+ // the list is what the refusal carries.
260
+ const candidates = await readArchiveFiles(path).catch(() => []);
261
+ if (candidates.length === 0)
262
+ throw error;
263
+ const near = candidates.filter((candidate) => candidate.includes(file));
264
+ throw new AxiError(`No coverage recorded for '${file}'`, "VALIDATION_ERROR", near.length > 0
265
+ ? [`did you mean: ${near.slice(0, 5).join(", ")}`]
266
+ : [
267
+ `Run \`xcodebuild-axi coverage ${tildePath(path)} --files\` to see the files this archive holds`,
268
+ ]);
269
+ });
270
+ const executable = lines.filter((line) => line.isExecutable);
271
+ const covered = executable.filter((line) => line.executionCount > 0).length;
272
+ const gaps = uncoveredRanges(executable);
273
+ const shown = gaps.slice(0, max);
274
+ return renderOutput([
275
+ renderFields({
276
+ file: relativize(file),
277
+ coverage: percent(executable.length > 0 ? covered / executable.length : 0),
278
+ lines: `${covered} of ${executable.length} covered`,
279
+ }),
280
+ gaps.length === 0
281
+ ? renderFields({ uncovered: "none — every executable line ran" })
282
+ : renderList(gaps.length > shown.length
283
+ ? `uncovered (${shown.length} of ${gaps.length})`
284
+ : "uncovered", shown),
285
+ renderFields(sourceField(path)),
286
+ ]);
287
+ }
288
+ /** Consecutive lines that never ran, as ranges rather than one row each. */
289
+ export function uncoveredRanges(lines) {
290
+ const ranges = [];
291
+ for (const line of lines) {
292
+ if (line.executionCount > 0)
293
+ continue;
294
+ const last = ranges[ranges.length - 1];
295
+ if (last && line.line === last.to + 1)
296
+ last.to = line.line;
297
+ else
298
+ ranges.push({ from: line.line, to: line.line });
299
+ }
300
+ return ranges.map((range) => ({
301
+ lines: range.from === range.to ? `${range.from}` : `${range.from}-${range.to}`,
302
+ count: range.to - range.from + 1,
303
+ }));
304
+ }
305
+ /**
306
+ * `--against`, which answers "did coverage drop" without a spreadsheet.
307
+ *
308
+ * The headline is the delta, because a coverage check in CI is a comparison
309
+ * rather than a threshold most of the time.
310
+ */
311
+ async function reportDiff(path, baseline, max) {
312
+ // xccov's argument order is before, after; the bundle being asked about is
313
+ // the after, so the baseline goes first.
314
+ const diff = await readCoverageDiff(baseline, path);
315
+ const overall = diff.lineCoverageDelta ?? {};
316
+ const blocks = [
317
+ renderFields({
318
+ coverage: movement(overall.lineCoverageDelta ?? 0),
319
+ covered_lines: overall.coveredLinesDelta ?? 0,
320
+ executable_lines: overall.executableLinesDelta ?? 0,
321
+ }),
322
+ ];
323
+ // Sorted on the number and rendered afterwards: "down 45.5%" does not
324
+ // compare as a number, and the biggest drop is the row being looked for.
325
+ const moved = (diff.targetDeltas ?? [])
326
+ .flatMap((target) => (target.fileDeltas ?? []).map((file) => ({
327
+ target: target.name ?? "",
328
+ file: relativize(file.documentLocation ?? ""),
329
+ delta: file.lineCoverageDelta?.lineCoverageDelta ?? 0,
330
+ lines: file.lineCoverageDelta?.coveredLinesDelta ?? 0,
331
+ })))
332
+ .sort((a, b) => a.delta - b.delta);
333
+ if (moved.length > 0) {
334
+ const shown = moved.slice(0, max).map(({ target, file, delta, lines }) => ({
335
+ target,
336
+ file,
337
+ coverage: movement(delta),
338
+ lines,
339
+ }));
340
+ blocks.push(renderList(moved.length > shown.length
341
+ ? `files (${shown.length} of ${moved.length})`
342
+ : "files", shown));
343
+ }
344
+ const added = namesOf(diff, "addedFiles");
345
+ const removed = namesOf(diff, "removedFiles");
346
+ if (added.length > 0)
347
+ blocks.push(renderFields({ added_files: added }));
348
+ if (removed.length > 0)
349
+ blocks.push(renderFields({ removed_files: removed }));
350
+ if (blocks.length === 1 && moved.length === 0) {
351
+ blocks.push(renderFields({ difference: "none — coverage matches the baseline" }));
352
+ }
353
+ return renderOutput([
354
+ ...blocks,
355
+ renderFields({ baseline: tildePath(baseline), ...sourceField(path) }),
356
+ ]);
357
+ }
358
+ function namesOf(diff, key) {
359
+ return (diff.targetDeltas ?? []).flatMap((target) => (target[key] ?? []).map((file) => relativize(file.documentLocation ?? "")));
360
+ }
361
+ /**
362
+ * Which way coverage moved, in words.
363
+ *
364
+ * Words rather than a signed percentage because TOON quotes any scalar that
365
+ * starts with `-`, and `"-2.1%"` costs more in quotes than `down 2.1%` costs
366
+ * in letters.
367
+ */
368
+ export function movement(delta) {
369
+ if (delta === 0)
370
+ return "unchanged";
371
+ return `${delta > 0 ? "up" : "down"} ${percent(Math.abs(delta))}`;
372
+ }
373
+ /**
374
+ * `--merge`, which combines the coverage of a sharded run.
375
+ *
376
+ * `xccov merge` wants report/archive pairs rather than result bundles, so the
377
+ * bundles are unpacked first — the two-step that makes this something people
378
+ * give up on doing in CI.
379
+ */
380
+ async function runMerge(first, args, max) {
381
+ const paths = positionals(args, VALUE_FLAGS).map((path) => resolve(expandTilde(path)));
382
+ if (paths.length < 2) {
383
+ throw new AxiError(`--merge combines the coverage of two or more runs, and ${paths.length} was given`, "VALIDATION_ERROR", [
384
+ "xcodebuild-axi coverage shard1.xcresult shard2.xcresult --merge",
385
+ "`xcodebuild-axi test --coverage` prints the bundle path it wrote",
386
+ ]);
387
+ }
388
+ const requested = getFlag(args, "--to");
389
+ const outReport = requested
390
+ ? resolve(expandTilde(requested))
391
+ : mergedCoveragePath(paths);
392
+ const outArchive = outReport.replace(/\.xccovreport$/, "") + ".xccovarchive";
393
+ if (requested && (existsSync(outReport) || existsSync(outArchive))) {
394
+ throw new AxiError(`Something is already at ${tildePath(outReport)}`, "VALIDATION_ERROR", [
395
+ "Pass a path that does not exist yet, or drop --to to write under ~/Library/Caches",
396
+ ]);
397
+ }
398
+ if (!requested) {
399
+ rmSync(outReport, { recursive: true, force: true });
400
+ rmSync(outArchive, { recursive: true, force: true });
401
+ }
402
+ mkdirSync(dirname(outReport), { recursive: true });
403
+ await mergeCoverage(paths, outReport, outArchive);
404
+ const merged = await readCoverage(outReport);
405
+ return renderOutput([
406
+ renderFields({
407
+ merged: paths.length,
408
+ coverage: percent(merged.lineCoverage),
409
+ lines: `${merged.coveredLines} of ${merged.executableLines} covered`,
410
+ report: tildePath(outReport),
411
+ archive: tildePath(outArchive),
412
+ }),
413
+ renderList("from", paths.slice(0, max).map((path) => ({ bundle: tildePath(path) }))),
414
+ renderHelp([
415
+ `Run \`xcodebuild-axi coverage ${tildePath(outReport)} --files\` to report on the merged coverage`,
416
+ ]),
417
+ ]);
418
+ }
112
419
  function expandTilde(path) {
113
420
  const home = process.env["HOME"];
114
421
  return home && path.startsWith("~/") ? `${home}${path.slice(1)}` : path;
@@ -1 +1 @@
1
- {"version":3,"file":"coverage.js","sourceRoot":"","sources":["../../../src/commands/coverage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"coverage.js","sourceRoot":"","sources":["../../../src/commands/coverage.ts"],"names":[],"mappings":"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"}