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 |
|
15 | Install the module with: `npm install jsverify`
|
16 |
|
17 | ## Synopsis
|
18 |
|
19 | ```js
|
20 | var jsc = require("jsverify");
|
21 |
|
22 | // forall (f : bool -> bool) (b : bool), f (f (f b)) = f(b).
|
23 | var boolFnAppliedThrice =
|
24 | jsc.forall("bool -> bool", "bool", function (f, b) {
|
25 | return f(f(f(b))) === f(b);
|
26 | });
|
27 |
|
28 | jsc.assert(boolFnAppliedThrice);
|
29 | // OK, passed 100 tests
|
30 | ```
|
31 |
|
32 | ## Documentation
|
33 |
|
34 | ### Usage with [mocha](http://visionmedia.github.io/mocha/)
|
35 |
|
36 | Using jsverify with mocha is easy, just define the properties and use `jsverify.assert`.
|
37 |
|
38 | Starting from version 0.4.3 you can write your specs without any boilerplate:
|
39 |
|
40 | ```js
|
41 | describe("sort", function () {
|
42 | jsc.property("idempotent", "array nat", function (arr) {
|
43 | return _.isEqual(sort(sort(arr)), sort(arr));
|
44 | });
|
45 | });
|
46 | ```
|
47 |
|
48 | You can also provide `--jsverifyRngState state` command line argument, to run tests with particular random generator state.
|
49 |
|
50 | ```
|
51 | $ mocha examples/nat.js
|
52 |
|
53 | 1) natural numbers are less than 90:
|
54 | Error: Failed after 49 tests and 1 shrinks. rngState: 074e9b5f037a8c21d6; Counterexample: 90;
|
55 |
|
56 | $ mocha examples/nat.js --grep 'are less than' --jsverifyRngState 074e9b5f037a8c21d6
|
57 |
|
58 | 1) natural numbers are less than 90:
|
59 | Error: Failed after 1 tests and 1 shrinks. rngState: 074e9b5f037a8c21d6; Counterexample: 90;
|
60 | ```
|
61 |
|
62 | Errorneous case is found with first try.
|
63 |
|
64 | ### Usage with [jasmine](http://pivotal.github.io/jasmine/)
|
65 |
|
66 | Check [jasmineHelpers.js](helpers/jasmineHelpers.js) and [jasmineHelpers2.js](helpers/jasmineHelpers2.js) for jasmine 1.3 and 2.0 respectively.
|
67 |
|
68 | ## API
|
69 |
|
70 | > _Testing shows the presence, not the absence of bugs._
|
71 | >
|
72 | > Edsger W. Dijkstra
|
73 |
|
74 | To show that propositions hold, we need to construct proofs.
|
75 | There are two extremes: proof by example (unit tests) and formal (machine-checked) proof.
|
76 | Property-based testing is somewhere in between.
|
77 | We formulate propositions, invariants or other properties we believe to hold, but
|
78 | only test it to hold for numerous (randomly generated) values.
|
79 |
|
80 | Types and function signatures are written in [Coq](http://coq.inria.fr/)/[Haskell](http://www.haskell.org/haskellwiki/Haskell) influented style:
|
81 | C# -style `List<T> filter(List<T> v, Func<T, bool> predicate)` is represented by
|
82 | `filter (v : array T) (predicate : T -> bool) : array T` in our style.
|
83 |
|
84 | `jsverify` can operate with both synchronous and asynchronous-promise properties.
|
85 | Generally every property can be wrapped inside [functor](http://learnyouahaskell.com/functors-applicative-functors-and-monoids),
|
86 | for now in either identity or promise functor, for synchronous and promise properties respectively.
|
87 |
|
88 | ### Properties
|
89 |
|
90 | - `forall(arbs: arbitrary a ..., userenv: (map arbitrary)?, prop : a -> property): property`
|
91 |
|
92 | Property constructor
|
93 |
|
94 | - `check (prop: property, opts: checkoptions?): result`
|
95 |
|
96 | Run random checks for given `prop`. If `prop` is promise based, result is also wrapped in promise.
|
97 |
|
98 | Options:
|
99 | - `opts.tests` - test count to run, default 100
|
100 | - `opts.size` - maximum size of generated values, default 5
|
101 |
|
102 | - `opts.quiet` - do not `console.log`
|
103 | - `opts.rngState` - state string for the rng
|
104 |
|
105 | - `assert(prop: property, opts: checkoptions?) : void`
|
106 |
|
107 | Same as `check`, but throw exception if property doesn't hold.
|
108 |
|
109 | - `property(name: string, ...)`
|
110 |
|
111 | Assuming there is globally defined `it`, the same as:
|
112 |
|
113 | ```js
|
114 | it(name, function () {
|
115 | jsc.assert(jsc.forall(...));
|
116 | }
|
117 | ```
|
118 |
|
119 | You can use `property` to write facts too:
|
120 | ```js
|
121 | jsc.property("+0 === -0", function () {
|
122 | return +0 === -0;
|
123 | });
|
124 | ```
|
125 |
|
126 | - `sampler(arb: arbitrary a, genSize: nat = 10): (sampleSize: nat?) -> a`
|
127 |
|
128 | Create a sampler for a given arbitrary with an optional size. Handy when used in
|
129 | a REPL:
|
130 | ```
|
131 | > jsc = require('jsverify') // or require('./lib/jsverify') w/in the project
|
132 | ...
|
133 | > jsonSampler = jsc.sampler(jsc.json, 4)
|
134 | [Function]
|
135 | > jsonSampler()
|
136 | 0.08467432763427496
|
137 | > jsonSampler()
|
138 | [ [ [] ] ]
|
139 | > jsonSampler()
|
140 | ''
|
141 | > sampledJson(2)
|
142 | [-0.4199344692751765, false]
|
143 | ```
|
144 |
|
145 | ### Types
|
146 |
|
147 | - `generator a` is a function `(size: nat) -> a`.
|
148 | - `show` is a function `a -> string`.
|
149 | - `shrink` is a function `a -> [a]`, returning *smaller* values.
|
150 | - `arbitrary a` is a triple of generator, shrink and show functions.
|
151 | - `{ generator: nat -> a, shrink : a -> array a, show: a -> string }`
|
152 |
|
153 | ### DSL for input parameters
|
154 |
|
155 | There is a small DSL to help with `forall`. For example the two definitions below are equivalent:
|
156 | ```js
|
157 | var bool_fn_applied_thrice = jsc.forall("bool -> bool", "bool", check);
|
158 | var bool_fn_applied_thrice = jsc.forall(jsc.fn(jsc.bool()), jsc.bool(), check);
|
159 | ```
|
160 |
|
161 | The DSL is based on a subset of language recognized by [typify-parser](https://github.com/phadej/typify-parser):
|
162 | - *identifiers* are fetched from the predefined environment.
|
163 | - *applications* are applied as one could expect: `"array bool"` is evaluated to `jsc.array(jsc.bool)`.
|
164 | - *functions* are supported: `"bool -> bool"` is evaluated to `jsc.fn(jsc.bool())`.
|
165 | - *square brackets* are treated as a shorthand for the array type: `"[nat]"` is evaluated to `jsc.array(jsc.nat)`.
|
166 |
|
167 | ### Arbitrary data
|
168 |
|
169 | - `arb.bless({...}): arbitrary a`
|
170 |
|
171 | Bless generator, shrink, show triple with with `.smap` property.
|
172 |
|
173 | - `.smap(f: a -> b, g: b -> a, newShow: (b -> string)?): arbitrary b`
|
174 |
|
175 | Transform `arbitrary a` into `arbitrary b`. For example:
|
176 |
|
177 | `g` should be a [right inverse](http://en.wikipedia.org/wiki/Surjective_function#Surjections_as_right_invertible_functions) of `f`.
|
178 |
|
179 | ```js
|
180 | positiveIntegersArb = nat.smap(
|
181 | function (x) { return x + 1; },
|
182 | function (x) { return x - 1; });
|
183 | ```
|
184 |
|
185 | ### Primitive arbitraries
|
186 |
|
187 | - `integer: arbitrary integer`
|
188 | - `integer(maxsize: nat): arbitrary integer`
|
189 | - `integer(minsize: integer, maxsize: integer): arbitrary integer`
|
190 |
|
191 | Integers, ℤ
|
192 |
|
193 | - `nat: arbitrary nat`
|
194 | - `nat(maxsize: nat): arbitrary nat`
|
195 |
|
196 | Natural numbers, ℕ (0, 1, 2...)
|
197 |
|
198 | - `number: arbitrary number`
|
199 | - `number(maxsize: number): arbitrary number`
|
200 | - `number(min: number, max: number): arbitrary number`
|
201 |
|
202 | JavaScript numbers, "doubles", ℝ. `NaN` and `Infinity` are not included.
|
203 |
|
204 | - `uint8: arbitrary nat`
|
205 | - `uint16: arbitrary nat`
|
206 | - `uint32: arbitrary nat`
|
207 |
|
208 | - `int8: arbitrary integer`
|
209 | - `int16: arbitrary integer`
|
210 | - `int32: arbitrary integer`
|
211 |
|
212 | - `bool: arbitrary bool`
|
213 |
|
214 | Booleans, `true` or `false`.
|
215 |
|
216 | - `datetime: arbitrary datetime`
|
217 |
|
218 | Random datetime
|
219 |
|
220 | - `elements(args: array a): arbitrary a`
|
221 |
|
222 | Random element of `args` array.
|
223 |
|
224 | - `char: arbitrary char`
|
225 |
|
226 | Single character
|
227 |
|
228 | - `asciichar: arbitrary char`
|
229 |
|
230 | Single ascii character (0x20-0x7e inclusive, no DEL)
|
231 |
|
232 | - `string: arbitrary string`
|
233 |
|
234 | - `notEmptyString: arbitrary string`
|
235 |
|
236 | Generates strings which are not empty.
|
237 |
|
238 | - `asciistring: arbitrary string`
|
239 |
|
240 | - `json: arbitrary json`
|
241 |
|
242 | JavaScript Objects: boolean, number, string, array of `json` values or object with `json` values.
|
243 |
|
244 | - `value: arbitrary json`
|
245 |
|
246 | - `falsy: arbitrary *`
|
247 |
|
248 | Generates falsy values: `false`, `null`, `undefined`, `""`, `0`, and `NaN`.
|
249 |
|
250 | - `constant(x: a): arbitrary a`
|
251 |
|
252 | Returns an unshrinkable arbitrary that yields the given object.
|
253 |
|
254 | ### Arbitrary combinators
|
255 |
|
256 | - `nonshrink(arb: arbitrary a): arbitrary a`
|
257 |
|
258 | Non shrinkable version of arbitrary `arb`.
|
259 |
|
260 | - `array(arb: arbitrary a): arbitrary (array a)`
|
261 |
|
262 | - `nearray(arb: arbitrary a): arbitrary (array a)`
|
263 |
|
264 | - `unit: arbitrary ()`
|
265 |
|
266 | - `either(arbA: arbitrary a, arbB : arbitrary b): arbitrary (either a b)`
|
267 |
|
268 | - `pair(arbA: arbitrary a, arbB : arbitrary b): arbitrary (pair a b)`
|
269 |
|
270 | If not specified `a` and `b` are equal to `value()`.
|
271 |
|
272 | - `tuple(arbs: (arbitrary a, arbitrary b...)): arbitrary (a, b...)`
|
273 |
|
274 | - `map(arb: arbitrary a): arbitrary (map a)`
|
275 |
|
276 | Generates a JavaScript object with properties of type `A`.
|
277 |
|
278 | - `oneof(gs : array (arbitrary a)...) : arbitrary a`
|
279 |
|
280 | Randomly uses one of the given arbitraries.
|
281 |
|
282 | - `record(spec: { key: arbitrary a... }): arbitrary { key: a... }`
|
283 |
|
284 | Generates a javascript object with given record spec.
|
285 |
|
286 | - `fn(arb: arbitrary a): arbitrary (b -> a)`
|
287 | - `fun(arb: arbitrary a): arbitrary (b -> a)`
|
288 |
|
289 | ### Generator functions
|
290 |
|
291 | A generator function, `generator a`, is a function `(size: nat) -> a`, which generates a value of given size.
|
292 |
|
293 | Generator combinators are auto-curried:
|
294 |
|
295 | ```js
|
296 | var xs = generator.array(shrink.nat, 1); // ≡
|
297 | var ys = generator.array(shrink.nat)(1);
|
298 | ```
|
299 |
|
300 | In purely functional approach `generator a` would be explicitly stateful computation:
|
301 | `(size: nat, rng: randomstate) -> (a, randomstate)`.
|
302 | *JSVerify* uses an implicit random number generator state,
|
303 | but the value generation is deterministic (tests reproduceable),
|
304 | if the primitives from *random* module are used.
|
305 |
|
306 | - `generator.bless(f: nat -> a): generator a`
|
307 |
|
308 | Bless function with `.map` and `.flatmap` properties.
|
309 |
|
310 | - `.map(f: a -> b): generator b`
|
311 |
|
312 | Map `generator a` into `generator b`. For example:
|
313 |
|
314 | ```js
|
315 | positiveIntegersGenerator = nat.generator.map(
|
316 | function (x) { return x + 1; });
|
317 | ```
|
318 |
|
319 | - `.isomap(f: a -> generator b): generator b`
|
320 |
|
321 | Monadic bind for generators.
|
322 |
|
323 | - `generator.constant(x: a): generator a`
|
324 |
|
325 | - `generator.combine(gen: generator a..., f: a... -> b): generator b`
|
326 |
|
327 | - `generator.oneof(gens: list (generator a)): generator a`
|
328 |
|
329 | - `generator.recursive(genZ: generator a, genS: generator a -> generator a): generator a`
|
330 |
|
331 | - `generator.pair(genA: generator a, genB: generator b): generator (a, b)`
|
332 |
|
333 | - `generator.either(genA: generator a, genB: generator b): generator (either a b)`
|
334 |
|
335 | - `generator.unit: generator ()
|
336 |
|
337 | `unit` is an empty tuple, i.e. empty array in JavaScript representation. This is useful as a building block.
|
338 |
|
339 | - `generator.tuple(gens: (generator a, generator b...): generator (a, b...)`
|
340 |
|
341 | - `generator.array(gen: generator a): generator (array a)`
|
342 |
|
343 | - `generator.nearray(gen: generator a): generator (array a)`
|
344 |
|
345 | - `generator.char: generator char`
|
346 |
|
347 | - `generator.string: generator string`
|
348 |
|
349 | - `generator.nestring: generator string`
|
350 |
|
351 | - `generator.asciichar: generator char`
|
352 |
|
353 | - `generator.asciistring: generator string`
|
354 |
|
355 | - `generator.map(gen: generator a): generator (map a)`
|
356 |
|
357 | - `generator.json: generator json`
|
358 |
|
359 | ### Shrink functions
|
360 |
|
361 | A shrink function, `shrink a`, is a function `a -> [a]`, returning an array of *smaller* values.
|
362 |
|
363 | Shrink combinators are auto-curried:
|
364 |
|
365 | ```js
|
366 | var xs = shrink.array(shrink.nat, [1]); // ≡
|
367 | var ys = shrink.array(shrink.nat)([1]);
|
368 | ```
|
369 |
|
370 | - `shrink.bless(f: a -> [a]): shrink a`
|
371 |
|
372 | Bless function with `.isomap` property.
|
373 |
|
374 | - `.isomap(f: a -> b, g: b -> a): shrink b`
|
375 |
|
376 | Transform `shrink a` into `shrink b`. For example:
|
377 |
|
378 | ```js
|
379 | positiveIntegersShrink = nat.shrink.isomap(
|
380 | function (x) { return x + 1; },
|
381 | function (x) { return x - 1; });
|
382 | ```
|
383 |
|
384 | - `shrink.noop: shrink a`
|
385 |
|
386 | - `shrink.pair(shrA: shrink a, shrB: shrink b): shrink (a, b)`
|
387 |
|
388 | - `shrink.either(shrA: shrink a, shrB: shrink b): shrink (either a b)`
|
389 |
|
390 | - `shrink.tuple(shrs: (shrink a, shrink b...)): shrink (a, b...)`
|
391 |
|
392 | - `shrink.array(shr: shrink a): shrink (array a)`
|
393 |
|
394 | - `shrink.nearray(shr: shrink a): shrink (nearray a)`
|
395 |
|
396 | - `shrink.record(shrs: { key: shrink a... }): shrink { key: a... }`
|
397 |
|
398 | ### Show functions
|
399 |
|
400 | - `show.def(x : a): string`
|
401 |
|
402 | Currently implemented as `JSON.stringify`.
|
403 |
|
404 | - `show.pair(showA: a -> string, showB: b -> string, x: (a, b)): string`
|
405 |
|
406 | - `show.either(showA: a -> string, showB: b -> string, e: either a b): string`
|
407 |
|
408 | - `show.tuple(shrinks: (a -> string, b -> string...), x: (a, b...)): string`
|
409 |
|
410 | - `show.array(shrink: a -> string, x: array a): string`
|
411 |
|
412 | ### Random functions
|
413 |
|
414 | - `random(min: int, max: int): int`
|
415 |
|
416 | Returns random int from `[min, max]` range inclusively.
|
417 |
|
418 | ```js
|
419 | getRandomInt(2, 3) // either 2 or 3
|
420 | ```
|
421 |
|
422 | - `random.number(min: number, max: number): number`
|
423 |
|
424 | Returns random number from `[min, max)` range.
|
425 |
|
426 | ### either
|
427 |
|
428 | - `either.left(value: a): either a b`
|
429 |
|
430 | - `either.right(value: b): either a b`
|
431 |
|
432 | - `either.either(l: a -> x, r: b -> x): x`
|
433 |
|
434 | - `either.isEqual(other: either a b): bool
|
435 |
|
436 | TODO: add `eq` optional parameter
|
437 |
|
438 | - `either.bimap(f: a -> c, g: b -> d): either c d`
|
439 |
|
440 | ```js
|
441 | either.bimap(compose(f, g), compose(h, i)) ≡ either.bimap(g, i).bimap(f, h);
|
442 | ```
|
443 |
|
444 | - `either.first(f: a -> c): either c b`
|
445 |
|
446 | ```js
|
447 | either.first(f) ≡ either.bimap(f, utils.identity)
|
448 | ```
|
449 |
|
450 | - `either.second(g: b -> d): either a d`
|
451 |
|
452 | ```js
|
453 | either.second(g) === either.bimap(utils.identity, g)
|
454 | ```
|
455 |
|
456 | ### Utility functions
|
457 |
|
458 | Utility functions are exposed (and documented) only to make contributions to jsverify more easy.
|
459 | The changes here don't follow semver, i.e. there might be backward-incompatible changes even in patch releases.
|
460 |
|
461 | Use [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.
|
462 |
|
463 | - `utils.isEqual(x: json, y: json): bool`
|
464 |
|
465 | Equality test for `json` objects.
|
466 |
|
467 | - `utils.force(x: a | () -> a) : a`
|
468 |
|
469 | Evaluate `x` as nullary function, if it is one.
|
470 |
|
471 | - `utils.merge(x: obj, y: obj): obj`
|
472 |
|
473 | Merge two objects, a bit like `_.extend({}, x, y)`.
|
474 |
|
475 | ## Contributing
|
476 |
|
477 | - `README.md` is generated from the source with [ljs](https://github.com/phadej/ljs)
|
478 | - `jsverify.standalone.js` is also generated by the build process
|
479 | - Before creating a pull request run `make test`, yet travis will do it for you.
|
480 |
|
481 | ## Release History
|
482 |
|
483 | - **0.5.3** — *2015-04-21* — More algebra
|
484 | - `unit` and `either` arbitraries
|
485 | - `arbitrary.smap` to help creating compound data
|
486 | - **0.5.2** — *2015-04-10* — `show.def` -change
|
487 | - **0.5.1** — *2015-02-19* — Dependencies bump
|
488 | - We also work on 0.12 and iojs!
|
489 | - **0.5.0** — *2014-12-24* — Merry Chrismas 2014!
|
490 | - Documention cleanup
|
491 | - **0.5.0-beta.2** — *2014-12-21* — Beta 2!
|
492 | - Pair & tuple related code cleanup
|
493 | - Update `CONTRIBUTING.md`
|
494 | - Small documentation type fixes
|
495 | - Bless `jsc.elements` shrink
|
496 | - **0.5.0-beta.1** — *2014-12-20* — Beta!
|
497 | - `bless` don't close over (uses `this`)
|
498 | - Cleanup generator module
|
499 | - Other code cleanup here and there
|
500 | - **0.4.6** — *2014-11-30* — better shrinks & recursive
|
501 | - Implemented shrinks: [#51](https://github.com/jsverify/jsverify/issues/51)
|
502 | - `jsc.generator.recursive`: [#37](https://github.com/jsverify/jsverify/issues/37)
|
503 | - array, nearray & map generators return a bit smaller results (*log2* of size)
|
504 | - **0.4.5** — *2014-11-22* — stuff
|
505 | - `generator.combine` & `.flatmap`
|
506 | - `nat`, `integer`, `number` & and `string` act as objects too
|
507 | - **0.4.4** — *2014-11-22* — new generators
|
508 | - New generators: `nearray`, `nestring`
|
509 | - `generator.constant`
|
510 | - zero-ary `jsc.property` (it ∘ assert)
|
511 | - `jsc.sampler`
|
512 | - **0.4.3** — *2014-11-08* — jsc.property
|
513 | - Now you can write your bdd specs without any boilerplate
|
514 | - support for nat-litearls in dsl [#36](https://github.com/jsverify/jsverify/issues/36)
|
515 | ```js
|
516 | describe("Math.abs", function () {
|
517 | jsc.property("result is non-negative", "integer 100", function (x) {
|
518 | return Math.abs(x) >= 0;
|
519 | });
|
520 | });
|
521 | ```
|
522 | - Falsy generator [#42](https://github.com/jsverify/jsverify/issues/42)
|
523 | - **0.4.2** — *2014-11-03* — User environments for DSL
|
524 | - User environments for DSL
|
525 | - Generator prototype `map`, and shrink prototype `isomap`
|
526 | - JSON generator works with larger sizes
|
527 | - **0.4.1** Move to own organization in GitHub
|
528 | - **0.4.0** — *2014-10-27* — typify-dsl & more arbitraries.
|
529 | Changes from **0.3.6**:
|
530 | - DSL for `forall` and `suchthat`
|
531 | - new primitive arbitraries
|
532 | - `oneof` behaves as in QuickCheck (BREAKING CHANGE)
|
533 | - `elements` is new name of old `oneof`
|
534 | - Other smaller stuff under the hood
|
535 | - **0.4.0**-beta.4 generator.oneof
|
536 | - **0.4.0**-beta.3 Expose shrink and show modules
|
537 | - **0.4.0**-beta.2 Move everything around
|
538 | - Better looking README.md!
|
539 | - **0.4.0**-beta.1 Beta!
|
540 | - Dev Dependencies update
|
541 | - **0.4.0**-alpha8 oneof & record -dsl support
|
542 | - also `jsc.compile`
|
543 | - record is shrinkable!
|
544 | - **0.4.0**-alpha7 oneof & record
|
545 | - *oneof* and *record* generator combinators ([@fson](https://github.com/fson))
|
546 | - Fixed uint\* generators
|
547 | - Default test size increased to 10
|
548 | - Numeric generators with size specified are independent of test size ([#20](https://github.com/phadej/jsverify/issues/20))
|
549 | - **0.4.0**-alpha6 more primitives
|
550 | - int8, int16, int32, uint8, uint16, uint32
|
551 | - char, asciichar and asciistring
|
552 | - value → json
|
553 | - use eslint
|
554 | - **0.4.0**-alpha5 move david to be devDependency
|
555 | - **0.4.0**-alpha4 more typify
|
556 | - `suchchat` supports typify dsl
|
557 | - `oneof` → `elements` to be in line with QuickCheck
|
558 | - Added versions of examples using typify dsl
|
559 | - **0.4.0**-alpha3 David, npm-freeze and jscs
|
560 | - **0.4.0**-alpha2 Fix typo in readme
|
561 | - **0.4.0**-alpha1 typify
|
562 | - DSL for `forall`
|
563 | ```js
|
564 | var bool_fn_applied_thrice = jsc.forall("bool -> bool", "bool", check);
|
565 | ```
|
566 |
|
567 | - generator arguments, which are functions are evaluated. One can now write:
|
568 | ```js
|
569 | jsc.forall(jsc.nat, check) // previously had to be jsc.nat()
|
570 | ```
|
571 |
|
572 | - **0.3.6** map generator
|
573 | - **0.3.5** Fix forgotten rngState in console output
|
574 | - **0.3.4** Dependencies update
|
575 | - **0.3.3** Dependencies update
|
576 | - **0.3.2** `fun` → `fn`
|
577 | - **0.3.1** Documentation typo fixes
|
578 | - **0.3.0** Major changes
|
579 | - random generate state handling
|
580 | - `--jsverifyRngState` parameter value used when run on node
|
581 | - karma tests
|
582 | - use make
|
583 | - dependencies update
|
584 | - **0.2.0** Use browserify
|
585 | - **0.1.4** Mocha test suite
|
586 | - major cleanup
|
587 | - **0.1.3** gen.show and exception catching
|
588 | - **0.1.2** Added jsc.assert
|
589 | - **0.1.1** Use grunt-literate
|
590 | - **0.1.0** Usable library
|
591 | - **0.0.2** Documented preview
|
592 | - **0.0.1** Initial preview
|
593 |
|
594 | ## Related work
|
595 |
|
596 | ### JavaScript
|
597 |
|
598 | - [JSCheck](http://www.jscheck.org/)
|
599 | - [claire](https://npmjs.org/package/claire)
|
600 | - [gent](https://npmjs.org/package/gent)
|
601 | - [fatcheck](https://npmjs.org/package/fatcheck)
|
602 | - [quickcheck](https://npmjs.org/package/quickcheck)
|
603 | - [qc.js](https://bitbucket.org/darrint/qc.js/)
|
604 | - [quick\_check](https://www.npmjs.org/package/quick_check)
|
605 | - [gencheck](https://github.com/graue/gentest)
|
606 | - [node-quickcheck](https://github.com/mcandre/node-quickcheck)
|
607 |
|
608 | ### Others
|
609 |
|
610 | - [Wikipedia - QuickCheck](http://en.wikipedia.org/wiki/QuickCheck)
|
611 | - [Haskell - QuickCheck](http://hackage.haskell.org/package/QuickCheck) [Introduction](http://www.haskell.org/haskellwiki/Introduction_to_QuickCheck1)
|
612 | - [Erlang - QuviQ](http://www.quviq.com/index.html)
|
613 | - [Erlang - triq](https://github.com/krestenkrab/triq)
|
614 | - [Scala - ScalaCheck](https://github.com/rickynils/scalacheck)
|
615 | - [Clojure - test.check](https://github.com/clojure/test.check)
|
616 | - [Python - Hypothesis](https://github.com/DRMacIver/hypothesis)
|
617 |
|
618 | The MIT License (MIT)
|
619 |
|
620 | Copyright (c) 2013, 2014 Oleg Grenrus
|
621 |
|
622 | Permission is hereby granted, free of charge, to any person obtaining a copy
|
623 | of this software and associated documentation files (the "Software"), to deal
|
624 | in the Software without restriction, including without limitation the rights
|
625 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
626 | copies of the Software, and to permit persons to whom the Software is
|
627 | furnished to do so, subject to the following conditions:
|
628 |
|
629 | The above copyright notice and this permission notice shall be included in
|
630 | all copies or substantial portions of the Software.
|
631 |
|
632 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
633 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
634 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
635 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
636 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
637 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
638 | THE SOFTWARE.
|