@creative-introvert/tons-of-tests 2.0.0 → 2.1.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 -134
- package/dist/cjs/Classify.js +5 -0
- package/dist/cjs/Classify.js.map +1 -1
- package/dist/cjs/Test.js +5 -1
- package/dist/cjs/Test.js.map +1 -1
- package/dist/cjs/Test.repository.types.js.map +1 -1
- package/dist/cjs/internal/Test.js +107 -54
- package/dist/cjs/internal/Test.js.map +1 -1
- package/dist/cjs/internal/Test.repository.sqlite.js +77 -20
- package/dist/cjs/internal/Test.repository.sqlite.js.map +1 -1
- package/dist/cjs/internal/stats.js +8 -2
- package/dist/cjs/internal/stats.js.map +1 -1
- package/dist/cjs/internal/summarize.js +18 -13
- package/dist/cjs/internal/summarize.js.map +1 -1
- package/dist/dts/Classify.d.ts +4 -0
- package/dist/dts/Classify.d.ts.map +1 -1
- package/dist/dts/Show.d.ts +3 -3
- package/dist/dts/Show.d.ts.map +1 -1
- package/dist/dts/Test.d.ts +46 -8
- package/dist/dts/Test.d.ts.map +1 -1
- package/dist/dts/Test.repository.d.ts +3 -3
- package/dist/dts/Test.repository.d.ts.map +1 -1
- package/dist/dts/Test.repository.types.d.ts +6 -0
- package/dist/dts/Test.repository.types.d.ts.map +1 -1
- package/dist/dts/internal/Test.d.ts +15 -10
- package/dist/dts/internal/Test.d.ts.map +1 -1
- package/dist/dts/internal/Test.repository.sqlite.d.ts +2 -1
- package/dist/dts/internal/Test.repository.sqlite.d.ts.map +1 -1
- package/dist/dts/internal/stats.d.ts.map +1 -1
- package/dist/dts/internal/summarize.d.ts.map +1 -1
- package/dist/esm/Classify.js +5 -0
- package/dist/esm/Classify.js.map +1 -1
- package/dist/esm/Test.js +4 -0
- package/dist/esm/Test.js.map +1 -1
- package/dist/esm/Test.repository.types.js.map +1 -1
- package/dist/esm/internal/Test.js +104 -53
- package/dist/esm/internal/Test.js.map +1 -1
- package/dist/esm/internal/Test.repository.sqlite.js +77 -20
- package/dist/esm/internal/Test.repository.sqlite.js.map +1 -1
- package/dist/esm/internal/stats.js +8 -2
- package/dist/esm/internal/stats.js.map +1 -1
- package/dist/esm/internal/summarize.js +18 -13
- package/dist/esm/internal/summarize.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,7 +26,8 @@ A specialized test runner for predictive functions, focusing on scenarios where
|
|
|
26
26
|
|
|
27
27
|
Use Node.js 24 or newer and Effect 4. The Effect packages in this repository
|
|
28
28
|
use the same exact version. The SQLite driver uses Node's built-in SQLite.
|
|
29
|
-
Existing database files
|
|
29
|
+
Existing database files are migrated when opened. Previously stored results
|
|
30
|
+
receive the key `result`; their test case hashes stay the same.
|
|
30
31
|
|
|
31
32
|
### Installation
|
|
32
33
|
|
|
@@ -49,6 +50,10 @@ import * as CLI from '@creative-introvert/tons-of-tests-cli';
|
|
|
49
50
|
import {Effect} from 'effect';
|
|
50
51
|
|
|
51
52
|
const myFunction = (input: number) => Promise.resolve(input * 1.7);
|
|
53
|
+
const classify = Classify.makeClassify<number, number>({
|
|
54
|
+
// Treat an absolute error of up to 0.4 as a match.
|
|
55
|
+
isEqual: (a, b) => Math.abs(b - a) <= 0.4,
|
|
56
|
+
});
|
|
52
57
|
|
|
53
58
|
CLI.run({
|
|
54
59
|
testSuite: {
|
|
@@ -60,12 +65,9 @@ CLI.run({
|
|
|
60
65
|
{input: 3, expected: 4},
|
|
61
66
|
{input: 4, expected: 5},
|
|
62
67
|
],
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
classify: Classify.makeClassify({
|
|
67
|
-
isEqual: (a, b) => Math.abs(b - a) <= 0.4,
|
|
68
|
-
}),
|
|
68
|
+
evaluate: (result, expected) => [
|
|
69
|
+
{key: 'result', result, expected, label: classify(result, expected)},
|
|
70
|
+
],
|
|
69
71
|
program: (input: number) => Effect.promise(() => myFunction(input)),
|
|
70
72
|
},
|
|
71
73
|
dbPath: 'with-cli-simple.db',
|
|
@@ -73,7 +75,10 @@ CLI.run({
|
|
|
73
75
|
});
|
|
74
76
|
```
|
|
75
77
|
|
|
76
|
-
|
|
78
|
+
Omit `evaluate` to compare the whole output with the expected value using
|
|
79
|
+
`Classify.defaultIsEqual`. The default evaluator returns one result with key
|
|
80
|
+
`result`. `Classify.makeClassify` returns a label for one comparison; use it
|
|
81
|
+
inside `evaluate` when you want to choose how values match.
|
|
77
82
|
|
|
78
83
|
`testCases` can also be an Effect `Stream`, which is useful for large or generated suites that are consumed lazily by the runner:
|
|
79
84
|
|
|
@@ -93,96 +98,146 @@ CLI.run({
|
|
|
93
98
|
});
|
|
94
99
|
```
|
|
95
100
|
|
|
96
|
-
|
|
101
|
+
### Multiple Results From One Test Case
|
|
97
102
|
|
|
103
|
+
Use `evaluate` to track parts of one program output separately. The runner calls
|
|
104
|
+
`program` once per test case, then passes its output and the case's expected
|
|
105
|
+
value to `evaluate`.
|
|
106
|
+
|
|
107
|
+
For a BANT inference, the evaluator can return a result for each of budget,
|
|
108
|
+
authority, need, and timeline:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import {Classify, type Test} from '@creative-introvert/tons-of-tests';
|
|
112
|
+
import {Array} from 'effect';
|
|
113
|
+
|
|
114
|
+
type Bant = {
|
|
115
|
+
readonly budget: string | null;
|
|
116
|
+
readonly authority: string | null;
|
|
117
|
+
readonly need: string | null;
|
|
118
|
+
readonly timeline: string | null;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const fields = ['budget', 'authority', 'need', 'timeline'] as const;
|
|
122
|
+
const classify = Classify.makeClassify({isEqual: Classify.defaultIsEqual});
|
|
123
|
+
|
|
124
|
+
const evaluate: Test.Evaluate<Bant, Bant, string | null, string | null> = (
|
|
125
|
+
output,
|
|
126
|
+
expected,
|
|
127
|
+
) =>
|
|
128
|
+
Array.map(fields, key => ({
|
|
129
|
+
key,
|
|
130
|
+
result: output[key],
|
|
131
|
+
expected: expected[key],
|
|
132
|
+
label: classify(output[key], expected[key]),
|
|
133
|
+
}));
|
|
98
134
|
```
|
|
99
|
-
pnpx tsx my-test-suite.ts summarize
|
|
100
135
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
136
|
+
Pass `evaluate` alongside `program` in the test suite. See the runnable
|
|
137
|
+
[multiple-results.ts example](./workspace/examples/src/with-cli/multiple-results.ts)
|
|
138
|
+
for a complete suite using a fixed response in place of an LLM call.
|
|
139
|
+
|
|
140
|
+
`evaluate` is a pure function. It must return a non-empty readonly array of
|
|
141
|
+
`Test.EvaluationResult` values. Each value has a `key`, `result`, `expected`, and
|
|
142
|
+
`label`. Keys must be non-empty and unique within the case. Keep keys stable
|
|
143
|
+
across runs so the CLI can match each result to its previous value.
|
|
144
|
+
|
|
145
|
+
The CLI shows one row per result in the existing table. Rows from the same case
|
|
146
|
+
stay next to each other and share the same `hash`. The `key` column identifies
|
|
147
|
+
each result. The hash comes from the original input and expected value; each
|
|
148
|
+
result is matched across runs by that hash and its key.
|
|
149
|
+
|
|
150
|
+
For the BANT example, these columns show the shared case hash (other columns
|
|
151
|
+
are omitted here):
|
|
152
|
+
|
|
153
|
+
```text
|
|
154
|
+
┌──────────┬───────────┬───────┐
|
|
155
|
+
│ hash │ key │ label │
|
|
156
|
+
├──────────┼───────────┼───────┤
|
|
157
|
+
│ 688c8d1f │ budget │ FP │
|
|
158
|
+
├──────────┼───────────┼───────┤
|
|
159
|
+
│ 688c8d1f │ authority │ TP │
|
|
160
|
+
├──────────┼───────────┼───────┤
|
|
161
|
+
│ 688c8d1f │ need │ TP │
|
|
162
|
+
├──────────┼───────────┼───────┤
|
|
163
|
+
│ 688c8d1f │ timeline │ FN │
|
|
164
|
+
└──────────┴───────────┴───────┘
|
|
129
165
|
```
|
|
130
166
|
|
|
131
|
-
|
|
167
|
+
The statistics count cases and results separately. Labels, precision, and recall
|
|
168
|
+
count visible results. Timing statistics count each visible case once, even when
|
|
169
|
+
it has several result rows.
|
|
132
170
|
|
|
133
|
-
|
|
134
|
-
|
|
171
|
+
If you supply `testSuite.schemas`, `input` describes the original input.
|
|
172
|
+
`result` and `expected` describe the values returned by `evaluate`. For this
|
|
173
|
+
BANT example, both use `Schema.NullOr(Schema.String)` because each result is one
|
|
174
|
+
field, even though the program returns a full BANT object.
|
|
175
|
+
|
|
176
|
+
#### Updating Suites That Use `classify`
|
|
177
|
+
|
|
178
|
+
Replace the suite's `classify` property with an `evaluate` callback. Keep the
|
|
179
|
+
classifier and wrap its label in a result, as shown in the basic example:
|
|
135
180
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
├─────┼──────────┼────────┼──────┼───────┼──────────┼────────┼──────────────┤
|
|
141
|
-
│ 1/3 │ bd04cb2c │ 0.52ms │ │ 0 │ 0 │ TP │ │
|
|
142
|
-
├─────┼──────────┼────────┼──────┼───────┼──────────┼────────┼──────────────┤
|
|
143
|
-
│ 2/3 │ 562e2cca │ 0.41ms │ │ 1 │ 2 │ TP │ 2 => 1.7 │
|
|
144
|
-
├─────┼──────────┼────────┼──────┼───────┼──────────┼────────┼──────────────┤
|
|
145
|
-
│ 3/3 │ a5afd52f │ 0.74ms │ │ 2 │ 3 │ TP │ 3 => 3.4 │
|
|
146
|
-
├─────┼──────────┼────────┼──────┼───────┼──────────┼────────┼──────────────┤
|
|
147
|
-
│ #/∑ │ hash │ ms │ tags │ input │ expected │ label₀ │ diff result₀ │
|
|
148
|
-
└─────┴──────────┴────────┴──────┴───────┴──────────┴────────┴──────────────┘
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
┌────────────────────────────────────────────────────────────────────┐
|
|
152
|
-
│ STATS │
|
|
153
|
-
├───┬────┬────┬────┬────┬───────────┬────────┬──────────┬────────────┤
|
|
154
|
-
│ ∑ │ TP │ TN │ FP │ FN │ precision │ recall │ timeMean │ timeMedian │
|
|
155
|
-
├───┼────┼────┼────┼────┼───────────┼────────┼──────────┼────────────┤
|
|
156
|
-
│ 5 │ 3 │ 0 │ 2 │ 0 │ 0.60 │ 1.00 │ 1.23ms │ 1.28ms │
|
|
157
|
-
├───┼────┼────┼────┼────┼───────────┼────────┼──────────┼────────────┤
|
|
158
|
-
│ ∑ │ TP │ TN │ FP │ FN │ precision │ recall │ timeMean │ timeMedian │
|
|
159
|
-
└───┴────┴────┴────┴────┴───────────┴────────┴──────────┴────────────┘
|
|
181
|
+
```ts
|
|
182
|
+
evaluate: (result, expected) => [
|
|
183
|
+
{key: 'result', result, expected, label: classify(result, expected)},
|
|
184
|
+
],
|
|
160
185
|
```
|
|
161
186
|
|
|
162
|
-
|
|
187
|
+
Suites that use the default comparison and omit `classify` need no changes.
|
|
188
|
+
Cached results keep their saved values and labels. Run the suite again after
|
|
189
|
+
changing `evaluate` to produce new results.
|
|
163
190
|
|
|
164
|
-
|
|
191
|
+
The same `schemas` decode current and previous runs. If you change the stored
|
|
192
|
+
result or expected-value shape and your schemas cannot read older values, use
|
|
193
|
+
a new suite name for the new shape.
|
|
165
194
|
|
|
195
|
+
### CLI Commands
|
|
196
|
+
|
|
197
|
+
#### Summarize
|
|
198
|
+
|
|
199
|
+
```sh
|
|
200
|
+
pnpx tsx my-test-suite.ts summarize
|
|
166
201
|
```
|
|
167
|
-
pnpx tsx my-test-suite.ts summarize --tags foo,bar
|
|
168
|
-
```
|
|
169
202
|
|
|
170
|
-
|
|
203
|
+
#### Filter Results
|
|
204
|
+
|
|
205
|
+
Both `summarize` and `diff` accept these filters:
|
|
206
|
+
|
|
207
|
+
| Flag | Includes a result when… |
|
|
208
|
+
| --- | --- |
|
|
209
|
+
| `--keys budget,need` | Its key is `budget` or `need`. |
|
|
210
|
+
| `--labels FP,FN` | Its current label is `FP` or `FN`. |
|
|
211
|
+
| `--tags enterprise,german` | Its case has either tag. |
|
|
212
|
+
| `--all-tags enterprise,german` | Its case has both tags. |
|
|
213
|
+
|
|
214
|
+
Different flags combine with AND. For example, show budget errors from
|
|
215
|
+
enterprise cases:
|
|
171
216
|
|
|
217
|
+
```sh
|
|
218
|
+
pnpx tsx bant-suite.ts summarize --keys budget --labels FP,FN --tags enterprise
|
|
172
219
|
```
|
|
173
|
-
|
|
220
|
+
|
|
221
|
+
For the basic example, show matching results:
|
|
222
|
+
|
|
223
|
+
```sh
|
|
224
|
+
pnpx tsx my-test-suite.ts summarize --labels TP
|
|
174
225
|
```
|
|
175
226
|
|
|
176
|
-
|
|
227
|
+
Filters change the displayed rows and statistics. The CLI runs and saves all
|
|
228
|
+
evaluations before applying them, so filtering does not discard saved results
|
|
229
|
+
or reduce the number of program calls. No matches produces an empty view;
|
|
230
|
+
`summarize` also reports zero counts.
|
|
177
231
|
|
|
178
232
|
#### Summarize From Cache
|
|
179
233
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
234
|
+
When results for the current run are already saved, `--cached` reads them
|
|
235
|
+
without re-running the program or evaluator. If no cached results exist, it
|
|
236
|
+
runs and saves the suite. After the first run, use it to inspect other keys
|
|
237
|
+
without making another inference call:
|
|
183
238
|
|
|
184
|
-
```
|
|
185
|
-
pnpx tsx
|
|
239
|
+
```sh
|
|
240
|
+
pnpx tsx bant-suite.ts summarize --cached --keys budget,need
|
|
186
241
|
```
|
|
187
242
|
|
|
188
243
|
`diff --cached` behaves the same way for the current-run side of the diff.
|
|
@@ -196,6 +251,7 @@ pnpx tsx my-test-suite.ts commit
|
|
|
196
251
|
#### Diff
|
|
197
252
|
|
|
198
253
|
The diff command compares your current test results with previously committed results. This is useful when you've made changes to either:
|
|
254
|
+
|
|
199
255
|
- Your test suite's inputs or expected values
|
|
200
256
|
- The implementation of the function being tested
|
|
201
257
|
|
|
@@ -205,67 +261,40 @@ index 21cd713..ab1b6dc 100644
|
|
|
205
261
|
--- a/my-test-suite.ts
|
|
206
262
|
+++ b/my-test-suite.ts
|
|
207
263
|
@@ -1,7 +1,7 @@
|
|
208
|
-
import * as CLI from '@creative-introvert/
|
|
264
|
+
import * as CLI from '@creative-introvert/tons-of-tests-cli';
|
|
209
265
|
import {Effect} from 'effect';
|
|
210
266
|
|
|
211
267
|
-const myFunction = (input: number) => Promise.resolve(input * 1.7);
|
|
212
268
|
+const myFunction = (input: number) => Promise.resolve(input * 2);
|
|
213
269
|
|
|
214
|
-
|
|
270
|
+
CLI.run({
|
|
215
271
|
testSuite: {
|
|
216
272
|
```
|
|
217
273
|
|
|
218
|
-
```
|
|
274
|
+
```sh
|
|
219
275
|
pnpx tsx my-test-suite.ts diff
|
|
220
|
-
#
|
|
276
|
+
# Exit with code 1 when the filtered view contains differences.
|
|
221
277
|
pnpx tsx my-test-suite.ts diff --exit-on-diff
|
|
222
|
-
|
|
223
|
-
┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
|
224
|
-
│ SUMMARY │
|
|
225
|
-
├─────┬──────────┬────────┬──────┬───────┬──────────┬────────┬──────────────┬─────────┬───────────────┤
|
|
226
|
-
│ #/∑ │ hash │ ms │ tags │ input │ expected │ label₀ │ diff result₀ │ label₋₁ │ diff result₋₁ │
|
|
227
|
-
├─────┼──────────┼────────┼──────┼───────┼──────────┼────────┼──────────────┼─────────┼───────────────┤
|
|
228
|
-
│ 1/4 │ 562e2cca │ 0.23ms │ │ 1 │ 2 │ TP │ │ FP │ 2 => 1.7 │
|
|
229
|
-
├─────┼──────────┼────────┼──────┼───────┼──────────┼────────┼──────────────┼─────────┼───────────────┤
|
|
230
|
-
│ 2/4 │ a5afd52f │ 3.66ms │ │ 2 │ 3 │ FP │ 3 => 4 │ FP │ 3 => 3.4 │
|
|
231
|
-
├─────┼──────────┼────────┼──────┼───────┼──────────┼────────┼──────────────┼─────────┼───────────────┤
|
|
232
|
-
│ 3/4 │ 5f7f8725 │ 1.19ms │ │ 3 │ 4 │ FP │ 4 => 6 │ FP │ 4 => 5.1 │
|
|
233
|
-
├─────┼──────────┼────────┼──────┼───────┼──────────┼────────┼──────────────┼─────────┼───────────────┤
|
|
234
|
-
│ 4/4 │ 6cc26923 │ 0.98ms │ │ 4 │ 5 │ FP │ 5 => 8 │ FP │ 5 => 6.8 │
|
|
235
|
-
├─────┼──────────┼────────┼──────┼───────┼──────────┼────────┼──────────────┼─────────┼───────────────┤
|
|
236
|
-
│ #/∑ │ hash │ ms │ tags │ input │ expected │ label₀ │ diff result₀ │ label₋₁ │ diff result₋₁ │
|
|
237
|
-
└─────┴──────────┴────────┴──────┴───────┴──────────┴────────┴──────────────┴─────────┴───────────────┘
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
┌────────────────────────────────────────────────────────────────────┐
|
|
241
|
-
│ STATS │
|
|
242
|
-
├───┬────┬────┬────┬────┬───────────┬────────┬──────────┬────────────┤
|
|
243
|
-
│ ∑ │ TP │ TN │ FP │ FN │ precision │ recall │ timeMean │ timeMedian │
|
|
244
|
-
├───┼────┼────┼────┼────┼───────────┼────────┼──────────┼────────────┤
|
|
245
|
-
│ 5 │ 2 │ 0 │ 3 │ 0 │ 0.40 │ 1.00 │ 1.30ms │ 0.98ms │
|
|
246
|
-
├───┼────┼────┼────┼────┼───────────┼────────┼──────────┼────────────┤
|
|
247
|
-
│ ∑ │ TP │ TN │ FP │ FN │ precision │ recall │ timeMean │ timeMedian │
|
|
248
|
-
└───┴────┴────┴────┴────┴───────────┴────────┴──────────┴────────────┘
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
┌────────────────────────────────────────┐
|
|
252
|
-
│ DIFF │
|
|
253
|
-
├────┬────┬────┬────┬───────────┬────────┤
|
|
254
|
-
│ TP │ TN │ FP │ FN │ precision │ recall │
|
|
255
|
-
├────┼────┼────┼────┼───────────┼────────┤
|
|
256
|
-
│ 1 │ 0 │ -1 │ 0 │ 0.20 │ 0.00 │
|
|
257
|
-
├────┼────┼────┼────┼───────────┼────────┤
|
|
258
|
-
│ TP │ TN │ FP │ FN │ precision │ recall │
|
|
259
|
-
└────┴────┴────┴────┴───────────┴────────┘
|
|
260
278
|
```
|
|
261
279
|
|
|
262
|
-
|
|
280
|
+
For a suite with several results per case, select the keys to compare:
|
|
263
281
|
|
|
282
|
+
```sh
|
|
283
|
+
pnpx tsx bant-suite.ts diff --keys budget --labels FP,FN
|
|
264
284
|
```
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
285
|
+
|
|
286
|
+
`diff` matches results by case hash and key before applying filters. It includes
|
|
287
|
+
new results and changes to a result's value, expected value, or label. A current
|
|
288
|
+
`FP` result keeps its previous value and label even when that previous label
|
|
289
|
+
does not match `--labels`.
|
|
290
|
+
|
|
291
|
+
See [workspace/examples/src/with-cli](./workspace/examples/src/with-cli) for
|
|
292
|
+
more examples. From the repository root, run:
|
|
293
|
+
|
|
294
|
+
```sh
|
|
295
|
+
direnv exec . pnpm exec tsx workspace/examples/src/with-cli/simple-run.ts summarize
|
|
296
|
+
direnv exec . pnpm exec tsx workspace/examples/src/with-cli/simple-effect.ts
|
|
297
|
+
direnv exec . pnpm exec tsx workspace/examples/src/with-cli/multiple-results.ts summarize --keys budget,need
|
|
269
298
|
```
|
|
270
299
|
|
|
271
300
|
### Using the CLI programmatically
|
|
@@ -318,16 +347,10 @@ const hash = await CLI.getLastTestRunHash({
|
|
|
318
347
|
// hash: string | null
|
|
319
348
|
```
|
|
320
349
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
```ts
|
|
326
|
-
import {DiffNonEmpty} from '@creative-introvert/tons-of-tests-cli';
|
|
327
|
-
|
|
328
|
-
// ... compose _diff into your own Effect pipeline, then:
|
|
329
|
-
Effect.catchTag('DiffNonEmpty', () => /* handle */);
|
|
330
|
-
```
|
|
350
|
+
When you use `CLI.effect`, `diff --exit-on-diff` fails with a typed
|
|
351
|
+
`DiffNonEmpty` error when the current run has visible diffs. Handle it with
|
|
352
|
+
`Effect.catchTag('DiffNonEmpty', handler)`; `error.count` gives the number of
|
|
353
|
+
visible changed results.
|
|
331
354
|
|
|
332
355
|
At the process entry point (`CLI.run`), `DiffNonEmpty` is translated to
|
|
333
356
|
`process.exitCode = 1` — the user-facing "exit with code 1 on diff"
|
package/dist/cjs/Classify.js
CHANGED
|
@@ -13,12 +13,16 @@ const values = exports.values = internal.values;
|
|
|
13
13
|
const defaultIsEqual = exports.defaultIsEqual = internal.defaultIsEqual;
|
|
14
14
|
const defaultIsNil = exports.defaultIsNil = internal.defaultIsNil;
|
|
15
15
|
const makeClassify = exports.makeClassify = internal.makeClassify;
|
|
16
|
+
/** Counts selected results; timing statistics count each selected case once. */
|
|
16
17
|
class Stats extends /*#__PURE__*/_effect.Schema.Class('Stats')({
|
|
17
18
|
TP: _effect.Schema.Finite,
|
|
18
19
|
TN: _effect.Schema.Finite,
|
|
19
20
|
FP: _effect.Schema.Finite,
|
|
20
21
|
FN: _effect.Schema.Finite,
|
|
22
|
+
/** Number of evaluation results. */
|
|
21
23
|
total: _effect.Schema.Finite,
|
|
24
|
+
/** Number of distinct original test cases represented by those results. */
|
|
25
|
+
testCases: _effect.Schema.Int,
|
|
22
26
|
precision: _effect.Schema.Finite,
|
|
23
27
|
recall: _effect.Schema.Finite,
|
|
24
28
|
timeMin: /*#__PURE__*/_effect.Schema.Option(_effect.Schema.Finite),
|
|
@@ -33,6 +37,7 @@ class Stats extends /*#__PURE__*/_effect.Schema.Class('Stats')({
|
|
|
33
37
|
FP: 0,
|
|
34
38
|
FN: 0,
|
|
35
39
|
total: 0,
|
|
40
|
+
testCases: 0,
|
|
36
41
|
precision: 0,
|
|
37
42
|
recall: 0,
|
|
38
43
|
timeMin: _effect.Option.none(),
|
package/dist/cjs/Classify.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Classify.js","names":["_effect","require","internal","_interopRequireWildcard","cache","e","t","__esModule","r","c","a","Object","defineProperty","n","__proto__","default","WeakMap","has","get","set","hasOwnProperty","call","getOwnPropertyDescriptor","LabelSchema","exports","values","defaultIsEqual","defaultIsNil","makeClassify","Stats","Schema","Class","TP","Finite","TN","FP","FN","total","precision","recall","timeMin","Option","timeMax","timeMedian","timeMean","empty","none"],"sources":["../../src/Classify.ts"],"sourcesContent":[null],"mappings":";;;;;;AAAA,IAAAA,OAAA,gBAAAC,OAAA;AAEA,IAAAC,QAAA,gBAAAC,uBAAA,cAAAF,OAAA;AAAmD,IAAAG,KAAA;AAAA,SAAAD,wBAAAE,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAE,UAAA,SAAAF,CAAA,MAAAG,CAAA,EAAAC,CAAA,EAAAC,CAAA,GAAAC,MAAA,CAAAC,cAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,QAAAM,MAAA,CAAAN,CAAA,MAAAA,CAAA,SAAAQ,CAAA,MAAAT,KAAA,yBAAAY,OAAA,KAAAZ,KAAA,OAAAY,OAAA,KAAAZ,KAAA,QAAAA,KAAA,CAAAa,GAAA,CAAAZ,CAAA,UAAAD,KAAA,CAAAc,GAAA,CAAAb,CAAA,GAAAD,KAAA,CAAAe,GAAA,CAAAd,CAAA,EAAAQ,CAAA,UAAAJ,CAAA,IAAAJ,CAAA,gBAAAI,CAAA,OAAAW,cAAA,CAAAC,IAAA,CAAAhB,CAAA,EAAAI,CAAA,OAAAD,CAAA,GAAAE,CAAA,IAAAC,MAAA,CAAAW,wBAAA,CAAAjB,CAAA,EAAAI,CAAA,OAAAD,CAAA,CAAAU,GAAA,IAAAV,CAAA,CAAAW,GAAA,IAAAT,CAAA,CAAAG,CAAA,EAAAJ,CAAA,EAAAD,CAAA,IAAAK,CAAA,CAAAJ,CAAA,IAAAJ,CAAA,CAAAI,CAAA,WAAAI,CAAA;AAE5C,MAAMU,WAAW,GAAAC,OAAA,CAAAD,WAAA,GAAGrB,QAAQ,CAACqB,WAAW;AAGxC,MAAME,MAAM,GAAAD,OAAA,CAAAC,MAAA,GAAGvB,QAAQ,CAACuB,MAAM;AAC9B,MAAMC,cAAc,GAAAF,OAAA,CAAAE,cAAA,GAAGxB,QAAQ,CAACwB,cAAc;AAC9C,MAAMC,YAAY,GAAAH,OAAA,CAAAG,YAAA,GAAGzB,QAAQ,CAACyB,YAAY;AAC1C,MAAMC,YAAY,GAAAJ,OAAA,CAAAI,YAAA,GAAG1B,QAAQ,CAAC0B,YAAY;
|
|
1
|
+
{"version":3,"file":"Classify.js","names":["_effect","require","internal","_interopRequireWildcard","cache","e","t","__esModule","r","c","a","Object","defineProperty","n","__proto__","default","WeakMap","has","get","set","hasOwnProperty","call","getOwnPropertyDescriptor","LabelSchema","exports","values","defaultIsEqual","defaultIsNil","makeClassify","Stats","Schema","Class","TP","Finite","TN","FP","FN","total","testCases","Int","precision","recall","timeMin","Option","timeMax","timeMedian","timeMean","empty","none"],"sources":["../../src/Classify.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
package/dist/cjs/Test.js
CHANGED
|
@@ -3,12 +3,16 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.runCollectRecord = exports.makeSha256 = exports.diff = exports.all = void 0;
|
|
6
|
+
exports.runCollectRecord = exports.resultKey = exports.makeSha256 = exports.filterResults = exports.diff = exports.all = void 0;
|
|
7
7
|
var internal = /*#__PURE__*/_interopRequireWildcard(/*#__PURE__*/require("./internal/Test.js"));
|
|
8
8
|
var cache;
|
|
9
9
|
function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var r, c, a = Object.defineProperty, n = { __proto__: null, default: e }; if (Object(e) !== e) return n; if (cache || "function" != typeof WeakMap || (cache = new WeakMap()), cache) { if (cache.has(e)) return cache.get(e); cache.set(e, n); } for (c in e) "default" !== c && {}.hasOwnProperty.call(e, c) && ((r = a && Object.getOwnPropertyDescriptor(e, c)) && (r.get || r.set) ? a(n, c, r) : n[c] = e[c]); return n; }
|
|
10
10
|
const all = exports.all = internal.all;
|
|
11
11
|
const diff = exports.diff = internal.diff;
|
|
12
12
|
const makeSha256 = exports.makeSha256 = internal.makeSha256;
|
|
13
|
+
/** Builds the lookup key for one evaluation within its original test case. */
|
|
14
|
+
const resultKey = exports.resultKey = internal.resultKey;
|
|
13
15
|
const runCollectRecord = exports.runCollectRecord = internal.runCollectRecord;
|
|
16
|
+
/** Keeps matching results and recalculates counts and case timing statistics. */
|
|
17
|
+
const filterResults = exports.filterResults = internal.filterResults;
|
|
14
18
|
//# sourceMappingURL=Test.js.map
|
package/dist/cjs/Test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Test.js","names":["internal","_interopRequireWildcard","require","cache","e","t","__esModule","r","c","a","Object","defineProperty","n","__proto__","default","WeakMap","has","get","set","hasOwnProperty","call","getOwnPropertyDescriptor","all","exports","diff","makeSha256","runCollectRecord"],"sources":["../../src/Test.ts"],"sourcesContent":[null],"mappings":";;;;;;AAGA,IAAAA,QAAA,gBAAAC,uBAAA,cAAAC,OAAA;AAA+C,IAAAC,KAAA;AAAA,SAAAF,wBAAAG,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAE,UAAA,SAAAF,CAAA,MAAAG,CAAA,EAAAC,CAAA,EAAAC,CAAA,GAAAC,MAAA,CAAAC,cAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,QAAAM,MAAA,CAAAN,CAAA,MAAAA,CAAA,SAAAQ,CAAA,MAAAT,KAAA,yBAAAY,OAAA,KAAAZ,KAAA,OAAAY,OAAA,KAAAZ,KAAA,QAAAA,KAAA,CAAAa,GAAA,CAAAZ,CAAA,UAAAD,KAAA,CAAAc,GAAA,CAAAb,CAAA,GAAAD,KAAA,CAAAe,GAAA,CAAAd,CAAA,EAAAQ,CAAA,UAAAJ,CAAA,IAAAJ,CAAA,gBAAAI,CAAA,OAAAW,cAAA,CAAAC,IAAA,CAAAhB,CAAA,EAAAI,CAAA,OAAAD,CAAA,GAAAE,CAAA,IAAAC,MAAA,CAAAW,wBAAA,CAAAjB,CAAA,EAAAI,CAAA,OAAAD,CAAA,CAAAU,GAAA,IAAAV,CAAA,CAAAW,GAAA,IAAAT,CAAA,CAAAG,CAAA,EAAAJ,CAAA,EAAAD,CAAA,IAAAK,CAAA,CAAAJ,CAAA,IAAAJ,CAAA,CAAAI,CAAA,WAAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"Test.js","names":["internal","_interopRequireWildcard","require","cache","e","t","__esModule","r","c","a","Object","defineProperty","n","__proto__","default","WeakMap","has","get","set","hasOwnProperty","call","getOwnPropertyDescriptor","all","exports","diff","makeSha256","resultKey","runCollectRecord","filterResults"],"sources":["../../src/Test.ts"],"sourcesContent":[null],"mappings":";;;;;;AAGA,IAAAA,QAAA,gBAAAC,uBAAA,cAAAC,OAAA;AAA+C,IAAAC,KAAA;AAAA,SAAAF,wBAAAG,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAE,UAAA,SAAAF,CAAA,MAAAG,CAAA,EAAAC,CAAA,EAAAC,CAAA,GAAAC,MAAA,CAAAC,cAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,QAAAM,MAAA,CAAAN,CAAA,MAAAA,CAAA,SAAAQ,CAAA,MAAAT,KAAA,yBAAAY,OAAA,KAAAZ,KAAA,OAAAY,OAAA,KAAAZ,KAAA,QAAAA,KAAA,CAAAa,GAAA,CAAAZ,CAAA,UAAAD,KAAA,CAAAc,GAAA,CAAAb,CAAA,GAAAD,KAAA,CAAAe,GAAA,CAAAd,CAAA,EAAAQ,CAAA,UAAAJ,CAAA,IAAAJ,CAAA,gBAAAI,CAAA,OAAAW,cAAA,CAAAC,IAAA,CAAAhB,CAAA,EAAAI,CAAA,OAAAD,CAAA,GAAAE,CAAA,IAAAC,MAAA,CAAAW,wBAAA,CAAAjB,CAAA,EAAAI,CAAA,OAAAD,CAAA,CAAAU,GAAA,IAAAV,CAAA,CAAAW,GAAA,IAAAT,CAAA,CAAAG,CAAA,EAAAJ,CAAA,EAAAD,CAAA,IAAAK,CAAA,CAAAJ,CAAA,IAAAJ,CAAA,CAAAI,CAAA,WAAAI,CAAA;AAyGxC,MAAMU,GAAG,GAAAC,OAAA,CAAAD,GAAA,GAAGtB,QAAQ,CAACsB,GAAG;AACxB,MAAME,IAAI,GAAAD,OAAA,CAAAC,IAAA,GAAGxB,QAAQ,CAACwB,IAAI;AAC1B,MAAMC,UAAU,GAAAF,OAAA,CAAAE,UAAA,GAAGzB,QAAQ,CAACyB,UAAU;AAC7C;AACO,MAAMC,SAAS,GAAAH,OAAA,CAAAG,SAAA,GAAG1B,QAAQ,CAAC0B,SAAS;AACpC,MAAMC,gBAAgB,GAAAJ,OAAA,CAAAI,gBAAA,GAAG3B,QAAQ,CAAC2B,gBAAgB;AACzD;AACO,MAAMC,aAAa,GAAAL,OAAA,CAAAK,aAAA,GAAG5B,QAAQ,CAAC4B,aAAa","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Test.repository.types.js","names":["_effect","require","TestRun","Schema","Class","id","Int","name","String","hash","NullOr","exports"],"sources":["../../src/Test.repository.types.ts"],"sourcesContent":[null],"mappings":";;;;;;AAAA,IAAAA,OAAA,gBAAAC,OAAA;
|
|
1
|
+
{"version":3,"file":"Test.repository.types.js","names":["_effect","require","TestRun","Schema","Class","id","Int","name","String","hash","NullOr","exports"],"sources":["../../src/Test.repository.types.ts"],"sourcesContent":[null],"mappings":";;;;;;AAAA,IAAAA,OAAA,gBAAAC,OAAA;AAoBM,MAAOC,OAAQ,sBAAQC,cAAM,CAACC,KAAK,CAAU,SAAS,CAAC,CAAC;EAC1DC,EAAE,EAAEF,cAAM,CAACG,GAAG;EACdC,IAAI,EAAEJ,cAAM,CAACK,MAAM;EACnBC,IAAI,eAAEN,cAAM,CAACO,MAAM,CAACP,cAAM,CAACK,MAAM;CACpC,CAAC;AAAGG,OAAA,CAAAT,OAAA,GAAAA,OAAA","ignoreList":[]}
|