3. Hoare: “ The role of testing, in theory, is to
establish the base propositions of an
inductive proof.[...] At present, this is mainly
theory [but] seems to show a possibility of
practical results, though proving correctness
is a laborious and expensive process.”
Perlis: “ Much of program complexity is
spurious and a number of test cases
properly studied will exhaust the testing
problem. The problem is to isolate the right
test cases, not to prove the algorithm, for
that follows after the choice of the proper
test cases.”
Diijkstra: “Testing shows the presence, not
the absence of bugs”
4. Testing with examples
specify correct output for chosen inputs
relatively easy to come up with
good communication tool
straightforward to implement
straightforward to overlook important ones
usually only cover a very small portion of your domain
6. Problem
-- ECMAScript® Language Specification
“The Number type has exactly
18437736874454810627
(that is, 264−253+3) values”
-- me
“The box above has 90000 pixels”
7. remember when you started learning TDD?
Math.abs=function(x){
if(x===0)return0;
if(x===-1||x===1)return1;
if((x>1&&x<2)||(x>-2&&x<-1))return1.23;
return5;
}
8. Testing with properties
not to be confused with properties on JavaScript objects
specify a property that holds for all / specified inputs
instead of finding a proof, test random inputs
similar to contracts
examples use jsverify, other implementations available
9. Describing a property
Humans: “whatever number we pass to abs, it should return
a number greater or equal than 0.”
Mathematicians: ∀ x ∈ ℝ: abs(x) ≥ 0
Programmers:
varp=require('jsverify');
p.check(p.forall(p.number(),function(x){
varactual=Math.abs(x);
returntypeofactual==='number'&&actual>=0;
}));
OK,passed100tests
17. Common use cases
f(x)>=y //assertingthefunction'srange
f(x)===f(f(x));//idempotence
a(x)===b(x);//regressiontestforreimplementation
newC1().f(x)===newC2().f(x);//closelyrelated
newC(c1).f(x)===newC(c2).f(x);//closelyrelated
max(a,b)===max(b,a));//commutativity
zoom(zoom(img,n),-n)===img);//invertibility
18. Bonus crazieness
What about higher-order functions?
“If we are to check properties involving
function valued variables, then we must be
able to generate arbitrary functions. Rather
surprisingly, we are able to do so.”
p.assert(p.forall(p.array(),p.fn(),p.value(),function(a,f,c){
return_.map(a,f,c).length===a.length;
}));
19. Conclusion
finding good properties makes you think harder
very functional style, but should work on testing OO code
not a replacement for TDD using examples
but can be used to help finding missed edge cases
best for unit testing (because of high number of test cases)
also good for verifying assumptions on 3dparty code