summaryrefslogtreecommitdiff
path: root/pbt/ts/src/property.ts
diff options
context:
space:
mode:
authorArnaud Bailly <arnaud@pankzsoft.com>2025-12-02 09:59:30 +0100
committerArnaud Bailly <arnaud@pankzsoft.com>2025-12-02 09:59:30 +0100
commit03dd55c022c6077b50429b33f2889bbcec9f0435 (patch)
tree7d9942a6f344ed119444672bbd0db850aa34dcd6 /pbt/ts/src/property.ts
parent67a318eeb886da7b9917d1809464dfdcb8f4e578 (diff)
downloadlambda-nantes-03dd55c022c6077b50429b33f2889bbcec9f0435.tar.gz
add simple classification
Diffstat (limited to 'pbt/ts/src/property.ts')
-rw-r--r--pbt/ts/src/property.ts39
1 files changed, 37 insertions, 2 deletions
diff --git a/pbt/ts/src/property.ts b/pbt/ts/src/property.ts
index 635e731..ea7a62b 100644
--- a/pbt/ts/src/property.ts
+++ b/pbt/ts/src/property.ts
@@ -9,6 +9,7 @@ type ShrinkResult<A> = {counterexample: A; shrinks: number};
type TestResult<A> = {
seed: number | null;
result: Result;
+ labels: string[];
counterexample: ShrinkResult<A> | null;
};
@@ -18,6 +19,28 @@ export type Gen<A> = (rng: Prando) => (size: number) => A;
type Shrinker<A> = (a: A) => A[];
+/// Label test input with some arbitrary string for classification purpose
+type Label<A> = (a: A) => string;
+
+/// classify test result
+export function classify<A>(results: TestResult<A>): [number, string][] {
+ if (results.labels.length == 0) return [];
+
+ const distribution = new Map<string, number>();
+ const result: [number, string][] = [];
+ results.labels.sort();
+ results.labels.forEach(s => {
+ const num = distribution.get(s) || 0;
+ distribution.set(s, num + 1);
+ });
+
+ distribution.forEach((v, k) => {
+ result.push([(v / results.labels.length) * 100.0, k]);
+ });
+
+ return result;
+}
+
type Property<A> = (seed: number, size: number) => Promise<TestResult<A>>;
const MAX_SUCCESS = 100;
@@ -57,10 +80,13 @@ export async function property<A>(
generator: Gen<A>,
predicate: Predicate<A>,
shrinker?: Shrinker<A>,
+ label?: Label<A>,
): Promise<Property<A>> {
return async (seed: number, size: number) => {
const rng = new Prando(seed);
const gen = generator(rng);
+ const labels: string[] = [];
+
let i = 0;
for (; i < MAX_SUCCESS; i++) {
const x = gen(size);
@@ -73,11 +99,20 @@ export async function property<A>(
shrinker,
);
}
- return {seed, result: 'Falsified', tests: i + 1, counterexample};
+ return {
+ seed,
+ result: 'Falsified',
+ tests: i + 1,
+ labels: [],
+ counterexample,
+ };
+ }
+ if (label !== undefined) {
+ labels.push(label(x));
}
size++;
}
- return {seed, result: 'OK', tests: i, counterexample: null};
+ return {seed, result: 'OK', tests: i, labels, counterexample: null};
};
}