@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.
Files changed (44) hide show
  1. package/README.md +157 -134
  2. package/dist/cjs/Classify.js +5 -0
  3. package/dist/cjs/Classify.js.map +1 -1
  4. package/dist/cjs/Test.js +5 -1
  5. package/dist/cjs/Test.js.map +1 -1
  6. package/dist/cjs/Test.repository.types.js.map +1 -1
  7. package/dist/cjs/internal/Test.js +107 -54
  8. package/dist/cjs/internal/Test.js.map +1 -1
  9. package/dist/cjs/internal/Test.repository.sqlite.js +77 -20
  10. package/dist/cjs/internal/Test.repository.sqlite.js.map +1 -1
  11. package/dist/cjs/internal/stats.js +8 -2
  12. package/dist/cjs/internal/stats.js.map +1 -1
  13. package/dist/cjs/internal/summarize.js +18 -13
  14. package/dist/cjs/internal/summarize.js.map +1 -1
  15. package/dist/dts/Classify.d.ts +4 -0
  16. package/dist/dts/Classify.d.ts.map +1 -1
  17. package/dist/dts/Show.d.ts +3 -3
  18. package/dist/dts/Show.d.ts.map +1 -1
  19. package/dist/dts/Test.d.ts +46 -8
  20. package/dist/dts/Test.d.ts.map +1 -1
  21. package/dist/dts/Test.repository.d.ts +3 -3
  22. package/dist/dts/Test.repository.d.ts.map +1 -1
  23. package/dist/dts/Test.repository.types.d.ts +6 -0
  24. package/dist/dts/Test.repository.types.d.ts.map +1 -1
  25. package/dist/dts/internal/Test.d.ts +15 -10
  26. package/dist/dts/internal/Test.d.ts.map +1 -1
  27. package/dist/dts/internal/Test.repository.sqlite.d.ts +2 -1
  28. package/dist/dts/internal/Test.repository.sqlite.d.ts.map +1 -1
  29. package/dist/dts/internal/stats.d.ts.map +1 -1
  30. package/dist/dts/internal/summarize.d.ts.map +1 -1
  31. package/dist/esm/Classify.js +5 -0
  32. package/dist/esm/Classify.js.map +1 -1
  33. package/dist/esm/Test.js +4 -0
  34. package/dist/esm/Test.js.map +1 -1
  35. package/dist/esm/Test.repository.types.js.map +1 -1
  36. package/dist/esm/internal/Test.js +104 -53
  37. package/dist/esm/internal/Test.js.map +1 -1
  38. package/dist/esm/internal/Test.repository.sqlite.js +77 -20
  39. package/dist/esm/internal/Test.repository.sqlite.js.map +1 -1
  40. package/dist/esm/internal/stats.js +8 -2
  41. package/dist/esm/internal/stats.js.map +1 -1
  42. package/dist/esm/internal/summarize.js +18 -13
  43. package/dist/esm/internal/summarize.js.map +1 -1
  44. 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 and stored test hashes keep the same format.
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
- // `makeClassify` customises how observed vs. expected results are
64
- // labelled. `isEqual` decides TP/TN vs FP/FN — here we tolerate a
65
- // 0.4 absolute error, so `1.7` passes for `2`, etc.
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
- > Omit `classify` to get default strict equality; then every non-exact result is labelled FP.
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
- #### Summarize
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
- │ SUMMARY │
103
- ├─────┬──────────┬────────┬──────┬───────┬──────────┬────────┬──────────────┤
104
- │ #/∑ │ hash │ ms │ tags │ input │ expected │ label₀ │ diff result₀ │
105
- ├─────┼──────────┼────────┼──────┼───────┼──────────┼────────┼──────────────┤
106
- │ 1/5 │ bd04cb2c │ 0.69ms │ │ 0 │ 0 │ TP │ │
107
- ├─────┼──────────┼────────┼──────┼───────┼──────────┼────────┼──────────────┤
108
- │ 2/5 │ 562e2cca │ 0.36ms │ │ 1 │ 2 │ TP │ 2 => 1.7 │
109
- ├─────┼──────────┼────────┼──────┼───────┼──────────┼────────┼──────────────┤
110
- │ 3/5 │ a5afd52f │ 3.30ms │ │ 2 │ 3 │ TP │ 3 => 3.4 │
111
- ├─────┼──────────┼────────┼──────┼───────┼──────────┼────────┼──────────────┤
112
- │ 4/5 │ 5f7f8725 │ 1.19ms │ │ 3 │ 4 │ FP │ 4 => 5.1 │
113
- ├─────┼──────────┼────────┼──────┼───────┼──────────┼────────┼──────────────┤
114
- │ 5/5 │ 6cc26923 │ 1.22ms │ │ 4 │ 5 │ FP │ 5 => 6.8 │
115
- ├─────┼──────────┼────────┼──────┼───────┼──────────┼────────┼──────────────┤
116
- │ #/∑ │ hash │ ms │ tags │ input │ expected │ label₀ │ diff result₀ │
117
- └─────┴──────────┴────────┴──────┴───────┴──────────┴────────┴──────────────┘
118
-
119
-
120
- ┌────────────────────────────────────────────────────────────────────┐
121
- │ STATS │
122
- ├───┬────┬────┬────┬────┬───────────┬────────┬──────────┬────────────┤
123
- │ ∑ │ TP │ TN │ FP │ FN │ precision │ recall │ timeMean │ timeMedian │
124
- ├───┼────┼────┼────┼────┼───────────┼────────┼──────────┼────────────┤
125
- │ 5 │ 3 │ 0 │ 2 │ 0 │ 0.60 │ 1.00 │ 1.35ms │ 1.19ms │
126
- ├───┼────┼────┼────┼────┼───────────┼────────┼──────────┼────────────┤
127
- │ ∑ │ TP │ TN │ FP │ FN │ precision │ recall │ timeMean │ timeMedian │
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
- #### Summarize With Labels Filter
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
- pnpx tsx my-test-suite.ts summarize --labels TP
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
- │ SUMMARY │
138
- ├─────┬──────────┬────────┬──────┬───────┬──────────┬────────┬──────────────┤
139
- │ #/∑ │ hash │ ms │ tags │ input │ expected │ label₀ │ diff result₀ │
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
- #### Summarize With Tag Filters
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
- `--tags` includes results matching ANY of the listed tags (OR):
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
- `--all-tags` includes results matching ALL listed tags (AND):
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
- pnpx tsx my-test-suite.ts summarize --all-tags foo,bar
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
- Both flags compose with `--labels`.
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
- `--cached` reads the most recently inserted test results from the local DB
181
- instead of re-running the program. This is useful when you want to re-format
182
- or re-filter without incurring the cost of a full run:
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 my-test-suite.ts summarize --cached
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/tots-cli';
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
- void CLI.run({
270
+ CLI.run({
215
271
  testSuite: {
216
272
  ```
217
273
 
218
- ```
274
+ ```sh
219
275
  pnpx tsx my-test-suite.ts diff
220
- # or, if you want it to process.exit(1) on diff
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
- Checkout `workspace/examples/src/with-cli` for more examples.
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
- pnpx tsx <file-path>
266
- # e.g.
267
- pnpx tsx ./workspace/examples/src/with-cli/simple-run.ts
268
- pnpx tsx ./workspace/examples/src/with-cli/simple-effect.ts
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
- If you compose the CLI's `diff` programmatically (via `_diff` or a custom
322
- harness), `diff --exit-on-diff` fails with a typed `DiffNonEmpty` error
323
- when the current run has visible diffs:
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"
@@ -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(),
@@ -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;AAI3C,MAAOC,KAAM,sBAAQC,cAAM,CAACC,KAAK,CAAQ,OAAO,CAAC,CAAC;EACpDC,EAAE,EAAEF,cAAM,CAACG,MAAM;EACjBC,EAAE,EAAEJ,cAAM,CAACG,MAAM;EACjBE,EAAE,EAAEL,cAAM,CAACG,MAAM;EACjBG,EAAE,EAAEN,cAAM,CAACG,MAAM;EACjBI,KAAK,EAAEP,cAAM,CAACG,MAAM;EACpBK,SAAS,EAAER,cAAM,CAACG,MAAM;EACxBM,MAAM,EAAET,cAAM,CAACG,MAAM;EACrBO,OAAO,eAAEV,cAAM,CAACW,MAAM,CAACX,cAAM,CAACG,MAAM,CAAC;EACrCS,OAAO,eAAEZ,cAAM,CAACW,MAAM,CAACX,cAAM,CAACG,MAAM,CAAC;EACrCU,UAAU,eAAEb,cAAM,CAACW,MAAM,CAACX,cAAM,CAACG,MAAM,CAAC;EACxCW,QAAQ,eAAEd,cAAM,CAACW,MAAM,CAACX,cAAM,CAACG,MAAM;CACxC,CAAC;EACE,OAAOY,KAAKA,CAAA;IACR,OAAO,IAAIhB,KAAK,CAAC;MACbG,EAAE,EAAE,CAAC;MACLE,EAAE,EAAE,CAAC;MACLC,EAAE,EAAE,CAAC;MACLC,EAAE,EAAE,CAAC;MACLC,KAAK,EAAE,CAAC;MACRC,SAAS,EAAE,CAAC;MACZC,MAAM,EAAE,CAAC;MACTC,OAAO,EAAEC,cAAM,CAACK,IAAI,EAAE;MACtBJ,OAAO,EAAED,cAAM,CAACK,IAAI,EAAE;MACtBH,UAAU,EAAEF,cAAM,CAACK,IAAI,EAAE;MACzBF,QAAQ,EAAEH,cAAM,CAACK,IAAI;KACxB,CAAC;EACN;;AACHtB,OAAA,CAAAK,KAAA,GAAAA,KAAA","ignoreList":[]}
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
@@ -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;AAiExC,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;AACtC,MAAMC,gBAAgB,GAAAH,OAAA,CAAAG,gBAAA,GAAG1B,QAAQ,CAAC0B,gBAAgB","ignoreList":[]}
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;AAkBM,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":[]}
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":[]}