summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnaud Bailly <arnaud.bailly@iohk.io>2025-01-26 12:25:24 +0100
committerArnaud Bailly <arnaud.bailly@iohk.io>2025-01-26 12:25:24 +0100
commitb8d51740ef8236639b7ac1eada6cf1a64750529a (patch)
tree7fb3b678479f9da10b3eee81fef679525e75f323
parentcc78d5d55b6e1a941b4f4d99c28e35f1363dbcab (diff)
downloadlambda-nantes-b8d51740ef8236639b7ac1eada6cf1a64750529a.tar.gz
Move shared code to library
-rw-r--r--pbt/README.md1
-rw-r--r--pbt/ts/src/index.ts44
-rw-r--r--pbt/ts/src/property.ts37
3 files changed, 42 insertions, 40 deletions
diff --git a/pbt/README.md b/pbt/README.md
index 4832394..308ebd9 100644
--- a/pbt/README.md
+++ b/pbt/README.md
@@ -75,3 +75,4 @@ Quelques liens intéressants glanés au fil de mes recherches sur le sujet :
* [Using relational problems to teach PBT](https://cs.brown.edu/~tbn/publications/wnk-pj20-pbt.pdf) : une étude sur l'impact de l'apprentissage du PBT (par exemple sur un [tri topologique](https://cs.brown.edu/courses/cs195y/2019/historical/oracle.pdf))
* [Choosing properties for PBT](https://fsharpforfunandprofit.com/posts/property-based-testing-2/)
* [PBT in practice](https://harrisongoldste.in/papers/icse24-pbt-in-practice.pdf): une étude à base d'entretiens sur l'efficacité _en pratique_ du PBT
+* [Integrated vs. type-based shrinking](https://hypothesis.works/articles/integrated-shrinking/) : un post du créateur d'[hypothesis](https://hypothesis.works), outil de PBT en Python, justifiant la _minimisation intégrée_
diff --git a/pbt/ts/src/index.ts b/pbt/ts/src/index.ts
index c6fc73a..1e9b8c0 100644
--- a/pbt/ts/src/index.ts
+++ b/pbt/ts/src/index.ts
@@ -1,11 +1,6 @@
import "dotenv/config";
import Prando from 'prando';
-import { Gen, property } from "./property";
-
-let genint: Gen<number> = (rng: Prando) =>
- (size: number) =>
- rng.nextInt(-size, size);
-
+import { Gen, listOf, property, shrinklist, someInt } from "./property";
function arrayEquals<A>(a: A[], b: A[]): boolean {
return Array.isArray(a) &&
@@ -14,19 +9,6 @@ function arrayEquals<A>(a: A[], b: A[]): boolean {
a.every((val, index) => val === b[index]);
}
-function genlist<A>(gen: Gen<A>): Gen<A[]> {
- return (rng: Prando) => {
- let g = gen(rng);
- return (size: number) => {
- let result = [];
- for (let i = 0; i < size; i++) {
- result.push(g(size));
- }
- return result;
- };
- };
-}
-
function reverse<A>(arr: A[]): A[] {
let result = [];
for (let i = arr.length - 1; i >= 0; i--) {
@@ -39,27 +21,9 @@ function reverse_is_self_inverse(arr: number[]): boolean {
return arrayEquals(reverse(reverse(arr)), arr);
}
-function shrinklist<A>(arr: A[]): A[][] {
- let result = [];
-
- let tail = arr.slice(1);
- let keep1 = arr.slice();
- keep1.splice(1, 1);
- result.push(tail,keep1);
-
- if (arr.length >3) {
- let half = Math.floor(arr.length / 2);
- let copy = arr.slice();
- let secondHalf = copy.slice(half);
- result.push(secondHalf);
- }
-
- return result;
-}
-
function gen2lists<A>(gen: Gen<A>): Gen<[A[], A[]]> {
return (rng: Prando) => {
- let gl = genlist(gen)(rng);
+ let gl = listOf(gen)(rng);
return (size: number) => {
return [gl(size), gl(size)]
};
@@ -84,10 +48,10 @@ function shrink2lists<A>([l1, l2]: [A[], A[]]): [A[], A[]][] {
}
let prop_reverse_with_two_lists =
- property<[number[], number[]]>(reverse_with_two_lists, gen2lists(genint), shrink2lists);
+ property<[number[], number[]]>(reverse_with_two_lists, gen2lists(someInt), shrink2lists);
let prop_reverse_is_self_inverse =
- property(reverse_is_self_inverse, genlist(genint), shrinklist);
+ property(reverse_is_self_inverse, listOf(someInt), shrinklist);
async function main() {
let rng = new Prando(Math.random() * 1000);
diff --git a/pbt/ts/src/property.ts b/pbt/ts/src/property.ts
index a8c59ba..d4eea28 100644
--- a/pbt/ts/src/property.ts
+++ b/pbt/ts/src/property.ts
@@ -64,3 +64,40 @@ export function property<A>(
return { result: 'OK', tests: i, counterexample: null };
};
}
+
+// basic generators
+
+export function listOf<A>(gen: Gen<A>): Gen<A[]> {
+ return (rng: Prando) => {
+ let g = gen(rng);
+ return (size: number) => {
+ let result = [];
+ for (let i = 0; i < size; i++) {
+ result.push(g(size));
+ }
+ return result;
+ };
+ };
+}
+
+export function shrinklist<A>(arr: A[]): A[][] {
+ let result = [];
+
+ let tail = arr.slice(1);
+ let keep1 = arr.slice();
+ keep1.splice(1, 1);
+ result.push(tail,keep1);
+
+ if (arr.length >3) {
+ let half = Math.floor(arr.length / 2);
+ let copy = arr.slice();
+ let secondHalf = copy.slice(half);
+ result.push(secondHalf);
+ }
+
+ return result;
+}
+
+export let someInt : Gen<number> = (rng: Prando) =>
+ (size: number) =>
+ rng.nextInt(-size, size);