1) Claire is a JavaScript library that helps test invariants using property-based testing, generating random data to test properties rather than specific test cases.
2) Properties to test include things like addition being commutative for all inputs, rather than testing specific cases.
3) The strategy involves defining data generators, identifying properties to test, writing the properties as Claire tests, and running the tests on generated data to find failures.
2. Property Based Testing
You may have heard of this from libraries such as
QuickCheck and ScalaCheck
Claire is a library by Quildreen Motta that helps you test
invariants in your javascript
3. Invariants!
We are used to writing tests like this:
eπi = -1
We should start writing tests like this:
∀x. exi = cos(x) + i sin(x)
4. Invariants!
An old idea in computer science
Preconditions and Postconditions
Loop Invariants
Usually expressed in a functional language
5. The Strategy
1. Define generators
2. Identify invariants
3. Convert to Claire property
4. Test property on generated data
5. ...
6. No more bugs!
6. Generators, Properties,
Tests
var claire = require('claire')
var _ = claire.data
//two generators, Int and Num
var commutativity = claire.forAll(_.Int, _.Num)
.satisfy(function(integer, real){ //the property being tested
return integer+real === real+integer
}).asTest() //returns a function
//use it in mocha
describe('addition', function(){
it('is commutative', commutativity)
})
//or invoke it to see the results
commutativity() //passes silently
7. Diagnosing Properties
var sorted_p = forAll( _.Array(_.Int) )
.satisfy(function(xs) {
xs = sorted(xs)
return xs.every(function(a, i) {
return i == 0 || a >= xs[i - 1]
})
}).classify(function(xs) {
return xs.length == 0 || xs.length == 1? 'trivial' : '> 1'
}).asTest({verbose: true, times: 1000})()
// + OK passed 1000 tests.
// > Collected test data:
// o 98% - > 1
// o 2% - trivial
9. Generators from a more
complex example
function modelObjGen(className, attrGens) {
return claire.label(className)(function() {
var attr, attrs, gen;
attrs = {};
for (attr in attrGens) {
gen = attrGens[attr];
attrs[attr] = gen.next().value;
}
return new App.Models[className](attrs);
});
};
10. Generators from a more
complex example
var SpecialItem = classObjGen('SpecialItem', {
type: claire.choice('Feedback', 'ContactForm', 'Document'),
info: gens.resize(5, ObjectGen(Any))
});
var Video = classObjGen('Video', {
youTubeId: claire.frequency([1, Nothing], [9, Id])
});
var Item = claire.label('Item', claire.choice(SpecialItem, Video));
var Unit = classObjGen('Unit', {
items: gens.resize(6, ArrayGen(Item))
});
11. Properties of Addition and
Multiplication
associativity: (a+b)+c = a+(b+c)
commutativity: a+b = b+a
identity: a+0 = a
closure: ∀ a,b ∈ ℤ. (a+b) ∈ ℤ
Test with Int, Num, and BigInt
for both addition and multiplication
Which ones fail?
12. Properties of Addition and
Multiplication
Two failures:
Num fails associativity of multiplication
BigInt fails associativity of addition
The Point: Claire makes it easy to test boundary conditions
and find corner cases.
14. Container Type Generators
### -- Container data types -------------------------------
List = (...as) -> repeat (choice ...as)
Map = (...as) -> transform to-object, (
repeat (sequence Id, (choice ...as))
)
#### λ to-object
# :internal:
# Folds a list of pairs into an object.
#
# :: [String, a] -> { String -> a }
to-object = (as) -> as.reduce ((r, [k,v]) -> r <<< { "#k": v }), {}
15. For the FP geeks
Claire's generators are monads:
claire.transformacts as fmap
.thenmethod on generators acts as monadic bind
16. What's in the Future?
1. Shrinking of counterexamples.
2. Generators based on generic lazy linked lists
3. Asynchronous tests
17. Why is this important?
Automated teting is important.
XUnit testing automates test running.
Propery based testing automates test generation.
Shrinking will help automate the first step in debugging.
Your confidence grows each time you run your test suite.
Random data (often) finds corners better than I do.
18. Thanks
install:
npm install claire
github:
a talk on QuickCheck by John Hughes.
https://github.com/killdream/claire
Functional Programming: A Secret Weapon for Software
Testing