supercov 2.0.0 → 3.0.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 +52 -22
- package/docs/agent-loop.md +8 -13
- package/docs/assertions.md +161 -75
- package/docs/cli.md +111 -59
- package/docs/coverage-model.md +5 -6
- package/docs/evidence.md +0 -11
- package/docs/getting-started.md +1 -1
- package/docs/performance.md +6 -14
- package/docs/quality.md +1 -1
- package/docs/security.md +43 -12
- package/docs/supported-suites.md +44 -48
- package/docs/troubleshooting.md +12 -5
- package/docs/workspace-isolation.md +23 -2
- package/package.json +36 -21
- package/runtime/javascript/atomic.mjs +46 -2
- package/runtime/javascript/ava.mjs +82 -0
- package/runtime/javascript/bootstrap.cjs +43 -0
- package/runtime/javascript/jest.cjs +52 -15
- package/runtime/javascript/jest.config.mjs +9 -1
- package/runtime/javascript/jestReporter.mjs +5 -6
- package/runtime/javascript/launchSupervisor.mjs +127 -15
- package/runtime/javascript/mocha.mjs +180 -0
- package/runtime/javascript/nodeTest.mjs +57 -3
- package/runtime/javascript/playwright.mjs +241 -32
- package/runtime/javascript/provenance.mjs +1 -1
- package/runtime/javascript/register.mjs +290 -2
- package/runtime/javascript/resolve-loader.mjs +40 -1
- package/runtime/javascript/runnerEvidence.mjs +3 -5
- package/runtime/javascript/runtime.mjs +551 -61
- package/runtime/javascript/tap.mjs +130 -0
- package/runtime/javascript/transport.mjs +7 -2
- package/runtime/javascript/vitest.mjs +5 -8
- package/runtime/javascript/vitestReporter.mjs +3 -10
- package/docs/assertion-agent.md +0 -150
- package/docs/assertion-evidence.md +0 -103
- package/docs/assertion-maps.md +0 -316
- package/schemas/assertions.schema.json +0 -276
package/README.md
CHANGED
|
@@ -12,10 +12,12 @@ Measure code quality with npx supercov.
|
|
|
12
12
|
|
|
13
13
|
Scoring needs a [TypeSafe AI](https://typesafe.ai) API key, and your coding agent will usually ask you for it. It costs about a cent per megabyte of source. Coverage needs no account, config file, import, custom reporter, or hosted service. Supercov is local, free, open source, and MIT licensed.
|
|
14
14
|
|
|
15
|
-
[Website](https://supercov.com) · [Documentation](https://supercov.com/docs) · [npm](https://www.npmjs.com/package/supercov) · [GitHub](https://github.com/supercorp-ai/supercov)
|
|
15
|
+
[Website](https://supercov.com) · [Documentation](https://supercov.com/docs) · [npm](https://www.npmjs.com/package/supercov) · [GitHub](https://github.com/supercorp-ai/supercov) · [Discord](https://discord.gg/CudcAH53yF)
|
|
16
16
|
|
|
17
17
|
Supported languages: [JavaScript](https://supercov.com/docs/javascript) · [TypeScript](https://supercov.com/docs/javascript) · [Rust](https://supercov.com/docs/rust) · [Python](https://supercov.com/docs/python) · [Ruby](https://supercov.com/docs/ruby) · [Go](https://supercov.com/docs/go) · [Java](https://supercov.com/docs/java) · [Kotlin](https://supercov.com/docs/kotlin).
|
|
18
18
|
|
|
19
|
+
In Claude Code, Codex and Gemini CLI you can also [install it as a plugin](#give-supercov-a-job).
|
|
20
|
+
|
|
19
21
|
Supported by [Supercorp](https://supercorp.ai).
|
|
20
22
|
|
|
21
23
|
[Agent workflow](https://supercov.com/docs/agent-loop): ask your coding agent
|
|
@@ -139,35 +141,57 @@ npx supercov -- python -m unittest
|
|
|
139
141
|
npx supercov -- bundle exec rspec
|
|
140
142
|
```
|
|
141
143
|
|
|
142
|
-
##
|
|
144
|
+
## See what the tests assert
|
|
143
145
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
+
Coverage says which code ran; assertion coverage says which of it the tests
|
|
147
|
+
would catch breaking. Supercov asks [Jev](https://typesafe.ai), test by test,
|
|
148
|
+
whether changing each statement the test ran would make it fail:
|
|
146
149
|
|
|
147
150
|
```sh
|
|
148
|
-
npx supercov
|
|
149
|
-
|
|
150
|
-
npx supercov runs
|
|
151
|
-
npx supercov runs <run> source src/example.ts
|
|
152
|
-
# Edit assertions.json, then validate and acknowledge:
|
|
153
|
-
npx supercov runs <run> assertions validate --json
|
|
154
|
-
# Copy examined expectedBasis tokens into assertions.json; save again.
|
|
155
|
-
npx supercov runs <run> assertions check --require-mappings --json
|
|
156
|
-
npx supercov runs <run> # includes the assertion percentage in the regular report
|
|
151
|
+
npx supercov -- npm test
|
|
152
|
+
TYPESAFE_API_KEY=... npx supercov runs latest assertions assess
|
|
153
|
+
npx supercov runs latest assertions # the share asserted and what is not
|
|
157
154
|
```
|
|
158
155
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
The score is agent-assessed and separate from MC/DC. See
|
|
163
|
-
[assertion maps](docs/assertion-maps.md) for the format and JS/TS limits, or run
|
|
164
|
-
`supercov docs assertion-agent` for the agent workflow. `supercov assertions schema`
|
|
165
|
-
exports the editor schema; `assertions validate --file <path>` checks JSON syntax.
|
|
156
|
+
Answers are reused across runs whenever the question is the same, so after a
|
|
157
|
+
commit only what changed is asked again. Every language Supercov measures. See
|
|
158
|
+
[assertion coverage](docs/assertions.md).
|
|
166
159
|
|
|
167
160
|
## Give Supercov a job
|
|
168
161
|
|
|
169
162
|
Paste one of these prompts into Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, or any coding agent that can run terminal commands.
|
|
170
163
|
|
|
164
|
+
Or install the agent skill, and your agent reaches for Supercov on its own when you ask for tests, coverage, refactoring or a security scan. In Claude Code:
|
|
165
|
+
|
|
166
|
+
```text
|
|
167
|
+
/plugin marketplace add supercorp-ai/supercov
|
|
168
|
+
/plugin install supercov@supercov
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
In Codex:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
codex plugin marketplace add supercorp-ai/supercov
|
|
175
|
+
codex plugin add supercov@supercov
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
In Gemini CLI:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
gemini extensions install https://github.com/supercorp-ai/supercov
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
For Cursor, GitHub Copilot and other agents that read skills: `npx skills add supercorp-ai/supercov`.
|
|
185
|
+
|
|
186
|
+
The Claude Code plugin and the Gemini CLI extension also add four commands you can type:
|
|
187
|
+
|
|
188
|
+
| Command | What it does |
|
|
189
|
+
| --- | --- |
|
|
190
|
+
| `/supercov:coverage [test command]` | Writes one test for code no test reaches, and reports coverage before and after |
|
|
191
|
+
| `/supercov:security [patch]` | Scans the repository, or a change, for security vulnerabilities |
|
|
192
|
+
| `/supercov:quality [patch]` | Ranks files by code smells, or checks what a change introduced |
|
|
193
|
+
| `/supercov:review [--base ref]` | Checks a branch or uncommitted change for security and quality problems |
|
|
194
|
+
|
|
171
195
|
### Write the first useful test
|
|
172
196
|
|
|
173
197
|
```text
|
|
@@ -280,9 +304,11 @@ Supercov uses exact per-test attribution where an adapter is available. For othe
|
|
|
280
304
|
| --- | --- |
|
|
281
305
|
| Playwright | Exact per test, worker, retry, outcome, action, and assertion phase |
|
|
282
306
|
| Vitest | Exact per test, with setup execution kept separate |
|
|
283
|
-
| Jest | Exact per test, including parameterized tests
|
|
307
|
+
| Jest | Exact per test, including parameterized tests |
|
|
284
308
|
| `node:test` | Exact per test |
|
|
285
|
-
|
|
|
309
|
+
| Mocha | Exact per test and retry, `--parallel` included |
|
|
310
|
+
| AVA | Exact per test, concurrent tests included |
|
|
311
|
+
| node-tap 15 and newer | Exact per subtest |
|
|
286
312
|
| Cargo's standard libtest runner | Exact test, attempt, and passing-assertion identity |
|
|
287
313
|
| rustdoc doctests | Exact per doctest |
|
|
288
314
|
| cargo-nextest | Exact test, attempt, retry, and binary identity |
|
|
@@ -352,6 +378,10 @@ npx supercov runs clean # remove all runs and the build cache
|
|
|
352
378
|
|
|
353
379
|
[MIT licensed](LICENSE). Inspect, extend, and run it anywhere.
|
|
354
380
|
|
|
381
|
+
## Community
|
|
382
|
+
|
|
383
|
+
Ask questions, share what you measured, and talk to the people building Supercov on [Discord](https://discord.gg/CudcAH53yF).
|
|
384
|
+
|
|
355
385
|
## Contributors
|
|
356
386
|
|
|
357
387
|
- [@DaVinciTachyon](https://github.com/DaVinciTachyon)
|
package/docs/agent-loop.md
CHANGED
|
@@ -55,24 +55,19 @@ duplicate.
|
|
|
55
55
|
|
|
56
56
|
## Add assertion coverage
|
|
57
57
|
|
|
58
|
-
For JavaScript and TypeScript projects,
|
|
59
|
-
|
|
60
|
-
map and carries forward compatible work from earlier runs of the same command.
|
|
58
|
+
For JavaScript and TypeScript projects, ask which executed statements no test
|
|
59
|
+
would catch breaking, then add checks for them:
|
|
61
60
|
|
|
62
61
|
```sh supercov
|
|
62
|
+
npx supercov runs latest assertions assess
|
|
63
63
|
npx supercov runs latest assertions
|
|
64
|
-
npx supercov
|
|
64
|
+
npx supercov runs latest assertions <path>
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
Start with [Understanding assertion coverage](assertions.md) for a copyable
|
|
73
|
-
prompt. [Mapping assertions with an agent](assertion-agent.md) gives the complete
|
|
74
|
-
editing and checking loop. Use the evidence and recorded observations alongside
|
|
75
|
-
MC/DC when deciding which tests need stronger checks.
|
|
67
|
+
`assess` needs `TYPESAFE_API_KEY`; reading does not. A statement that is not
|
|
68
|
+
asserted runs in some test, but nothing that test checks depends on it. After
|
|
69
|
+
adding a check, rerun the suite and assess again: only the questions the change
|
|
70
|
+
touched are asked. See [Assertion coverage](assertions.md).
|
|
76
71
|
|
|
77
72
|
## Example
|
|
78
73
|
|
package/docs/assertions.md
CHANGED
|
@@ -1,17 +1,7 @@
|
|
|
1
1
|
# Assertion coverage
|
|
2
2
|
|
|
3
|
-
Line coverage shows which code ran. Assertion coverage
|
|
4
|
-
tests
|
|
5
|
-
Supercov checks those links against recorded execution from the same test.
|
|
6
|
-
|
|
7
|
-
Assertion coverage measures JavaScript, TypeScript, Python, Ruby and Rust. The
|
|
8
|
-
map format is the same for every one of them: an assertion is identified by its
|
|
9
|
-
file, line and column, so a project written in more than one language keeps a
|
|
10
|
-
single map.
|
|
11
|
-
|
|
12
|
-
Python and Ruby report an assertion's line but not its column, so two
|
|
13
|
-
assertions written on one line cannot be told apart and neither is credited.
|
|
14
|
-
Put them on separate lines.
|
|
3
|
+
Line coverage shows which code ran. Assertion coverage shows which of that code
|
|
4
|
+
the tests would catch breaking.
|
|
15
5
|
|
|
16
6
|
## A passing test can miss a wrong result
|
|
17
7
|
|
|
@@ -37,75 +27,171 @@ test('confirms an order', () => {
|
|
|
37
27
|
});
|
|
38
28
|
```
|
|
39
29
|
|
|
40
|
-
Every line
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
##
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
The
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
30
|
+
Every line runs and the test passes. It would also pass if `total` were
|
|
31
|
+
`undefined`, so the line computing it is covered but not asserted.
|
|
32
|
+
|
|
33
|
+
## What counts as asserted
|
|
34
|
+
|
|
35
|
+
A statement is asserted when changing it would make at least one passing test
|
|
36
|
+
that runs it fail: an assertion fails, test or helper code throws, the test
|
|
37
|
+
times out, or the process crashes. The change depends on the statement:
|
|
38
|
+
|
|
39
|
+
| Statement | Change |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| `if` (and `elif`, `elsif`, `unless`, `else if`) | the condition inverted, each way separately (asserted if either is caught); a Rust `if let` is made not to match |
|
|
42
|
+
| `return x`, and a block's value in Ruby, Rust and Kotlin | returns a stand-in for nothing, without evaluating `x` |
|
|
43
|
+
| a `when`, `switch`, `try`, `loop` or Kotlin `throw` a function ends on | every value it returns becomes that stand-in (skipping it would leave the function nothing to return) |
|
|
44
|
+
| declaration or assignment with a value | the value becomes that stand-in, without being evaluated |
|
|
45
|
+
| JSX expression | the value becomes undefined |
|
|
46
|
+
| anything else | skipped: the statement does not run |
|
|
47
|
+
|
|
48
|
+
The stand-in is `undefined` in JavaScript and TypeScript, `None` in Python and
|
|
49
|
+
`nil` in Ruby. Go and the JVM languages replace a value after it is computed,
|
|
50
|
+
as their mutation testers do: the zero value in Go, and `null`, `0` or `false`
|
|
51
|
+
in Java and Kotlin. Rust has no value that fits every type, so it takes a
|
|
52
|
+
different value of the same type, from the function's signature or the
|
|
53
|
+
`let`'s annotation where there is one: a boolean negated, an `Ok` turned into
|
|
54
|
+
an `Err` and back, a literal swapped (`false` for `true`, `1` for `0`), an
|
|
55
|
+
`Ordering` reversed, `None`, `""` or `0`. Where nothing is annotated, the type
|
|
56
|
+
comes from the crate's own signatures, the parameters and `let`s in scope, or
|
|
57
|
+
a `match`'s arms (`let (major, text) = numeric(text)?;` takes `numeric`'s
|
|
58
|
+
return type): a tuple gets one element changed, an enum another of its
|
|
59
|
+
variants, a struct literal one field, a closure its result, integer
|
|
60
|
+
arithmetic its lowest bit flipped, a comparison its order reversed, a slice
|
|
61
|
+
or split the empty one, and `let Some(x) = .. else` gets `None`. A value of a
|
|
62
|
+
type the crate defines is built from its own constants, constructors and
|
|
63
|
+
enums (`Err(Error::new(ErrorKind::Empty))`, `Ok(Version::new(0, 0, 0))`).
|
|
64
|
+
`Default::default()` is left only where nothing says what the type is.
|
|
65
|
+
|
|
66
|
+
Imports, declarations without a value, and function, class and type
|
|
67
|
+
declarations are not assessed; in Python neither are `pass`, `global`,
|
|
68
|
+
`nonlocal` and docstrings, and in Ruby neither are the calls that declare
|
|
69
|
+
(`require`, `attr_reader`, `private`, `include` ...). **Assertions** is the
|
|
70
|
+
share of the executed statements that are asserted.
|
|
71
|
+
|
|
72
|
+
## Assess and read
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npx supercov -- npm test
|
|
76
|
+
npx supercov runs latest assertions assess
|
|
77
|
+
npx supercov runs latest assertions
|
|
62
78
|
```
|
|
63
79
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
80
|
+
`assertions assess` works it out and saves the result to the run. For each test,
|
|
81
|
+
Supercov renders what the test ran -- its code, its helpers, and the source it
|
|
82
|
+
executed -- and asks [Jev](https://typesafe.ai) whether the test would fail for
|
|
83
|
+
each statement's change. It prints an estimate first; `--dry-run` sends nothing.
|
|
84
|
+
It needs a TypeSafe AI API key in `TYPESAFE_API_KEY`.
|
|
69
85
|
|
|
70
|
-
|
|
71
|
-
|
|
86
|
+
`assertions` reads the saved result with no network and no key, a page at a
|
|
87
|
+
time, from the run down to one statement:
|
|
72
88
|
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
and update the map. Show the test change, before-and-after assertion
|
|
79
|
-
coverage, and any uncertainty or missing evidence.
|
|
89
|
+
```bash
|
|
90
|
+
npx supercov runs latest assertions # the share, and the files by statements not asserted
|
|
91
|
+
npx supercov runs latest assertions src/adapters.ts # that file's statements not asserted
|
|
92
|
+
npx supercov runs latest assertions src/adapters.ts:100 # one statement: each asked test's answer
|
|
93
|
+
npx supercov runs latest assertions --test "closes the stream" # what one test catches, and what it misses
|
|
80
94
|
```
|
|
81
95
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
compatible mappings and flags explanations that need another look.
|
|
85
|
-
|
|
86
|
-
## Read the result
|
|
87
|
-
|
|
88
|
-
The agent can show the summary and the statement-level report for a file:
|
|
96
|
+
```text
|
|
97
|
+
Run run_4f2a: 93.8% asserted (2731 of 2913 executed statements)
|
|
89
98
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
99
|
+
Files, most statements not asserted first: a statement is not asserted when no test that runs it was judged to fail if it changed.
|
|
100
|
+
NOT ASSERTED ASSERTED FILE
|
|
101
|
+
41 388/429 src/adapters.ts
|
|
102
|
+
...
|
|
103
|
+
showing 1-20 of 57
|
|
104
|
+
next page: npx supercov runs 'run_4f2a' assertions --offset 20
|
|
105
|
+
inspect a file: npx supercov runs 'run_4f2a' assertions 'src/adapters.ts'
|
|
93
106
|
```
|
|
94
107
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
108
|
+
Each listing ends with the command for its next page and for the next step
|
|
109
|
+
down, so an agent reads only as much as it needs. `runs latest file` and
|
|
110
|
+
`runs latest line` show the same verdicts beside the coverage, and
|
|
111
|
+
`npx supercov runs latest` and the HTML report show the same share.
|
|
112
|
+
|
|
113
|
+
A statement that is not asserted is a place to add a check: a test that runs it
|
|
114
|
+
exists, but nothing it asserts depends on what the statement does.
|
|
115
|
+
|
|
116
|
+
## Which tests check a change
|
|
117
|
+
|
|
118
|
+
`npx supercov runs latest tests affected` uses the assessment to say which of
|
|
119
|
+
the tests a change reaches were judged to catch it, and lists them first;
|
|
120
|
+
`assertions assess --changed` asks every test that ran the changed code. See
|
|
121
|
+
[Find the tests a change affects](cli.md#find-the-tests-a-change-affects).
|
|
122
|
+
|
|
123
|
+
## Later runs ask only about what changed
|
|
124
|
+
|
|
125
|
+
Answers are kept in `.supercov/assertions/`. Each is stored under the exact text
|
|
126
|
+
Jev saw for that statement and test, and reused only when a new run would ask
|
|
127
|
+
the same question with the same text. Nothing decides whether a change could
|
|
128
|
+
matter: a change to the statement, to code around it that the test ran, to the
|
|
129
|
+
test or its helpers, or to which tests run it, asks again. A dependency or
|
|
130
|
+
configuration change asks everything again. After a typical commit only a few
|
|
131
|
+
dozen questions are asked; the rest are reused.
|
|
132
|
+
|
|
133
|
+
## Cost, speed and accuracy
|
|
134
|
+
|
|
135
|
+
- **Cost:** about 0.006 cents per statement for a first assessment: 14 projects
|
|
136
|
+
in six languages (8,356 statements) cost $0.48 together. A project of 3,000
|
|
137
|
+
statements costs about $0.18; a later commit usually well under a cent.
|
|
138
|
+
- **Speed:** about 20 seconds for 1,500 statements with 24 requests in flight
|
|
139
|
+
(`--workers`, default 24; it changes how long a pass takes, not what it
|
|
140
|
+
costs).
|
|
141
|
+
|
|
142
|
+
Measured on four JavaScript and TypeScript projects (7,393 executed statements):
|
|
143
|
+
|
|
144
|
+
- **Accuracy:** against ground truth from applying each change and running the
|
|
145
|
+
tests, on a fresh sample of 78 statements: 69 right; of the 13 not asserted it
|
|
146
|
+
found 8, and 8 of the 12 it flagged were truly not asserted. The share it
|
|
147
|
+
reported was 84.6% against a true 83.3%.
|
|
148
|
+
- **Python:** on h11 (532 executed statements, pytest), every statement checked
|
|
149
|
+
the same way: 502 right; of the 67 not asserted it found 45, and 45 of the 53
|
|
150
|
+
it flagged were truly not asserted. The share it reported was 90.0% against a
|
|
151
|
+
true 87.4%, for about $0.04.
|
|
152
|
+
- **Go, Rust, Java, Ruby and Kotlin**, checked the same way. These were used
|
|
153
|
+
to shape how changes and tests are shown to Jev, so they are flattering:
|
|
154
|
+
|
|
155
|
+
| Project | Checked | Right | Flagged (truly not asserted) | Share reported / true |
|
|
156
|
+
| --- | --- | --- | --- | --- |
|
|
157
|
+
| google/uuid (Go) | 339 | 298 | 34 (28) | 90.0% / 81.4% |
|
|
158
|
+
| hashicorp/go-version (Go) | 257 | 253 | 21 (19) | 91.8% / 91.8% |
|
|
159
|
+
| dtolnay/semver (Rust) | 200 of a sample of 200 | 190 | 7 (2) | 96.5% / 96.5% |
|
|
160
|
+
| apache/commons-cli (Java) | 196 of a sample of 200 | 167 | 49 (33) | 75.0% / 76.5% |
|
|
161
|
+
| dry-rb/dry-inflector (Ruby 3.4) | 157 | 148 | 13 (8) | 91.7% / 92.4% |
|
|
162
|
+
| sporkmonger/addressable (Ruby) | 198 of a sample of 200 | 182 | 25 (14) | 87.4% / 90.4% |
|
|
163
|
+
| square/moshi (Kotlin) | 60 of a sample of 60 | 52 | 9 (6) | 85.0% / 81.7% |
|
|
164
|
+
|
|
165
|
+
- **Held out:** five projects nothing was tuned on, each assessed once by the
|
|
166
|
+
shipped version and its verdicts frozen before any change was run, scored on
|
|
167
|
+
a pre-registered sample of 60 statements (and on every statement where the
|
|
168
|
+
suite is fast enough):
|
|
169
|
+
|
|
170
|
+
| Project | Checked | Right | Flagged (truly not asserted) | Share reported / true |
|
|
171
|
+
| --- | --- | --- | --- | --- |
|
|
172
|
+
| pallets/itsdangerous (Python) | 60 of 60 | 56 | 3 (2) | 95.0% / 91.7% |
|
|
173
|
+
| — every statement | 238 of 238 | 224 | 13 (9) | 94.5% / 92.0% |
|
|
174
|
+
| Masterminds/semver (Go) | 60 of 60 | 55 | 7 (7) | 88.3% / 80.0% |
|
|
175
|
+
| — every statement | 497 of 498 | 472 | 46 (44) | 90.7% / 86.5% |
|
|
176
|
+
| hashie/hashie (Ruby 3.4) | 60 of 60 | 57 | 3 (1) | 95.0% / 96.7% |
|
|
177
|
+
| — every statement | 700 of 701 | 655 | 26 (10) | 96.3% / 94.4% |
|
|
178
|
+
| FasterXML/java-classmate (Java) | 60 of 60 | 58 | 9 (7) | 85.0% / 88.3% |
|
|
179
|
+
| bluss/arrayvec (Rust) | 54 of 60 | 48 | 1 (1) | 98.1% / 87.0% |
|
|
180
|
+
|
|
181
|
+
Assessing all five (2,582 statements) cost $0.15, about 0.006 cents per
|
|
182
|
+
statement. Go reads high: Jev takes a dropped error (`return false,
|
|
183
|
+
fmt.Errorf(..)` becoming `return false, nil`) as caught where the tests check
|
|
184
|
+
only the boolean. Rust reads high too on arrayvec, whose code is generic over
|
|
185
|
+
its element type; six of its sampled changes cannot be made, because no value
|
|
186
|
+
of an unknown `T` can be written.
|
|
187
|
+
|
|
188
|
+
The share is a good measure of a project; a single statement's verdict is a
|
|
189
|
+
judgment worth checking before acting on it. Supercov does not run mutated code
|
|
190
|
+
for this: nothing is executed, and your tests are never slowed.
|
|
191
|
+
|
|
192
|
+
## Requirements
|
|
193
|
+
|
|
194
|
+
Runs of any language Supercov measures: JavaScript and TypeScript, Python
|
|
195
|
+
(pytest, unittest), Ruby (RSpec, Minitest, test-unit, Cucumber), Go, Rust
|
|
196
|
+
(libtest, nextest, doctests), and Java and Kotlin (JUnit, TestNG); and
|
|
197
|
+
`TYPESAFE_API_KEY` for `assess`. Reading a saved result needs neither.
|