Skip to content

Commit 8415106

Browse files
committed
Support generator shrinking
1 parent 68b6263 commit 8415106

File tree

4 files changed

+58
-36
lines changed

4 files changed

+58
-36
lines changed

documentation/index.md

+17-14
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,24 @@ repository: https://github.com/unexpectedjs/unexpected-check
1010

1111
<img alt="Checkmate!" src="./unexpected-check.jpg" style="display: block; max-width: 100%">
1212

13-
This plugin tries to bring property testing to the
13+
This plugin tries to bring generative testing (aka property testing) to the
1414
[unexpected](http://unexpected.js.org) assertion library. The idea is that it
1515
should be possible to mix property based testing and normal unit-tests using the
1616
same tool chain.
1717

18-
This project is still in it early days and features such as failure shrinking
19-
and asynchronous testing are missing. It is currently not possible to configure
20-
the number of iterations the tests should be executes either
18+
If the generators you supply supports shrinking by providing a `shrink` function
19+
on the generator function, unexpected-check will try to shrink the error space
20+
as much as possible and therefore provide much more precise error cases.
21+
22+
This project is still in it early days and asynchronous testing are missing. It
23+
is currently not possible to configure the number of iterations the tests should
24+
be executed either.
2125

2226
I recommend using the plugin together with
23-
[chance-generators](https://github.com/sunesimonsen/change-generators), but it
24-
is not a requirement. You can uses any function that produces a random output
25-
when called as generators.
27+
[chance-generators](https://github.com/sunesimonsen/change-generators) as it
28+
provides a huge range of generators and supports shrinking, but it is not a
29+
requirement. You can uses any function that produces a random output when called
30+
as generators.
2631

2732
## Usage
2833

@@ -59,18 +64,16 @@ But that assumption as actually not true as the build in sort functions is based
5964
on converting items to strings and comparing them. So you will get the following error:
6065

6166
```output
62-
Ran 23 iterations and found 20 errors
67+
Ran 44 iterations and found 20 errors
6368
counterexample:
6469
65-
Generated input: [ -19, -2, -16 ]
70+
Generated input: [ 18, 4 ]
6671
67-
expected [ -16, -19, -2 ]
68-
first item to be less than or equal to all [ -19, -2, -16 ]
72+
expected [ 18, 4 ] first item to be less than or equal to all [ 18, 4 ]
6973
7074
[
71-
-19, // should be greater than or equal to -16
72-
-2,
73-
-16
75+
18,
76+
4 // should be greater than or equal to 18
7477
]
7578
```
7679

lib/unexpected-check.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@
5454
var generators = Array.prototype.slice.call(arguments, 2);
5555

5656
function createTask() {
57-
var args = generators.map(function (generator) {
58-
return generator();
57+
var args = generators.map(function (g) {
58+
return g();
5959
});
6060

6161
var task = {
@@ -65,6 +65,9 @@
6565
try {
6666
subject.apply(null, args);
6767
} catch (e) {
68+
generators = generators.map(function (g, i) {
69+
return g.shrink ? g.shrink(args[i]) : g;
70+
});
6871
task.error = convertToUnexpectedError(e);
6972
}
7073

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"author": "Sune Simonsen",
1919
"license": "MIT",
2020
"devDependencies": {
21-
"chance-generators": "1.0.1",
21+
"chance-generators": "1.1.0",
2222
"eslint": "1.10.3",
2323
"eslint-config-onelint": "0.0.2",
2424
"lodash.escape": "3.1.0",

test/unexpected-check.spec.js

+35-19
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,16 @@ describe('unexpected-check', function () {
4040
.and('last item to be greater than or equal to all', arr);
4141
}, 'to be valid for all', arrays);
4242
}, 'to throw',
43-
'Ran 23 iterations and found 20 errors\n' +
43+
'Ran 44 iterations and found 20 errors\n' +
4444
'counterexample:\n' +
4545
'\n' +
46-
' Generated input: [ -19, -2, -16 ]\n' +
46+
' Generated input: [ 18, 4 ]\n' +
4747
'\n' +
48-
' expected [ -16, -19, -2 ]\n' +
49-
' first item to be less than or equal to all [ -19, -2, -16 ]\n' +
48+
' expected [ 18, 4 ] first item to be less than or equal to all [ 18, 4 ]\n' +
5049
'\n' +
5150
' [\n' +
52-
' -19, // should be greater than or equal to -16\n' +
53-
' -2,\n' +
54-
' -16\n' +
51+
' 18,\n' +
52+
' 4 // should be greater than or equal to 18\n' +
5553
' ]');
5654
});
5755

@@ -61,19 +59,15 @@ describe('unexpected-check', function () {
6159
expect(arr, 'not to contain', 2);
6260
}, 'to be valid for all', arrays);
6361
}, 'to throw',
64-
'Ran 52 iterations and found 20 errors\n' +
62+
'Ran 25 iterations and found 20 errors\n' +
6563
'counterexample:\n' +
6664
'\n' +
67-
' Generated input: [ 2, -17, 9, -13, 7 ]\n' +
65+
' Generated input: [ 2 ]\n' +
6866
'\n' +
69-
' expected [ 2, -17, 9, -13, 7 ] not to contain 2\n' +
67+
' expected [ 2 ] not to contain 2\n' +
7068
'\n' +
7169
' [\n' +
72-
' 2, // should be removed\n' +
73-
' -17,\n' +
74-
' 9,\n' +
75-
' -13,\n' +
76-
' 7\n' +
70+
' 2 // should be removed\n' +
7771
' ]');
7872
});
7973

@@ -93,15 +87,37 @@ describe('unexpected-check', function () {
9387
expect(items, 'not to contain', i);
9488
}, 'to be valid for all', arrays, g.integer({ min: -20, max: 20 }));
9589
}, 'to throw',
96-
'Ran 96 iterations and found 20 errors\n' +
90+
'Ran 100 iterations and found 18 errors\n' +
9791
'counterexample:\n' +
9892
'\n' +
99-
' Generated input: [ -7 ], -7\n' +
93+
' Generated input: [ 3 ], 3\n' +
10094
'\n' +
101-
' expected [ -7 ] not to contain -7\n' +
95+
' expected [ 3 ] not to contain 3\n' +
10296
'\n' +
10397
' [\n' +
104-
' -7 // should be removed\n' +
98+
' 3 // should be removed\n' +
99+
' ]');
100+
});
101+
102+
it('finds needle in a haystack errors', function () {
103+
expect(function () {
104+
expect(function (items) {
105+
expect(items, 'to have items satisfying', function (item, i) {
106+
expect(item, 'not to be', i);
107+
});
108+
}, 'to be valid for all', arrays);
109+
}, 'to throw',
110+
'Ran 100 iterations and found 17 errors\n' +
111+
'counterexample:\n' +
112+
'\n' +
113+
' Generated input: [ -19, 1 ]\n' +
114+
'\n' +
115+
' expected [ -19, 1 ]\n' +
116+
' to have items satisfying function (item, i) { expect(item, \'not to be\', i); }\n' +
117+
'\n' +
118+
' [\n' +
119+
' -19,\n' +
120+
' 1 // should not be 1\n' +
105121
' ]');
106122
});
107123
});

0 commit comments

Comments
 (0)