Comparing version 0.5.0-beta.2 to 0.5.0
## Release History | ||
- **0.5.0** — *2014-12-24* Merry Chrismas 2014! | ||
- Documention cleanup | ||
- **0.5.0-beta.2** — *2014-12-21* — Beta 2! | ||
@@ -4,0 +6,0 @@ - Pair & tuple related code cleanup |
@@ -30,12 +30,11 @@ /* @flow weak */ | ||
/** | ||
- `array(arb: arbitrary a): arbitrary (array a)` | ||
*/ | ||
function array(arb) { | ||
arb = utils.force(arb || primitive.json); | ||
function arrayImpl(flavour) { | ||
return function array(arb) { | ||
arb = utils.force(arb || primitive.json); | ||
return { | ||
generator: generator.array(arb.generator), | ||
shrink: shrink.array(arb.shrink), | ||
show: show.array(arb.show), | ||
return { | ||
generator: generator[flavour](arb.generator), | ||
shrink: shrink[flavour](arb.shrink), | ||
show: show.array(arb.show), | ||
}; | ||
}; | ||
@@ -45,14 +44,11 @@ } | ||
/** | ||
- `array(arb: arbitrary a): arbitrary (array a)` | ||
*/ | ||
var array = arrayImpl("array"); | ||
/** | ||
- `nearray(arb: arbitrary a): arbitrary (array a)` | ||
*/ | ||
function nearray(arb) { | ||
arb = utils.force(arb || primitive.json); | ||
var nearray = arrayImpl("nearray"); | ||
return { | ||
generator: generator.nearray(arb.generator), | ||
shrink: shrink.nearray(arb.shrink), | ||
show: show.array(arb.show), | ||
}; | ||
} | ||
/** | ||
@@ -59,0 +55,0 @@ - `pair(arbA: arbitrary a, arbB : arbitrary b): arbitrary (pair a b)` |
@@ -10,5 +10,4 @@ /* @flow weak */ | ||
/** | ||
- `fn(gen: generator a): generator (b -> a)` | ||
- `fun(gen: generator a): generator (b -> a)` | ||
Unary functions. | ||
- `fn(arb: arbitrary a): arbitrary (b -> a)` | ||
- `fun(arb: arbitrary a): arbitrary (b -> a)` | ||
*/ | ||
@@ -15,0 +14,0 @@ |
@@ -8,3 +8,18 @@ /* @flow weak */ | ||
/** | ||
### Generator functions | ||
### Generator functions | ||
A generator function, `generator a`, is a function `(size: nat) -> a`, which generates a value of given size. | ||
Generator combinators are auto-curried: | ||
```js | ||
var xs = generator.array(shrink.nat, 1); // ≡ | ||
var ys = generator.array(shrink.nat)(1); | ||
``` | ||
In purely functional approach `generator a` would be explicitly stateful computation: | ||
`(size: nat, rng: randomstate) -> (a, randomstate)`. | ||
*JSVerify* uses an implicit random number generator state, | ||
but the value generation is deterministic (tests reproduceable), | ||
if the primitives from *random* module are used. | ||
*/ | ||
@@ -31,2 +46,20 @@ | ||
/** | ||
- `generator.bless(f: nat -> a): generator a` | ||
Bless function with `.map` and `.flatmap` properties. | ||
- `.map(f: a -> b): generator b` | ||
Map `generator a` into `generator b`. For example: | ||
```js | ||
positiveIntegersGenerator = nat.generator.map( | ||
function (x) { return x + 1; }); | ||
``` | ||
- `.isomap(f: a -> generator b): generator b` | ||
Monadic bind for generators. | ||
*/ | ||
function generatorBless(generator) { | ||
@@ -39,3 +72,3 @@ generator.map = generatorProtoMap; | ||
/** | ||
- `generator.constant(x: a): gen a` | ||
- `generator.constant(x: a): generator a` | ||
*/ | ||
@@ -48,2 +81,31 @@ function generateConstant(x) { | ||
/** | ||
- `generator.combine(gen: generator a..., f: a... -> b): generator b` | ||
*/ | ||
function generatorCombine() { | ||
var generators = Array.prototype.slice.call(arguments, 0, -1); | ||
var f = arguments[arguments.length - 1]; | ||
return generatorBless(function (size) { | ||
var values = generators.map(function (gen) { | ||
return gen(size); | ||
}); | ||
return f.apply(undefined, values); | ||
}); | ||
} | ||
/** | ||
- `generator.oneof(gens: list (generator a)): generator a` | ||
*/ | ||
function generateOneof(generators) { | ||
var result = generatorBless(function (size) { | ||
var idx = random(0, generators.length - 1); | ||
var arb = generators[idx]; | ||
return arb(size); | ||
}); | ||
return utils.curried2(result, arguments); | ||
} | ||
// Helper, essentially: log2(size + 1) | ||
@@ -55,4 +117,23 @@ function logsize(size) { | ||
/** | ||
- `generator.pair(genA: gen a, genB: gen b, size: nat): gen (a, b)` | ||
- `generator.recursive(genZ: generator a, genS: generator a -> generator a): generator a` | ||
*/ | ||
function generatorRecursive(genZ, genS) { | ||
return generatorBless(function (size) { | ||
function rec(n, sizep) { | ||
if (n <= 0 || random(0, 3) === 0) { | ||
return genZ(sizep); | ||
} else { | ||
return genS(generatorBless(function (sizeq) { | ||
return rec(n - 1, sizeq); | ||
}))(sizep); | ||
} | ||
} | ||
return rec(logsize(size), size); | ||
}); | ||
} | ||
/** | ||
- `generator.pair(genA: generator a, genB: generator b): generator (a, b)` | ||
*/ | ||
function generatePair(genA, genB) { | ||
@@ -67,3 +148,3 @@ var result = generatorBless(function (size) { | ||
/** | ||
- `generator.tuple(gens: (gen a, gen b...), size: nat): gen (a, b...)` | ||
- `generator.tuple(gens: (generator a, generator b...): generator (a, b...)` | ||
*/ | ||
@@ -84,3 +165,3 @@ function generateTuple(gens) { | ||
/** | ||
- `generator.array(gen: gen a, size: nat): gen (array a)` | ||
- `generator.array(gen: generator a): generator (array a)` | ||
*/ | ||
@@ -101,3 +182,3 @@ function generateArray(gen) { | ||
/** | ||
- `generator.nearray(gen: Gen a, size: nat): gen (array a)` | ||
- `generator.nearray(gen: generator a): generator (array a)` | ||
*/ | ||
@@ -118,3 +199,3 @@ function generateNEArray(gen) { | ||
/** | ||
- `generator.char: gen char` | ||
- `generator.char: generator char` | ||
*/ | ||
@@ -126,3 +207,3 @@ var generateChar = generatorBless(function generateChar(/* size */) { | ||
/** | ||
- `generator.string(size: nat): gen string` | ||
- `generator.string: generator string` | ||
*/ | ||
@@ -132,3 +213,3 @@ var generateString = generateArray(generateChar).map(utils.charArrayToString); | ||
/** | ||
- `generator.nestring(size: nat): gen string` | ||
- `generator.nestring: generator string` | ||
*/ | ||
@@ -138,3 +219,3 @@ var generateNEString = generateNEArray(generateChar).map(utils.charArrayToString); | ||
/** | ||
- `generator.asciichar: gen char` | ||
- `generator.asciichar: generator char` | ||
*/ | ||
@@ -146,3 +227,3 @@ var generateAsciiChar = generatorBless(function generateAsciiChar(/* size */) { | ||
/** | ||
- `generator.asciistring(size: nat): gen string` | ||
- `generator.asciistring: generator string` | ||
*/ | ||
@@ -152,3 +233,3 @@ var generateAsciiString = generateArray(generateAsciiChar).map(utils.charArrayToString); | ||
/** | ||
- `generator.map(gen: gen a, size: nat): gen (map a)` | ||
- `generator.map(gen: generator a): generator (map a)` | ||
*/ | ||
@@ -169,52 +250,4 @@ function generateMap(gen) { | ||
/** | ||
- `generator.oneof(gen: list (gen a), size: nat): gen a` | ||
- `generator.json: generator json` | ||
*/ | ||
function generateOneof(generators) { | ||
var result = generatorBless(function (size) { | ||
var idx = random(0, generators.length - 1); | ||
var arb = generators[idx]; | ||
return arb(size); | ||
}); | ||
return utils.curried2(result, arguments); | ||
} | ||
/** | ||
- `generator.combine(gen: gen a..., f: a... -> b): gen b` | ||
*/ | ||
function generatorCombine() { | ||
var generators = Array.prototype.slice.call(arguments, 0, -1); | ||
var f = arguments[arguments.length - 1]; | ||
return generatorBless(function (size) { | ||
var values = generators.map(function (gen) { | ||
return gen(size); | ||
}); | ||
return f.apply(undefined, values); | ||
}); | ||
} | ||
/** | ||
- `generator.recursive(genZ: gen a, genS: gen a -> gen a): gen a` | ||
*/ | ||
function generatorRecursive(genZ, genS) { | ||
return generatorBless(function (size) { | ||
function rec(n, sizep) { | ||
if (n <= 0 || random(0, 3) === 0) { | ||
return genZ(sizep); | ||
} else { | ||
return genS(generatorBless(function (sizeq) { | ||
return rec(n - 1, sizeq); | ||
}))(sizep); | ||
} | ||
} | ||
return rec(logsize(size), size); | ||
}); | ||
} | ||
/** | ||
- `generator.json: gen json` | ||
*/ | ||
var generateInteger = generatorBless(function (size) { | ||
@@ -221,0 +254,0 @@ return random(-size, size); |
@@ -9,2 +9,11 @@ /* @flow weak */ | ||
### Shrink functions | ||
A shrink function, `shrink a`, is a function `a -> [a]`, returning an array of *smaller* values. | ||
Shrink combinators are auto-curried: | ||
```js | ||
var xs = shrink.array(shrink.nat, [1]); // ≡ | ||
var ys = shrink.array(shrink.nat)([1]); | ||
``` | ||
*/ | ||
@@ -23,2 +32,17 @@ | ||
/** | ||
- `shrink.bless(f: a -> [a]): shrink a` | ||
Bless function with `.isomap` property. | ||
- `.isomap(f: a -> b, g: b -> a): shrink b` | ||
Transform `shrink a` into `shrink b`. For example: | ||
```js | ||
positiveIntegersShrink = nat.shrink.isomap( | ||
function (x) { return x + 1; }, | ||
function (x) { return x - 1; }); | ||
``` | ||
*/ | ||
function shrinkBless(shrink) { | ||
@@ -30,3 +54,3 @@ shrink.isomap = shrinkProtoIsoMap; | ||
/** | ||
- `shrink.noop(x: a): array a` | ||
- `shrink.noop: shrink a` | ||
*/ | ||
@@ -38,3 +62,3 @@ var shrinkNoop = shrinkBless(function shrinkNoop() { | ||
/** | ||
- `shrink.pair(shrA: a -> array a, shrB: b -> array, x: (a, b)): array (a, b)` | ||
- `shrink.pair(shrA: shrink a, shrB: shrink b): shrink (a, b)` | ||
*/ | ||
@@ -96,3 +120,3 @@ function shrinkPair(shrinkA, shrinkB) { | ||
/** | ||
- `shrink.tuple(shrinks: (a -> array a, b -> array b...), x: (a, b...)): array (a, b...)` | ||
- `shrink.tuple(shrs: (shrink a, shrink b...)): shrink (a, b...)` | ||
*/ | ||
@@ -128,3 +152,3 @@ function shrinkTuple(shrinks) { | ||
/** | ||
- `shrink.array(shrink: a -> array a, x: array a): array (array a)` | ||
- `shrink.array(shr: shrink a): shrink (array a)` | ||
*/ | ||
@@ -134,3 +158,3 @@ var shrinkArray = shrinkArrayWithMinimumSize(0); | ||
/** | ||
- `shrink.nearray(shrink: a -> nearray a, x: nearray a): array (nearray a)` | ||
- `shrink.nearray(shr: shrink a): shrink (nearray a)` | ||
*/ | ||
@@ -140,3 +164,3 @@ var shrinkNEArray = shrinkArrayWithMinimumSize(1); | ||
/** | ||
- `shrink.record(shrinks: { key: a -> string... }, x: { key: a... }): array { key: a... }` | ||
- `shrink.record(shrs: { key: shrink a... }): shrink { key: a... }` | ||
*/ | ||
@@ -143,0 +167,0 @@ function shrinkRecord(shrinksRecord) { |
{ | ||
"name": "jsverify", | ||
"description": "Property-based testing for JavaScript.", | ||
"version": "0.5.0-beta.2", | ||
"version": "0.5.0", | ||
"homepage": "http://jsverify.github.io/", | ||
@@ -32,3 +32,3 @@ "author": { | ||
"devDependencies": { | ||
"browserify": "~7.0.3", | ||
"browserify": "^8.0.1", | ||
"chai": "^1.10.0", | ||
@@ -47,5 +47,5 @@ "david": "^6.0.1", | ||
"karma-mocha": "~0.1.3", | ||
"ljs": "~0.2.3", | ||
"ljs": "~0.3.0", | ||
"lodash": "~2.4.1", | ||
"mocha": "~2.0.1", | ||
"mocha": "^2.1.0", | ||
"npm-freeze": "^0.1.3", | ||
@@ -52,0 +52,0 @@ "q": "~2.0.2", |
147
README.md
@@ -32,3 +32,2 @@ # JSVerify | ||
## Documentation | ||
@@ -90,6 +89,4 @@ | ||
### Properties | ||
- `forall(arbs: arbitrary a ..., userenv: (map arbitrary)?, prop : a -> property): property` | ||
@@ -99,3 +96,2 @@ | ||
- `check (prop: property, opts: checkoptions?): result` | ||
@@ -112,3 +108,2 @@ | ||
- `assert(prop: property, opts: checkoptions?) : void` | ||
@@ -118,3 +113,2 @@ | ||
- `property(name: string, ...)` | ||
@@ -137,3 +131,2 @@ | ||
- `sampler(arb: arbitrary a, genSize: nat = 10): (sampleSize: nat?) -> a` | ||
@@ -158,3 +151,2 @@ | ||
### Types | ||
@@ -168,3 +160,2 @@ | ||
### DSL for input parameters | ||
@@ -184,7 +175,4 @@ | ||
### Primitive arbitraries | ||
- `integer: arbitrary integer` | ||
@@ -196,3 +184,2 @@ - `integer(maxsize: nat): arbitrary integer` | ||
- `nat: arbitrary nat` | ||
@@ -203,3 +190,2 @@ - `nat(maxsize: nat): arbitrary nat` | ||
- `number: arbitrary number` | ||
@@ -211,3 +197,2 @@ - `number(maxsize: number): arbitrary number` | ||
- `uint8: arbitrary nat` | ||
@@ -217,3 +202,2 @@ - `uint16: arbitrary nat` | ||
- `int8: arbitrary integer` | ||
@@ -223,3 +207,2 @@ - `int16: arbitrary integer` | ||
- `bool: arbitrary bool` | ||
@@ -229,3 +212,2 @@ | ||
- `datetime: arbitrary datetime` | ||
@@ -235,3 +217,2 @@ | ||
- `elements(args: array a): arbitrary a` | ||
@@ -241,3 +222,2 @@ | ||
- `char: arbitrary char` | ||
@@ -247,3 +227,2 @@ | ||
- `asciichar: arbitrary char` | ||
@@ -253,6 +232,4 @@ | ||
- `string: arbitrary string` | ||
- `notEmptyString: arbitrary string` | ||
@@ -262,6 +239,4 @@ | ||
- `asciistring: arbitrary string` | ||
- `json: arbitrary json` | ||
@@ -273,3 +248,2 @@ | ||
- `falsy: arbitrary *` | ||
@@ -279,3 +253,2 @@ | ||
- `constant(x: a): arbitrary a` | ||
@@ -285,7 +258,4 @@ | ||
### Arbitrary combinators | ||
- `nonshrink(arb: arbitrary a): arbitrary a` | ||
@@ -295,9 +265,6 @@ | ||
- `array(arb: arbitrary a): arbitrary (array a)` | ||
- `nearray(arb: arbitrary a): arbitrary (array a)` | ||
- `pair(arbA: arbitrary a, arbB : arbitrary b): arbitrary (pair a b)` | ||
@@ -307,6 +274,4 @@ | ||
- `tuple(arbs: (arbitrary a, arbitrary b...)): arbitrary (a, b...)` | ||
- `map(arb: arbitrary a): arbitrary (map a)` | ||
@@ -316,3 +281,2 @@ | ||
- `oneof(gs : array (arbitrary a)...) : arbitrary a` | ||
@@ -322,3 +286,2 @@ | ||
- `record(spec: { key: arbitrary a... }): arbitrary { key: a... }` | ||
@@ -328,100 +291,118 @@ | ||
- `fn(arb: arbitrary a): arbitrary (b -> a)` | ||
- `fun(arb: arbitrary a): arbitrary (b -> a)` | ||
- `fn(gen: generator a): generator (b -> a)` | ||
- `fun(gen: generator a): generator (b -> a)` | ||
Unary functions. | ||
### Generator functions | ||
A generator function, `generator a`, is a function `(size: nat) -> a`, which generates a value of given size. | ||
- `generator.constant(x: a): gen a` | ||
Generator combinators are auto-curried: | ||
```js | ||
var xs = generator.array(shrink.nat, 1); // ≡ | ||
var ys = generator.array(shrink.nat)(1); | ||
``` | ||
- `generator.pair(genA: gen a, genB: gen b, size: nat): gen (a, b)` | ||
In purely functional approach `generator a` would be explicitly stateful computation: | ||
`(size: nat, rng: randomstate) -> (a, randomstate)`. | ||
*JSVerify* uses an implicit random number generator state, | ||
but the value generation is deterministic (tests reproduceable), | ||
if the primitives from *random* module are used. | ||
- `generator.bless(f: nat -> a): generator a` | ||
- `generator.tuple(gens: (gen a, gen b...), size: nat): gen (a, b...)` | ||
Bless function with `.map` and `.flatmap` properties. | ||
- `.map(f: a -> b): generator b` | ||
- `generator.array(gen: gen a, size: nat): gen (array a)` | ||
Map `generator a` into `generator b`. For example: | ||
```js | ||
positiveIntegersGenerator = nat.generator.map( | ||
function (x) { return x + 1; }); | ||
``` | ||
- `generator.nearray(gen: Gen a, size: nat): gen (array a)` | ||
- `.isomap(f: a -> generator b): generator b` | ||
Monadic bind for generators. | ||
- `generator.char: gen char` | ||
- `generator.constant(x: a): generator a` | ||
- `generator.combine(gen: generator a..., f: a... -> b): generator b` | ||
- `generator.string(size: nat): gen string` | ||
- `generator.oneof(gens: list (generator a)): generator a` | ||
- `generator.recursive(genZ: generator a, genS: generator a -> generator a): generator a` | ||
- `generator.nestring(size: nat): gen string` | ||
- `generator.pair(genA: generator a, genB: generator b): generator (a, b)` | ||
- `generator.tuple(gens: (generator a, generator b...): generator (a, b...)` | ||
- `generator.asciichar: gen char` | ||
- `generator.array(gen: generator a): generator (array a)` | ||
- `generator.nearray(gen: generator a): generator (array a)` | ||
- `generator.asciistring(size: nat): gen string` | ||
- `generator.char: generator char` | ||
- `generator.string: generator string` | ||
- `generator.map(gen: gen a, size: nat): gen (map a)` | ||
- `generator.nestring: generator string` | ||
- `generator.asciichar: generator char` | ||
- `generator.oneof(gen: list (gen a), size: nat): gen a` | ||
- `generator.asciistring: generator string` | ||
- `generator.map(gen: generator a): generator (map a)` | ||
- `generator.combine(gen: gen a..., f: a... -> b): gen b` | ||
- `generator.json: generator json` | ||
- `generator.recursive(genZ: gen a, genS: gen a -> gen a): gen a` | ||
- `generator.json: gen json` | ||
### Shrink functions | ||
A shrink function, `shrink a`, is a function `a -> [a]`, returning an array of *smaller* values. | ||
- `shrink.noop(x: a): array a` | ||
Shrink combinators are auto-curried: | ||
```js | ||
var xs = shrink.array(shrink.nat, [1]); // ≡ | ||
var ys = shrink.array(shrink.nat)([1]); | ||
``` | ||
- `shrink.pair(shrA: a -> array a, shrB: b -> array, x: (a, b)): array (a, b)` | ||
- `shrink.bless(f: a -> [a]): shrink a` | ||
Bless function with `.isomap` property. | ||
- `shrink.tuple(shrinks: (a -> array a, b -> array b...), x: (a, b...)): array (a, b...)` | ||
- `.isomap(f: a -> b, g: b -> a): shrink b` | ||
Transform `shrink a` into `shrink b`. For example: | ||
- `shrink.array(shrink: a -> array a, x: array a): array (array a)` | ||
```js | ||
positiveIntegersShrink = nat.shrink.isomap( | ||
function (x) { return x + 1; }, | ||
function (x) { return x - 1; }); | ||
``` | ||
- `shrink.noop: shrink a` | ||
- `shrink.nearray(shrink: a -> nearray a, x: nearray a): array (nearray a)` | ||
- `shrink.pair(shrA: shrink a, shrB: shrink b): shrink (a, b)` | ||
- `shrink.tuple(shrs: (shrink a, shrink b...)): shrink (a, b...)` | ||
- `shrink.record(shrinks: { key: a -> string... }, x: { key: a... }): array { key: a... }` | ||
- `shrink.array(shr: shrink a): shrink (array a)` | ||
- `shrink.nearray(shr: shrink a): shrink (nearray a)` | ||
- `shrink.record(shrs: { key: shrink a... }): shrink { key: a... }` | ||
### Show functions | ||
- `show.def(x : a): string` | ||
- `show.pair(showA: a -> string, showB: b -> string, x: (a, b)): string` | ||
- `show.tuple(shrinks: (a -> string, b -> string...), x: (a, b...)): string` | ||
- `show.array(shrink: a -> string, x: array a): string` | ||
### Random functions | ||
- `random(min: int, max: int): int` | ||
@@ -435,3 +416,2 @@ | ||
- `random.number(min: number, max: number): number` | ||
@@ -441,4 +421,2 @@ | ||
### Utility functions | ||
@@ -451,3 +429,2 @@ | ||
- `utils.isEqual(x: json, y: json): bool` | ||
@@ -457,3 +434,2 @@ | ||
- `utils.force(x: a | () -> a) : a` | ||
@@ -463,3 +439,2 @@ | ||
- `utils.merge(x: obj, y: obj): obj` | ||
@@ -469,4 +444,2 @@ | ||
## Contributing | ||
@@ -480,2 +453,4 @@ | ||
- **0.5.0** — *2014-12-24* Merry Chrismas 2014! | ||
- Documention cleanup | ||
- **0.5.0-beta.2** — *2014-12-21* — Beta 2! | ||
@@ -482,0 +457,0 @@ - Pair & tuple related code cleanup |
Sorry, the diff of this file is too big to display
168059
4702
568