Hacker News new | ask | show | jobs
by dantiberian 3960 days ago
To take this another step further, you can look at generative, or property based testing. You specify properties of your input data, e.g. A sequence of 0 or more Unicode characters, and the properties that should hold, e.g. It never crashes, the length stays the same after processing, e.t.c. Then the generator will generate ever more complicated test cases to try to break the invariants, if it does then it will backtrack to find the smallest failing test case.

I find generative tests take a lot longer to think about and write, but are invaluable for flushing out all the corner cases. There are libraries for lots of languages, Haskell, Clojure, Python, Erlang, and others too I'm sure.

2 comments

This is a good starting point to find such tools:

"QuickCheck is a combinator library originally written in Haskell, designed to assist in software testing by generating test cases for test suites. It is compatible with the GHC compiler and the Hugs interpreter.

In QuickCheck the programmer writes assertions about logical properties that a function should fulfill. Then QuickCheck attempts to generate test cases that falsify these assertions. The project was started in 1999. Besides being used to test regular programs, QuickCheck is also useful for building up a functional specification, for documenting what functions should be doing, and for testing compiler implementations.[1]

Re-implementations of QuickCheck exist for C,[2][3] C++,[4][5][6] Chicken Scheme,[7] Clojure,[8][9][10] Common Lisp,[11] D,[12] Elm, [13] Erlang, F#,[14] Factor,[15] Io,[16] Java,[17][18][19] JavaScript,[20] Node.js,[21] Objective-C,[22] OCaml,[23] Perl,[24] Prolog,[25][26] Python,[27] R,[28] Ruby,[29] Rust,[30] Scala,[31] Scheme,[32] Smalltalk,[33] Standard ML[34] and Swift.[35]"

https://en.wikipedia.org/wiki/QuickCheck

Fuzzing is also cool, or lifting test cases from other implementations, chances are corner cases for those are also corner cases for yours.