summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnaud Bailly <arnaud@pankzsoft.com>2025-11-15 09:33:09 +0100
committerArnaud Bailly <arnaud@pankzsoft.com>2025-11-15 09:33:09 +0100
commit57472750c9cd14b9907895e5269b3be01819c7b3 (patch)
tree093728bce8c71dad24f9e2665dc70ff7f1b60f35
parent208fd364a9a8bdc0e12993ace4f1829303548476 (diff)
downloadlambda-nantes-57472750c9cd14b9907895e5269b3be01819c7b3.tar.gz
[pbt] expose simpler interface Property.run
-rw-r--r--pbt/ts/package.json1
-rw-r--r--pbt/ts/src/index.test.ts4
-rw-r--r--pbt/ts/src/index.ts7
-rw-r--r--pbt/ts/src/property.ts47
4 files changed, 34 insertions, 25 deletions
diff --git a/pbt/ts/package.json b/pbt/ts/package.json
index b7585fc..ff17a45 100644
--- a/pbt/ts/package.json
+++ b/pbt/ts/package.json
@@ -14,6 +14,7 @@
},
"scripts": {
"test": "jest",
+ "watch": "jest --watch",
"lint": "gts lint",
"clean": "gts clean",
"compile": "tsc",
diff --git a/pbt/ts/src/index.test.ts b/pbt/ts/src/index.test.ts
index deb55ec..58f5119 100644
--- a/pbt/ts/src/index.test.ts
+++ b/pbt/ts/src/index.test.ts
@@ -1,9 +1,9 @@
-import Prando from 'prando';
import { prop_reverse_with_two_lists } from './index';
+import { Property } from './property';
describe('testing lists reversal', () => {
test('reverse of two appended lists is append of each list reversed', () => {
- let reverse_append_result = prop_reverse_with_two_lists(new Prando(Math.random() * 1000), 0);
+ let reverse_append_result = Property.run(prop_reverse_with_two_lists);
expect(reverse_append_result).toBe(true);
});
});
diff --git a/pbt/ts/src/index.ts b/pbt/ts/src/index.ts
index cb7fd6e..25b97aa 100644
--- a/pbt/ts/src/index.ts
+++ b/pbt/ts/src/index.ts
@@ -1,6 +1,6 @@
import "dotenv/config";
import Prando from 'prando';
-import { Gen, listOf, property, shrinklist, someInt } from "./property";
+import { Gen, Property, listOf, property, shrinklist, someInt } from "./property";
function arrayEquals<A>(a: A[], b: A[]): boolean {
return Array.isArray(a) &&
@@ -54,9 +54,8 @@ let prop_reverse_is_self_inverse =
property(reverse_is_self_inverse, listOf(someInt), shrinklist);
async function main() {
- let rng = new Prando(Math.random() * 1000);
- let reverse_append_result = prop_reverse_with_two_lists(rng, 0);
- let reverse_reverse_result = prop_reverse_is_self_inverse(rng, 0);
+ let reverse_append_result = Property.run(prop_reverse_with_two_lists);
+ let reverse_reverse_result = Property.run(prop_reverse_is_self_inverse);
console.log('reverse_append_result: ' + JSON.stringify(reverse_append_result));
console.log('reverse_reverse_result: ' + JSON.stringify(reverse_reverse_result));
};
diff --git a/pbt/ts/src/property.ts b/pbt/ts/src/property.ts
index d4eea28..7714747 100644
--- a/pbt/ts/src/property.ts
+++ b/pbt/ts/src/property.ts
@@ -5,6 +5,7 @@ type Result = 'OK' | 'Falsified' | 'Exception';
type ShrinkResult<A> = { counterexample: A, shrinks: number };
type TestResult<A> = {
+ seed: number | null,
result: Result,
counterexample: ShrinkResult<A> | null
};
@@ -15,8 +16,8 @@ export type Gen<A> = (rng: Prando) => ((size: number) => A);
type Shrinker<A> = (a: A) => A[];
-type Property<A> = (rng: Prando,
- size: number) => TestResult<A>;
+type Property<A> = (seed: number,
+ size: number) => TestResult<A>;
const MAX_SUCCESS = 100;
@@ -49,20 +50,21 @@ export function property<A>(
predicate: Predicate<A>,
generator: Gen<A>,
shrinker: Shrinker<A>): Property<A> {
- return (rng: Prando,
- size: number) => {
- let gen = generator(rng);
- let i = 0;
- for (; i < MAX_SUCCESS; i++) {
- let x = gen(size);
- if (!predicate(x)) {
- let counterexample = findMinimalCounterExample(x, predicate, shrinker);
- return { result: 'Falsified', tests: i+1, counterexample };
- }
- size++;
- }
- return { result: 'OK', tests: i, counterexample: null };
- };
+ return (seed: number,
+ size: number) => {
+ let rng = new Prando(seed);
+ let gen = generator(rng);
+ let i = 0;
+ for (; i < MAX_SUCCESS; i++) {
+ let x = gen(size);
+ if (!predicate(x)) {
+ let counterexample = findMinimalCounterExample(x, predicate, shrinker);
+ return { seed, result: 'Falsified', tests: i + 1, counterexample };
+ }
+ size++;
+ }
+ return { seed, result: 'OK', tests: i, counterexample: null };
+ };
}
// basic generators
@@ -86,9 +88,9 @@ export function shrinklist<A>(arr: A[]): A[][] {
let tail = arr.slice(1);
let keep1 = arr.slice();
keep1.splice(1, 1);
- result.push(tail,keep1);
+ result.push(tail, keep1);
- if (arr.length >3) {
+ if (arr.length > 3) {
let half = Math.floor(arr.length / 2);
let copy = arr.slice();
let secondHalf = copy.slice(half);
@@ -98,6 +100,13 @@ export function shrinklist<A>(arr: A[]): A[][] {
return result;
}
-export let someInt : Gen<number> = (rng: Prando) =>
+export let someInt: Gen<number> = (rng: Prando) =>
(size: number) =>
rng.nextInt(-size, size);
+
+export const Property = {
+ run<A>(prop: Property<A>): TestResult<A> {
+ let seed = Math.floor(Math.random() * 1000000);
+ return prop(seed, 0);
+ }
+};