[Haskell-cafe] Testing a collision detection system
Joachim Durchholz
jo at durchholz.org
Mon Jul 30 06:19:04 UTC 2018
> So the idea is to use an existing collision detection library to
> generate (a lot of) test cases from random data.
I think that won't solve your problem. You wouldn't test that your
collision library works, you'd test that your collision library is
bug-for-bug-compatible with whatever other collision library you're
using as your gold standard.
You'd probably be better off by writing a small collision detector that
uses just the raw data. Optimized not for speed but for easy inspectability.
Then apply that algorithm to the test cases.
If the objects are pixels, AND the bitmaps and check whether the result
has 1 bits or not.
If the objects are vector art, apply a collision algorithm; I dimly
recall there was a really simple and easy-to-validate one in one of
Robert Sedgewick's "Algorithms" books.
To generate the test cases, that's easier for vector than for bitmap -
you have sets of points and can move/rotate the two shapes so that you
get each permutation of line endpoints.
Depending on the complexity of your shapes, this may or may not be feasible.
You can compute the convex hull (again, pretty easy if you go by
Sedgewick) and check that if convex hulls don't intersect, your
algorithm does not intersect; that's going to cut down on test cases
that you don't need to check.
Yet another approach to test case writing: Look at each decision point
in the intersection algorithm, then take a step back and find out what
that means, geometrically, and write (or generate) test cases for both
branches. IOW generate your test cases towards 100% coverage.
QuickCheck may help, too.
If you find it does not detect relevant test cases, consider
restructuring your code so that the decisionmaking is simplified, and/or
separated out from the nitty-gritty details of actual checking. Maybe
separate it out into a "strategy layer" and an "execution layer", where
strategy decides how to test and execution does the actual test (I can't
be clearer because I don't know the kind of shapes you are testing).
The goal would be to separate the logic, because that's going to
simplify testing tremendously. It may even make the code so
understandable that you don't even need to write tests, because the code
is self-evident - well, that's probably just an ideal that you can come
nearer but never fully achieve, but it's a guideline to consider
whenever you make decisions about how you structure your code.
Refactoring in this way may amount to a full rewrite. If may also reduce
your testing effort; it's difficult to assess whether it's going to be a
net win.
Regards,
Jo
More information about the Haskell-Cafe
mailing list