-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathindex.html
More file actions
306 lines (239 loc) · 11.7 KB
/
index.html
File metadata and controls
306 lines (239 loc) · 11.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<title>JSVerify — property based testing for JavaScript. Like QuickCheck.</title>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<meta name="description" content"Property based testing for JavaScript. Highly inspired by QuickCheck">
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style>
@import url(http://fonts.googleapis.com/css?family=Lato:300,400|Inconsolata&subset=latin,latin-ext);
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Gill Sans", "Gill Sans MT", Calibri, 'Lato', sans-serif;
}
header {
background: #000;
width: 100vw;
height: 100vh;
position: relative;
min-width: 320px;
}
header .box {
display: block;
width: 90vmin;
height: 90vmin;
position: relative;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
background: #f0db4f;
background-size: 100% 100%;
background-image: url(https://raw.githubusercontent.com/jsverify/jsverify/master/jsverify-300.png);
text-align: center;
padding: 15vmin 0;
color: #333;
}
header a {
color: #333;
text-decoration: none;
}
a {
color: #063;
}
section {
padding: 1em 3em;
max-width: 50em;
margin: 0 auto;
}
h2, h3 {
margin-top: 1em;
}
h2, h3, blockquote, ul, p, pre {
margin-bottom: 0.5em;
}
blockquote {
border-left: 2px solid #999;
padding: 0.2em 1em 0.2em 1em;
background: #f9f9f9;
}
blockquote p {
margin: 0;
}
h2 {
font-weight: 300;
font-size: 1.8rem;
}
h3 {
font-weight: 300;
font-size: 1.5rem;
}
h2 a, h3 a {
color: #000;
text-decoration: none;
}
code {
background: #eee;
padding: 0 0.3em;
border-radius: 0.2em;
font-family: "Inconsalata-LCG", Monaco, Consolas, "Lucida Console", "Inconsalata", monospace;
font-size: 0.9rem;
}
code span {
font-family: "Inconsalata-LCG", Monaco, Consolas, "Lucida Console", "Inconsalata", monospace;
}
code span.comment {
color: #369;
font-style: italic;
}
code span.literal {
color: #396;
}
code span.variable {
color: #555;
font-style: italic;
}
pre {
padding: 0.2em 1em;
background: #eee;
border: 1px solid #ddd;
border-radius: 0.3em;
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
white-space: pre-wrap; /* CSS 3 */
overflow-y: hidden;
}
footer {
font-size: 0.8rem;
font-weight: 300;
color: #ccc;
background: #333;
padding: 1em 3em;
}
footer a {
color: #999;
}
</style>
<script src="Promise.js"></script>
<script src="underscore.js"></script>
<script src="jsverify.standalone.js"></script>
</head>
<body>
<header>
<a href="#jsverify" class="box">
<h1>JSVerify</h1>
<p>Write powerful and concise tests.</p>
</a>
</header>
<section>
<h2><a name="jsverify" class="anchor" href="#jsverify">JSVerify</a></h2>
<p>JSVerify is a property-based testing library, highly inspired by <a href="https://hackage.haskell.org/package/QuickCheck">QuickCheck</a>.
It is testing framework agnostic, you could use JSVerify with <a href="http://mochajs.org/">Mocha</a>, <a href="https://github.com/caolan/nodeunit">nodeunit</a>, <a href="http://jasmine.github.io/">Jasmine</a> or any other framework.
<h2>
<a name="property-based-testing" class="anchor" href="#property-based-testing">
Property based testing</a></h2>
<p>Write properties about your function that should hold true for all inputs, instead of enumerating expected inputs and outputs.
Tests written this way are concise and powerful.</p>
<blockquote>
<p>
Property-based tests make statements about the output of your code based on the input, and these statements are verified for many different possible inputs. <a href="http://blog.jessitron.com/2013/04/property-based-testing-what-is-it.html">[1]</a></p>
</blockquote>
<blockquote>
<p>
Property-based testing encourages a high level approach to testing in the form of abstract invariants functions should satisfy universally, with the actual test data generated for the programmer by the testing library. In this way code can be hammered with thousands of tests that would be infeasible to write by hand, often uncovering subtle corner cases that wouldn't be found otherwise. <a href="http://book.realworldhaskell.org/read/testing-and-quality-assurance.html">[2]</a></p>
</blockquote>
<h2>
<a name="getting-started" class="anchor" href="#getting-started">Getting Started</a></h2>
<p>Install the module from <a href="https://www.npmjs.org/package/jsverify">npm registry</a> with: <code>npm install jsverify</code></p>
<p>Clone the source from <a href="https://github.com/jsverify/jsverify">GitHub</a> and contribute!</p>
<h2><a name="examples" class="anchor" href="#examples">Examples</a></h2>
<h3><a name="bool-thrice" class="anchor" href="#bool-thrice">Boolean to Boolean function applied thrice</a></h3>
<p>This example is taken from older revision of <a href="http://www.cis.upenn.edu/~bcpierce/sf/current/index.html">Software Foundations book</a>.
We could prove the proposition by hand, as there are only four distinct <em>bool → bool</em> functions. Or we can let <em>JSVerify</em> generate inputs for us.
<p>
<pre><code class="javascript"><span class="comment">// forall (f: bool -> bool, b: bool), f (f (f b)) ≡ f(b).</span>
var boolFnAppliedThrice =
jsc.forall(<span class="literal">"bool -> bool"</span>, <span class="literal">"bool"</span>, function (<span class="variable">f</span>, <span class="variable">b</span>) {
return <span class="variable">f</span>(<span class="variable">f</span>(<span class="variable">f</span><span class="variable">(b)</span>)) === <span class="variable">f</span><span class="variable">(b)</span>;
});
jsc.assert(boolFnAppliedThrice);
<span class="comment">// OK, passed 100 tests</span></code></pre>
<h3><a name="sort-idempotent" class="anchor" href="#sort-idempotent">Sort is idempotent</a></h3>
<p>A unary operation (or function) is idempotent if, whenever it is applied twice to any value, it gives the same result as if it were applied once; i.e., <em>ƒ(ƒ(x)) ≡ ƒ(x)</em>. For example, sort: <em>sort(sort(x)) ≡ sort(x)</em>.</p>
<pre><code class="javascript"><span class="comment">// forall (f: string -> nat, arr: array string),</span>
<span class="comment">sortBy(sortBy(arr, f), f) ≡ sortBy(arr, f).</span>
var sortIdempotent =
jsc.forall(<span class="literal">"string -> nat"</span>, <span class="literal">"array string"</span>, function (<span class="variable">f</span>, <span class="variable">arr</span>) {
return _.isEqual(_.sortBy(_.sortBy(<span class="variable">arr</span>, <span class="variable">f</span>), <span class="variable">f</span>), _.sortBy(<span class="variable">arr</span>, <span class="variable">f</span>));
});
jsc.assert(sortIdempotent);
<span class="comment">// OK, passed 100 tests</span></code></pre>
<h3><a name="promise-example" class="anchor" href="#promise-example">Promises</a></h3>
<p>We could test asynchronous methods with <em>JSVerify</em> too. Just return a <em>Promise</em> from a property function.</p>
<pre><code class="javascript">function delay(<span class="variable">timeout</span>, <span class="variable">f</span>) {
var <span class="variable">complete</span>;
var <span class="variable">p</span> = new Promise(function (<span class="variable">c</span>, <span class="variable">r</span>) {
<span class="variable">complete</span> = <span class="variable">c</span>;
});
setTimeout(function () {
<span class="variable">complete</span>(<span class="variable">f</span>());
}, <span class="variable">timeout</span>);
return <span class="variable">p</span>;
}
var noEffectOnPureComputations =
jsc.forall(<span class="literal">"json -> json"</span>, <span class="literal">"json"</span>, jsc.nat(<span class="literal">100</span>), function (<span class="variable">f</span>, <span class="variable">x</span>, <span class="variable">t</span>) {
var <span class="variable">sync</span> = <span class="variable">f</span>(<span class="variable">x</span>);
return delay(<span class="variable">t</span>, function () {
return <span class="variable">f</span>(<span class="variable">x</span>);
})
.then(function (<span class="variable">async</span>) {
return _.isEqual(<span class="variable">sync</span>, <span class="variable">async</span>);
});
});
jsc.check(noEffectOnPureComputations);
<span class="comment">// OK, passed 100 tests</span></code></pre>
<h3><a name="minimal-counterexamle" class="anchor" href="#minimal-counterexample">Minimal counterexamples</a></h3>
<p>In case property doesn't hold, <em>JSVerify</em> tries to find the smallest possible counterexample.</p>
<pre><code>var wrongTakeProp =
jsc.forall(<span class="literal">"array nat"</span>, <span class="literal">"nat"</span>, function (<span class="variable">arr</span>, <span class="variable">n</span>) {
return _.take(<span class="variable">arr</span>, <span class="variable">n</span>).length === <span class="variable">n</span>;
});
jsc.check(wrongTakeProp);
<span class="comment">//Failed after 2 tests and 6 shrinks. rngState: ...;</span>
<span class="comment">// Counterexample: []; 1; [ [], 1 ]</span></code></pre>
<p>Here the problem was in the property specification:</p>
<pre><code>var correctTakeProp =
jsc.forall(<span class="literal">"array nat"</span>, <span class="literal">"nat"</span>, function (<span class="variable">arr</span>, <span class="variable">n</span>) {
return _.take(<span class="variable">arr</span>, <span class="variable">n</span>).length <= <span class="variable">n</span>; <span class="comment">// Less than or equal to!</span>
});
jsc.check(correctTakeProp);
<span class="comment">// OK, passed 100 tests</span></code></pre>
<h2><a name="documentation" class="anchor" href="#documentation">Documentation</a></h2>
<p>Check <a href="https://github.com/jsverify/jsverify#documentation">the README on GitHub</a> for API and usage documentation.</p>
</section>
<footer>
<p>This project is maintained by <a href="https://github.com/phadej">phadej</a></p>
<p><small>Hosted on GitHub Pages</small></p>
</footer>
<script src="javascripts/scale.fix.js"></script>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-4812655-7");
pageTracker._trackPageview();
} catch(err) {}
</script>
</body>
<s/html>