UNPKG

31 kBMarkdownView Raw
1# JSVerify
2
3<img src="https://raw.githubusercontent.com/jsverify/jsverify/master/jsverify-300.png" align="right" height="100" />
4
5> Property-based checking. Like QuickCheck.
6
7[![Build Status](https://secure.travis-ci.org/jsverify/jsverify.svg?branch=master)](http://travis-ci.org/jsverify/jsverify)
8[![NPM version](https://badge.fury.io/js/jsverify.svg)](http://badge.fury.io/js/jsverify)
9[![Dependency Status](https://david-dm.org/jsverify/jsverify.svg)](https://david-dm.org/jsverify/jsverify)
10[![devDependency Status](https://david-dm.org/jsverify/jsverify/dev-status.svg)](https://david-dm.org/jsverify/jsverify#info=devDependencies)
11[![Code Climate](https://img.shields.io/codeclimate/github/jsverify/jsverify.svg)](https://codeclimate.com/github/jsverify/jsverify)
12
13## Getting Started
14
15Install the module with: `npm install jsverify`
16
17## Synopsis
18
19```js
20var jsc = require("jsverify");
21
22// forall (f : bool -> bool) (b : bool), f (f (f b)) = f(b).
23var boolFnAppliedThrice =
24 jsc.forall("bool -> bool", "bool", function (f, b) {
25 return f(f(f(b))) === f(b);
26 });
27
28jsc.assert(boolFnAppliedThrice);
29// OK, passed 100 tests
30```
31
32## Documentation
33
34### Usage with [mocha](http://mochajs.org/)
35
36Using jsverify with mocha is easy, just define the properties and use `jsverify.assert`.
37
38Starting from version 0.4.3 you can write your specs without any boilerplate:
39
40```js
41describe("sort", function () {
42 jsc.property("idempotent", "array nat", function (arr) {
43 return _.isEqual(sort(sort(arr)), sort(arr));
44 });
45});
46```
47
48Starting from version 0.8.0 you can write the specs in TypeScript. There are
49typings provided. The drawback is that you cannot use type DSL:
50
51```typescript
52describe("basic jsverify usage", () => {
53 jsc.property("(b && b) === b", jsc.bool, b => (b && b) === b);
54
55 jsc.property("boolean fn thrice", jsc.fn(jsc.bool), jsc.bool, (f, b) =>
56 f(f(f(b))) === f(b)
57 );
58});
59```
60
61You can also provide `--jsverifyRngState state` command line argument, to run tests with particular random generator state.
62
63```
64$ mocha examples/nat.js
65
661) natural numbers are less than 90:
67 Error: Failed after 49 tests and 1 shrinks. rngState: 074e9b5f037a8c21d6; Counterexample: 90;
68
69$ mocha examples/nat.js --grep 'are less than' --jsverifyRngState 074e9b5f037a8c21d6
70
711) natural numbers are less than 90:
72 Error: Failed after 1 tests and 1 shrinks. rngState: 074e9b5f037a8c21d6; Counterexample: 90;
73```
74
75Erroneous case is found with first try.
76
77### Usage with [jasmine](https://jasmine.github.io/)
78
79Check [jasmineHelpers.js](helpers/jasmineHelpers.js) and [jasmineHelpers2.js](helpers/jasmineHelpers2.js) for jasmine 1.3 and 2.0 respectively.
80
81## API Reference
82
83> _Testing shows the presence, not the absence of bugs._
84>
85> Edsger W. Dijkstra
86
87To show that propositions hold, we need to construct proofs.
88There are two extremes: proof by example (unit tests) and formal (machine-checked) proof.
89Property-based testing is somewhere in between.
90We formulate propositions, invariants or other properties we believe to hold, but
91only test it to hold for numerous (randomly generated) values.
92
93Types and function signatures are written in [Coq](http://coq.inria.fr/)/[Haskell](http://www.haskell.org/haskellwiki/Haskell)-influenced style:
94C# -style `List<T> filter(List<T> v, Func<T, bool> predicate)` is represented by
95`filter(v: array T, predicate: T -> bool): array T` in our style.
96
97Methods and objects live in `jsc` object, e.g. `shrink.bless` method is used by
98```js
99var jsc = require("jsverify");
100var foo = jsc.shrink.bless(...);
101```
102
103Methods starting with `.dot` are prototype methods:
104```js
105var arb = jsc.nat;
106var arb2 = jsc.nat.smap(f, g);
107```
108
109`jsverify` can operate with both synchronous and asynchronous-promise properties.
110Generally every property can be wrapped inside [functor](http://learnyouahaskell.com/functors-applicative-functors-and-monoids),
111for now in either identity or promise functor, for synchronous and promise properties respectively.
112
113### Properties
114
115- `forall(arbs: arbitrary a ..., userenv: (map arbitrary)?, prop : a -> property): property`
116
117 Property constructor
118
119- `check (prop: property, opts: checkoptions?): result`
120
121 Run random checks for given `prop`. If `prop` is promise based, result is also wrapped in promise.
122
123 Options:
124 - `opts.tests` - test count to run, default 100
125 - `opts.size` - maximum size of generated values, default 50
126 - `opts.quiet` - do not `console.log`
127 - `opts.rngState` - state string for the rng
128
129 The `result` is `true` if check succeeds, otherwise it's an object with various fields:
130 - `counterexample` - an input for which property fails.
131 - `tests` - number of tests run before failing case is found
132 - `shrinks` - number of shrinks performed
133 - `exc` - an optional exception thrown by property function
134 - `rngState` - random number generator's state before execution of the property
135
136- `assert(prop: property, opts: checkoptions?) : void`
137
138 Same as `check`, but throw exception if property doesn't hold.
139
140- `property(name: string, ...)`
141
142 Assuming there is globally defined `it`, the same as:
143
144 ```js
145 it(name, function () {
146 jsc.assert(jsc.forall(...));
147 }
148 ```
149
150 You can use `property` to write facts too:
151 ```js
152 jsc.property("+0 === -0", function () {
153 return +0 === -0;
154 });
155 ```
156
157- `compile(desc: string, env: typeEnv?): arbitrary a`
158
159 Compile the type description in provided type environment, or default one.
160
161- `sampler(arb: arbitrary a, genSize: nat = 10): (sampleSize: nat?) -> a`
162
163 Create a sampler for a given arbitrary with an optional size. Handy when used in
164 a REPL:
165 ```
166 > jsc = require('jsverify') // or require('./lib/jsverify') w/in the project
167 ...
168 > jsonSampler = jsc.sampler(jsc.json, 4)
169 [Function]
170 > jsonSampler()
171 0.08467432763427496
172 > jsonSampler()
173 [ [ [] ] ]
174 > jsonSampler()
175 ''
176 > sampledJson(2)
177 [-0.4199344692751765, false]
178 ```
179
180- `throws(block: () -> a, error: class?, message: string?): bool`
181
182 Executes nullary function `block`. Returns `true` if `block` throws. See [assert.throws](https://nodejs.org/api/assert.html#assert_assert_throws_block_error_message)
183
184- `assertForall(arbs: arbitrary a ..., userenv: (map arbitrary)?, prop : a -> property): void`
185
186 Combines 'assert' and 'forall'.
187 Constructs a property with forall from arguments, then throws an exception if the property doesn't hold.
188 Options for 'assert' cannot be set here - use assert(forall(...)) if you need that.
189
190- `checkForall(arbs: arbitrary a ..., userenv: (map arbitrary)?, prop : a -> property): result`
191
192 Combines 'check' and 'forall'.
193 Constructs a property with forall from arguments, and returns a value based on if the property holds or not.
194 See 'check' for description of return value.
195
196 Options for 'check' cannot be set here - use check(forall(...)) if you need that.
197
198### Types
199
200- `generator a` is a function `(size: nat) -> a`.
201- `show` is a function `a -> string`.
202- `shrink` is a function `a -> [a]`, returning *smaller* values.
203- `arbitrary a` is a triple of generator, shrink and show functions.
204 - `{ generator: nat -> a, shrink : a -> array a, show: a -> string }`
205
206### Blessing
207
208We chose to represent generators and shrinks by functions, yet we would
209like to have additional methods on them. Thus we *bless* objects with
210additional properties.
211
212Usually you don't need to bless anything explicitly, as all combinators
213return blessed values.
214
215See [perldoc for bless](http://perldoc.perl.org/functions/bless.html).
216
217### DSL for input parameters
218
219There is a small DSL to help with `forall`. For example the two definitions below are equivalent:
220```js
221var bool_fn_applied_thrice = jsc.forall("bool -> bool", "bool", check);
222var bool_fn_applied_thrice = jsc.forall(jsc.fn(jsc.bool), jsc.bool, check);
223```
224
225The DSL is based on a subset of language recognized by [typify-parser](https://github.com/phadej/typify-parser):
226- *identifiers* are fetched from the predefined environment.
227- *applications* are applied as one could expect: `"array bool"` is evaluated to `jsc.array(jsc.bool)`.
228- *functions* are supported: `"bool -> bool"` is evaluated to `jsc.fn(jsc.bool)`.
229- *square brackets* are treated as a shorthand for the array type: `"[nat]"` is evaluated to `jsc.array(jsc.nat)`.
230- *union*: `"bool | nat"` is evaluated to `jsc.sum([jsc.bool, jsc.nat])`.
231 - **Note** `oneof` cannot be shrinked, because the union is untagged, we don't know which shrink to use.
232- *conjunction*: `"bool & nat"` is evaluated to `jsc.tuple(jsc.bool, jsc.nat)`.
233- *anonymous records*: `"{ b: bool; n: nat }"` is evaluated to `jsc.record({ b: jsc.bool, n: jsc.nat })`.
234- *EXPERIMENTAL: recursive types*: `"rec list -> unit | (nat & list)"`.
235
236### Arbitrary data
237
238- `.smap(f: a -> b, g: b -> a, newShow: (b -> string)?): arbitrary b`
239
240 Transform `arbitrary a` into `arbitrary b`. For example:
241
242 `g` should be a [right inverse](http://en.wikipedia.org/wiki/Surjective_function#Surjections_as_right_invertible_functions) of `f`, but doesn't need to be complete inverse.
243 i.e. i.e. `f` doesn't need to be invertible, only surjective.
244
245 ```js
246 var positiveIntegersArb = nat.smap(
247 function (x) { return x + 1; },
248 function (x) { return x - 1; });
249 ```
250
251 ```js
252 var setNatArb = jsc.array(jsc.nat).smap(_.uniq, _.identity);
253 ```
254
255 Right inverse means that *f(g(y)) = y* for all *y* in *Y*. Here *Y* is a type of **arrays of unique natural numbers**. For them
256 ```js
257 _.uniq(_.identity(y)) = _.uniq(y) = y
258 ```
259
260 Opposite: *g(f(x))* for all *x* in *X*, doesn't need to hold. *X* is **arrays of natural numbers**:
261 ```js
262 _.identity(_uniq([0, 0])) = [0]] != [0, 0]
263 ```
264
265 We need an inverse for shrinking, and there right inverse is enough. We can always *pull back* `smap`ped value, shrink the preimage, and *map* or *push forward* shrunken preimages again.
266
267- `bless(arb: {...}): arbitrary a`
268
269 Bless almost arbitrary structure to be proper arbitrary. *Note*: this function mutates argument.
270
271 #### Example:
272
273 ```js
274 var arbTokens = jsc.bless({
275 generator: function () {
276 switch (jsc.random(0, 2)) {
277 case 0: return "foo";
278 case 1: return "bar";
279 case 2: return "quux";
280 }
281 }
282 });
283 ```
284
285### Primitive arbitraries
286
287- `integer: arbitrary integer`
288- `integer(maxsize: nat): arbitrary integer`
289- `integer(minsize: integer, maxsize: integer): arbitrary integer`
290
291 Integers, ℤ
292
293- `nat: arbitrary nat`
294- `nat(maxsize: nat): arbitrary nat`
295
296 Natural numbers, ℕ (0, 1, 2...)
297
298- `number: arbitrary number`
299- `number(maxsize: number): arbitrary number`
300- `number(min: number, max: number): arbitrary number`
301
302 JavaScript numbers, "doubles", ℝ. `NaN` and `Infinity` are not included.
303
304- `uint8: arbitrary nat`
305- `uint16: arbitrary nat`
306- `uint32: arbitrary nat`
307
308- `int8: arbitrary integer`
309- `int16: arbitrary integer`
310- `int32: arbitrary integer`
311
312- `bool: arbitrary bool`
313
314 Booleans, `true` or `false`.
315
316- `datetime: arbitrary datetime`
317
318 Random datetime
319
320- `elements(args: array a): arbitrary a`
321
322 Random element of `args` array.
323
324- `falsy: arbitrary *`
325
326 Generates falsy values: `false`, `null`, `undefined`, `""`, `0`, and `NaN`.
327
328- `constant(x: a): arbitrary a`
329
330 Returns an unshrinkable arbitrary that yields the given object.
331
332### Arbitrary combinators
333
334- `nonshrink(arb: arbitrary a): arbitrary a`
335
336 Non shrinkable version of arbitrary `arb`.
337
338- `unit: arbitrary ()`
339
340- `either(arbA: arbitrary a, arbB : arbitrary b): arbitrary (either a b)`
341
342- `pair(arbA: arbitrary a, arbB : arbitrary b): arbitrary (pair a b)`
343
344 If not specified `a` and `b` are equal to `value()`.
345
346- `tuple(arbs: (arbitrary a, arbitrary b...)): arbitrary (a, b...)`
347
348- `sum(arbs: (arbitrary a, arbitrary b...)): arbitrary (a | b ...)`
349
350- `dict(arb: arbitrary a): arbitrary (dict a)`
351
352 Generates a JavaScript object with properties of type `A`.
353
354- `array(arb: arbitrary a): arbitrary (array a)`
355
356- `nearray(arb: arbitrary a): arbitrary (array a)`
357
358- `json: arbitrary json`
359
360 JavaScript Objects: boolean, number, string, null, array of `json` values or object with `json` values.
361
362- `oneof(gs : array (arbitrary a)...) : arbitrary a`
363
364 Randomly uses one of the given arbitraries.
365
366- ```js
367 letrec(
368 (tie: key -> (arbitrary a | arbitrary b | ...))
369 -> { key: arbitrary a, key: arbitrary b, ... }):
370 { key: arbitrary a, key: arbitrary b, ... }
371 ```
372
373 Mutually recursive definitions. Every reference to a sibling arbitrary
374 should go through the `tie` function.
375
376 ```js
377 { arb1, arb2 } = jsc.letrec(function (tie) {
378 return {
379 arb1: jsc.tuple(jsc.int, jsc.oneof(jsc.const(null), tie("arb2"))),
380 arb2: jsc.tuple(jsc.bool, jsc.oneof(jsc.const(null), tie("arb1"))),
381 }
382 });
383 ```
384
385### Arbitrary records
386
387- `record(spec: { key: arbitrary a... }, userenv: env?): arbitrary { key: a... }`
388
389 Generates a javascript object with given record spec.
390
391- `generator.record(gen: { key: generator a... }): generator { key: a... }`
392
393- `shrink.record(shrs: { key: shrink a... }): shrink { key: a... }`
394
395### Arbitrary strings
396
397- `char: arbitrary char` &mdash; Single character
398
399- `asciichar: arbitrary char` &mdash; Single ascii character (0x20-0x7e inclusive, no DEL)
400
401- `string: arbitrary string`
402
403- `nestring: arbitrary string` &mdash; Generates strings which are not empty.
404
405- `asciistring: arbitrary string`
406
407- `asciinestring: arbitrary string`
408
409### Arbitrary functions
410
411- `fn(arb: arbitrary a): arbitrary (b -> a)`
412- `fun(arb: arbitrary a): arbitrary (b -> a)`
413
414### Small arbitraries
415
416- `generator.small(gen: generator a): generator a`
417- `small(arb: arbitrary a): arbitrary a`
418
419Create a generator (abitrary) which will generate smaller values, i.e. generator's `size` parameter is decreased logarithmically.
420
421```js
422jsc.property("small array of small natural numbers", "small (array nat)", function (arr) {
423 return Array.isArray(arr);
424});
425
426jsc.property("small array of normal natural numbers", "(small array) nat", function (arr) {
427 return Array.isArray(arr);
428});
429```
430
431### Generator functions
432
433A generator function, `generator a`, is a function `(size: nat) -> a`, which generates a value of given size.
434
435Generator combinators are auto-curried:
436
437```js
438var xs = jsc.generator.array(jsc.nat.generator, 1); // ≡
439var ys = jsc.generator.array(jsc.nat.generator)(1);
440```
441
442In purely functional approach `generator a` would be explicitly stateful computation:
443`(size: nat, rng: randomstate) -> (a, randomstate)`.
444*JSVerify* uses an implicit random number generator state,
445but the value generation is deterministic (tests are reproducible),
446if the primitives from *random* module are used.
447
448- `generator.bless(f: nat -> a): generator a`
449
450 Bless function with `.map` and `.flatmap` properties.
451
452- `.map(f: a -> b): generator b`
453
454 Map `generator a` into `generator b`. For example:
455
456 ```js
457 positiveIntegersGenerator = nat.generator.map(
458 function (x) { return x + 1; });
459 ```
460
461- `.flatmap(f: a -> generator b): generator b`
462
463 Monadic bind for generators. Also `flatMap` version is supported.
464
465- `generator.constant(x: a): generator a`
466
467- `generator.combine(gen: generator a..., f: a... -> b): generator b`
468
469- `generator.oneof(gens: list (generator a)): generator a`
470
471- `generator.recursive(genZ: generator a, genS: generator a -> generator a): generator a`
472
473- `generator.pair(genA: generator a, genB: generator b): generator (a, b)`
474
475- `generator.either(genA: generator a, genB: generator b): generator (either a b)`
476
477- `generator.unit: generator ()`
478
479 `unit` is an empty tuple, i.e. empty array in JavaScript representation. This is useful as a building block.
480
481- `generator.tuple(gens: (generator a, generator b...)): generator (a, b...)`
482
483- `generator.sum(gens: (generator a, generator b...)): generator (a | b...)`
484
485- `generator.array(gen: generator a): generator (array a)`
486
487- `generator.nearray(gen: generator a): generator (array a)`
488
489- `generator.dict(gen: generator a): generator (dict a)`
490
491### Shrink functions
492
493A shrink function, `shrink a`, is a function `a -> [a]`, returning an array of *smaller* values.
494
495Shrink combinators are auto-curried:
496
497```js
498var xs = jsc.shrink.array(jsc.nat.shrink, [1]); // ≡
499var ys = jsc.shrink.array(jsc.nat.shrink)([1]);
500```
501
502- `shrink.bless(f: a -> [a]): shrink a`
503
504 Bless function with `.smap` property.
505
506- `.smap(f: a -> b, g: b -> a): shrink b`
507
508 Transform `shrink a` into `shrink b`. For example:
509
510 ```js
511 positiveIntegersShrink = nat.shrink.smap(
512 function (x) { return x + 1; },
513 function (x) { return x - 1; });
514 ```
515
516- `shrink.noop: shrink a`
517
518- `shrink.pair(shrA: shrink a, shrB: shrink b): shrink (a, b)`
519
520- `shrink.either(shrA: shrink a, shrB: shrink b): shrink (either a b)`
521
522- `shrink.tuple(shrs: (shrink a, shrink b...)): shrink (a, b...)`
523
524- `shrink.sum(shrs: (shrink a, shrink b...)): shrink (a | b...)`
525
526- `shrink.array(shr: shrink a): shrink (array a)`
527
528- `shrink.nearray(shr: shrink a): shrink (nearray a)`
529
530### Show functions
531
532- `show.def(x : a): string`
533
534 Currently implemented as `JSON.stringify`.
535
536- `show.pair(showA: a -> string, showB: b -> string, x: (a, b)): string`
537
538- `show.either(showA: a -> string, showB: b -> string, e: either a b): string`
539
540- `show.tuple(shrinks: (a -> string, b -> string...), x: (a, b...)): string`
541
542- `show.sum(shrinks: (a -> string, b -> string...), x: (a | b ...)): string`
543
544- `show.array(shrink: a -> string, x: array a): string`
545
546### Random functions
547
548- `random(min: int, max: int): int`
549
550 Returns random int from `[min, max]` range inclusively.
551
552 ```js
553 getRandomInt(2, 3) // either 2 or 3
554 ```
555
556- `random.number(min: number, max: number): number`
557
558 Returns random number from `[min, max)` range.
559
560### either
561
562- `either.left(value: a): either a b`
563
564- `either.right(value: b): either a b`
565
566- `either.either(l: a -> x, r: b -> x): x`
567
568- `either.isEqual(other: either a b): bool`
569
570 TODO: add `eq` optional parameter
571
572- `either.bimap(f: a -> c, g: b -> d): either c d`
573
574 ```js
575 either.bimap(compose(f, g), compose(h, i)) ≡ either.bimap(g, i).bimap(f, h);
576 ```
577
578- `either.first(f: a -> c): either c b`
579
580 ```js
581 either.first(f) ≡ either.bimap(f, utils.identity)
582 ```
583
584- `either.second(g: b -> d): either a d`
585
586 ```js
587 either.second(g) === either.bimap(utils.identity, g)
588 ```
589
590### Utility functions
591
592Utility functions are exposed (and documented) only to make contributions to jsverify more easy.
593The changes here don't follow semver, i.e. there might be backward-incompatible changes even in patch releases.
594
595Use [underscore.js](http://underscorejs.org/), [lodash](https://lodash.com/), [ramda](http://ramda.github.io/ramdocs/docs/), [lazy.js](http://danieltao.com/lazy.js/) or some other utility belt.
596
597- `utils.isEqual(x: json, y: json): bool`
598
599 Equality test for `json` objects.
600
601- `utils.isApproxEqual(x: a, y: b, opts: obj): bool`
602
603 Tests whether two objects are approximately and optimistically equal.
604 Returns `false` only if they are distinguishable not equal.
605 Returns `true` when `x` and `y` are `NaN`.
606 This function works with cyclic data.
607
608 Takes optional 'opts' parameter with properties:
609
610 - `fnEqual` - whether all functions are considered equal (default: yes)
611 - `depth` - how deep to recurse until treating as equal (default: 5)
612
613- `utils.force(x: a | () -> a) : a`
614
615 Evaluate `x` as nullary function, if it is one.
616
617- `utils.merge(x... : obj): obj`
618
619 Merge two objects, a bit like `_.extend({}, x, y)`.
620
621## FAQ
622
623### Why do all the examples import the library as jsc instead of jsv?
624
625Does JSC originate with [JSCheck](http://www.jscheck.org/)?
626
627**A:** Yes
628
629### smap requires an inverse function, which isn't always practical. Is this complexity related to shrinking?
630
631**A:** Yes. We don't want to give an easy-to-use interface which forgets
632shrinking altogether. Note, that *right* inverse is enough, which is most
633likely easy to write, even *complete* inverse doesn't exist.
634
635## Contributing
636
637- `README.md` is generated from the source with [ljs](https://github.com/phadej/ljs), say `make literate`.
638- `jsverify.standalone.js` is also generated by the build process
639- Before creating a pull request run `make test`, yet travis will do it for you.
640
641## Release History
642
643- **0.8.0** &mdash; *2017-03-12* &mdash; TypeScript typings
644 - Provide TypeScript typings
645 [#202](https://github.com/jsverify/jsverify/pull/202)
646 [#196](https://github.com/jsverify/jsverify/pull/196)
647- **0.7.5** &mdash; *2017-03-08* &mdash; International Women's Day
648 - Add `letrec` combinator
649 [#193](https://github.com/jsverify/jsverify/pull/193)
650 - Add `null` to `json` arbitrary
651 [#201](https://github.com/jsverify/jsverify/pull/201)
652 - Fix typos and outdated links in documentation
653- **0.7.4** &mdash; *2016-09-07* &mdash; Bless `suchthat`
654 - Fix "arbitraries created with `suchthat` are missing `.smap`"
655 [#184](https://github.com/jsverify/jsverify/issues/184)
656- **0.7.3** &mdash; *2016-08-26* &mdash; Remove lodash
657 - Fixed accidental use of `lodash`. We have our own `isNaN` now.
658- **0.7.2** &mdash; *2016-08-25* &mdash; One year since the last release
659 - `jsc.utils.isEqual` returns true if both arguments are `NaN`.
660 - Add `jsc.assertForall` and `jsc.checkForall`
661- **0.7.1** &mdash; *2015-08-24* &mdash; jsc.throws
662 - Add `jsc.throws` [#133](https://github.com/jsverify/jsverify/pull/133)
663- **0.7.0** &mdash; *2015-08-23* &mdash; More experiments
664 - `jsc.sum` - generate arbitrary sum types (generalisation of either) [#125](https://github.com/jsverify/jsverify/pull/125)
665 - *BREAKING CHANGE:* bar (`|`) in DSL generates `jsc.sum`
666 - experimental support of recursive types in DSL (especially no shrinking yet) [#109](https://github.com/jsverify/jsverify/issues/109) [#126](https://github.com/jsverify/jsverify/pull/126)
667 - fail early when `jsc.forall` is given zero generators [#128](https://github.com/jsverify/jsverify/issues/128)
668 - `jsc.json` has shrink [#122](https://github.com/jsverify/jsverify/issues/122)
669 - non-true non-function results from properties are treated as exceptions [#127](https://github.com/jsverify/jsverify/issues/127)
670- **0.6.3** &mdash; *2015-07-27* &mdash; Bug fixes
671 - `jsc.utils.isEqual` doesn't care about key ordering [#123](https://github.com/jsverify/jsverify/issues/123)
672 - tuple's shrink is blessed [#124](https://github.com/jsverify/jsverify/issues/124)
673- **0.6.2** &mdash; *2015-07-13* &mdash; Trampolines
674- **0.6.1** &mdash; *2015-07-13* &mdash; Bug fixes
675 - Print stacktrace of catched exceptions
676 - `maxsize = 0` for numeric generators works
677 - Issue with non-parametric jsc.property returning property.
678- **0.6.0** &mdash; *2015-06-19* &mdash; Minor but major release!
679 - added `jsc.utils.isApproxEqual`
680- **0.6.0-beta.2** &mdash; *2015-05-31* &mdash; Beta!
681 - Fix issue [#113](https://github.com/jsverify/jsverify/issues/113) - Shrink of tuple with arrays failed.
682- **0.6.0-beta.1** &mdash; *2015-05-04* &mdash; Beta!
683 - FAQ section
684 - Improved `smap` documentation
685 - `flatmap` is also `flatMap`
686 - Fix function arbitrary
687 - `small` arbitraries
688 - `jsc.generator.record`
689 - Thanks to @peterjoel for reporting issues
690- **0.6.0-alpha.6** &mdash; *2015-04-25* &mdash; Fix issues #98
691 - Documentation improvements
692 - Fix issue [#98](https://github.com/jsverify/jsverify/issues/98) - error while generating `int32` values
693- **0.6.0-alpha.5** &mdash; *2015-04-23* &mdash; Fix issue #99
694 - Documentation improvements
695 - Fix issue #99 (`suchthat` shrink)
696- **0.6.0-alpha.4** &mdash; *2015-04-26* &mdash; Fix issue #87
697 - jsc.property didn't fail with asynchronous properties
698 - thanks @Ezku for reporting
699- **0.6.0-alpha.3** &mdash; *2015-04-24* &mdash; promise shrink fixed
700- **0.6.0-alpha.2** &mdash; *2015-04-24* &mdash; jsc.bless
701 - Added `jsc.bless`
702- **0.6.0-alpha.1** &mdash; *2015-04-22* &mdash; Preview
703 - Using lazy sequences for shrink results
704 - *Breaking changes:*
705 - `jsc.map` renamed to `jsc.dict`
706 - `jsc.value` removed, use `jsc.json`
707 - `jsc.string()` removed, use `jsc.string`
708 - `shrink.isomap` renamed to `shrink.smap`
709- **0.5.3** &mdash; *2015-04-21* &mdash; More algebra
710 - `unit` and `either` arbitraries
711 - `arbitrary.smap` to help creating compound data
712- **0.5.2** &mdash; *2015-04-10* &mdash; `show.def` -change
713- **0.5.1** &mdash; *2015-02-19* &mdash; Dependencies bump
714 - We also work on 0.12 and iojs!
715- **0.5.0** &mdash; *2014-12-24* &mdash; Merry Chrismas 2014!
716 - Documentation cleanup
717- **0.5.0-beta.2** &mdash; *2014-12-21* &mdash; Beta 2!
718 - Pair &amp; tuple related code cleanup
719 - Update `CONTRIBUTING.md`
720 - Small documentation type fixes
721 - Bless `jsc.elements` shrink
722- **0.5.0-beta.1** &mdash; *2014-12-20* &mdash; Beta!
723 - `bless` don't close over (uses `this`)
724 - Cleanup generator module
725 - Other code cleanup here and there
726- **0.4.6** &mdash; *2014-11-30* &mdash; better shrinks &amp; recursive
727 - Implemented shrinks: [#51](https://github.com/jsverify/jsverify/issues/51)
728 - `jsc.generator.recursive`: [#37](https://github.com/jsverify/jsverify/issues/37)
729 - array, nearray &amp; map generators return a bit smaller results (*log2* of size)
730- **0.4.5** &mdash; *2014-11-22* &mdash; stuff
731 - `generator.combine` &amp; `.flatmap`
732 - `nat`, `integer`, `number` &amp; and `string` act as objects too
733- **0.4.4** &mdash; *2014-11-22* &mdash; new generators
734 - New generators: `nearray`, `nestring`
735 - `generator.constant`
736 - zero-ary `jsc.property` (it ∘ assert)
737 - `jsc.sampler`
738- **0.4.3** &mdash; *2014-11-08* &mdash; jsc.property
739 - Now you can write your bdd specs without any boilerplate
740 - support for nat-litearls in dsl [#36](https://github.com/jsverify/jsverify/issues/36)
741 ```js
742 describe("Math.abs", function () {
743 jsc.property("result is non-negative", "integer 100", function (x) {
744 return Math.abs(x) >= 0;
745 });
746 });
747 ```
748 - Falsy generator [#42](https://github.com/jsverify/jsverify/issues/42)
749- **0.4.2** &mdash; *2014-11-03* &mdash; User environments for DSL
750 - User environments for DSL
751 - Generator prototype `map`, and shrink prototype `isomap`
752 - JSON generator works with larger sizes
753- **0.4.1** Move to own organization in GitHub
754- **0.4.0** &mdash; *2014-10-27* &mdash; typify-dsl &amp; more arbitraries.
755 Changes from **0.3.6**:
756 - DSL for `forall` and `suchthat`
757 - new primitive arbitraries
758 - `oneof` behaves as in QuickCheck (BREAKING CHANGE)
759 - `elements` is new name of old `oneof`
760 - Other smaller stuff under the hood
761- **0.4.0**-beta.4 generator.oneof
762- **0.4.0**-beta.3 Expose shrink and show modules
763- **0.4.0**-beta.2 Move everything around
764 - Better looking README.md!
765- **0.4.0**-beta.1 Beta!
766 - Dev Dependencies update
767- **0.4.0**-alpha8 oneof &amp; record -dsl support
768 - also `jsc.compile`
769 - record is shrinkable!
770- **0.4.0**-alpha7 oneof &amp; record
771 - *oneof* and *record* generator combinators ([@fson](https://github.com/fson))
772 - Fixed uint\* generators
773 - Default test size increased to 10
774 - Numeric generators with size specified are independent of test size ([#20](https://github.com/phadej/jsverify/issues/20))
775- **0.4.0**-alpha6 more primitives
776 - int8, int16, int32, uint8, uint16, uint32
777 - char, asciichar and asciistring
778 - value &rarr; json
779 - use eslint
780- **0.4.0**-alpha5 move david to be devDependency
781- **0.4.0**-alpha4 more typify
782 - `suchchat` supports typify dsl
783 - `oneof` &rarr; `elements` to be in line with QuickCheck
784 - Added versions of examples using typify dsl
785- **0.4.0**-alpha3 David, npm-freeze and jscs
786- **0.4.0**-alpha2 Fix typo in readme
787- **0.4.0**-alpha1 typify
788 - DSL for `forall`
789 ```js
790 var bool_fn_applied_thrice = jsc.forall("bool -> bool", "bool", check);
791 ```
792
793 - generator arguments, which are functions are evaluated. One can now write:
794 ```js
795 jsc.forall(jsc.nat, check) // previously had to be jsc.nat()
796 ```
797
798- **0.3.6** map generator
799- **0.3.5** Fix forgotten rngState in console output
800- **0.3.4** Dependencies update
801- **0.3.3** Dependencies update
802- **0.3.2** `fun` &rarr; `fn`
803- **0.3.1** Documentation typo fixes
804- **0.3.0** Major changes
805 - random generate state handling
806 - `--jsverifyRngState` parameter value used when run on node
807 - karma tests
808 - use make
809 - dependencies update
810- **0.2.0** Use browserify
811- **0.1.4** Mocha test suite
812 - major cleanup
813- **0.1.3** gen.show and exception catching
814- **0.1.2** Added jsc.assert
815- **0.1.1** Use grunt-literate
816- **0.1.0** Usable library
817- **0.0.2** Documented preview
818- **0.0.1** Initial preview
819
820## Related work
821
822### JavaScript
823
824- [JSCheck](http://www.jscheck.org/)
825- [claire](https://npmjs.org/package/claire)
826- [gent](https://npmjs.org/package/gent)
827- [fatcheck](https://npmjs.org/package/fatcheck)
828- [quickcheck](https://npmjs.org/package/quickcheck)
829- [qc.js](https://bitbucket.org/darrint/qc.js/)
830- [quick\_check](https://www.npmjs.org/package/quick_check)
831- [gentest](https://github.com/graue/gentest)
832- [node-quickcheck](https://github.com/mcandre/node-quickcheck)
833
834### Others
835
836- [Wikipedia - QuickCheck](http://en.wikipedia.org/wiki/QuickCheck)
837- [Haskell - QuickCheck](http://hackage.haskell.org/package/QuickCheck) [Introduction](http://www.haskell.org/haskellwiki/Introduction_to_QuickCheck1)
838- [Erlang - QuviQ](http://www.quviq.com/index.html)
839- [Erlang - triq](https://github.com/krestenkrab/triq)
840- [Scala - ScalaCheck](https://github.com/rickynils/scalacheck)
841- [Clojure - test.check](https://github.com/clojure/test.check)
842- [Python - Hypothesis](https://github.com/DRMacIver/hypothesis)
843
844The MIT License (MIT)
845
846Copyright (c) 2013-2015 Oleg Grenrus
847
848Permission is hereby granted, free of charge, to any person obtaining a copy
849of this software and associated documentation files (the "Software"), to deal
850in the Software without restriction, including without limitation the rights
851to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
852copies of the Software, and to permit persons to whom the Software is
853furnished to do so, subject to the following conditions:
854
855The above copyright notice and this permission notice shall be included in
856all copies or substantial portions of the Software.
857
858THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
859IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
860FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
861AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
862LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
863OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
864THE SOFTWARE.