Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to test or describe endless possibilities?

Example class in pseudocode:

class SumCalculator
  method calculate(int1, int2) returns int

What is a good way to test this? In other words how should I describe the behavior I need?

test1: canDetermineSumOfTwoIntegers

or

test2: returnsSumOfTwoIntegers

or

test3: knowsFivePlusThreeIsEight

Test1 and Test2 seem vague and it would need to test a specific calculation, so it doesn't really describe what is being tested. Yet test3 is very limited.

What is a good way to test such classes?

like image 922
koen Avatar asked Mar 06 '10 15:03

koen


4 Answers

I would test the boundary conditions (max-int, min-int, zero, positive, negative) and some typical cases:

test1: sumOfPosAndPos
test2: sumOfPosAndNeg
test3: sumOfPosAndZero
test4: sumOfNegAndZero
test5: sumOfMaxIntAndMinInt

etc.

like image 186
Bruno Rijsman Avatar answered Nov 11 '22 00:11

Bruno Rijsman


There are several philosophies. Roy Osherove, author of The Art of Unit Testing, seems to prefer using explicit values, and selecting the lowest (or simplest) representation of each Equivalence Class.

That principle doesn't apply itself particularly well to your example, but works really well in many other scenarios.

If, for example, a class requires an input of a positive integer, you pick the number 1 because it's the simplest representation of all positive intergers.

Personally, I rather prefer a principle I call Constrained Non-Determinism. The point here is that we let some kind of factory serve us anonymous variables for the given type, because it forces us to establish the relationship directly in the test.

I'm using AutoFixture to do this (but you could also use something else), so in this case I would test the SumCalculator like this:

var fixture = new Fixture();
var int1 = fixture.CreateAnonymous<int>();
var int2 = fixture.CreateAnonymous<int>();
var expectedResult = int1 + int2;
var sut = fixture.CreateAnonymous<SumCalculator>();

var result = sut.Calculate(int1, int2);

Assert.AreEqual(expectedResult, result);

In principle, this single test provides a specification for the Calculate method. We never know what the values of int1 and int2 are, and that is very appropriate in all those many cases where it actually doesn't matter.

like image 34
Mark Seemann Avatar answered Nov 10 '22 23:11

Mark Seemann


if you're testing mathematical function, i would suggest you should test it against its inverse function, for example: for function that do x = a + b, you should test it whether a-x = -b and x-b = a, this is just for illustration, ofcourse it won't work on every case.

like image 3
uray Avatar answered Nov 11 '22 00:11

uray


Another alternative here would be to used a Parameterized Test Case to remove the duplication in the tests. Basically a table contains all the data for the tests, in a tuple form ([term1, term2, sum]), then a testcase iterates on the table on invoke the parameterized testcase to test a row in the table :

I would also add negative (overflow here) testing : what is calculate(MAXINT, 1) supposed to return ?

like image 1
philant Avatar answered Nov 10 '22 23:11

philant