Comment by drothlis
3 years ago
I'm not the OP but I think Fibonacci is a contrived example. In practice these "characterisation tests" are great for adding tests to an existing codebase. The "snapshot" just records the current behaviour; it doesn't judge whether it's correct or not, but if you refactor it will catch changes to the behaviour, and then it's up to a human to judge if the changes were desirable or not.
Fibo would be excellent for property testing.
I.e. For all x, Fib(x+2)=Fib(x)+Fib(x+1)
A property based test produces values of x and tests this property (or invariant).
If it fails the framework usually then tries to find the simplest failing case.
I am always slightly uncomfortable about property based tests that just replicate the logic of the thing they're testing. I don't really know of an alternative in this case, and obviously there's rarely any harm in having regression tests. But it feels like a code smell somehow.
I suppose they're ideal for cases where there's a simple, obviously correct but slow implementation that you can use to test a more complex but faster implementation.
Your uneasiness is understandable, but often it is far simpler to check the correctness of a result than to find it in the first place. Then property-based testing really shines.
Even outside that special case it is always possible to generate just some input data and check for the absence of runtime errors or exceptions. That approach can be improved by adding assertions, pre- and postconditions to your code under test.
Additionally, there a different ways to come up with good properties, see: https://www.youtube.com/watch?v=zvRAyq5wj38
You say it replicates the logic, but I think it's more useful to say that it describes the meaning: fib is the function on natural numbers that has that property plus the base cases fib(0) = 1 and fib(1) = 1. That's what fib means.
That said, there are plenty of cases where your reaction is justified, where the test is implemented the same way as the function it's testing when the correctness property could be specified more simply.
You can chuck some regular tests in at the same time. They attack different classes of bugs.
Property based tests fuzz test values you may not have dreamed of. Given a string as the required type it could generate some exotic stuff.
Fib(x)=0 does satisfy this property though.
A full definition would include Fib(0) = 0, Fib(1) = 1 or if you prefer 1, 1.
You need to manually check the first 2 values in a seperate test.
P.S. They're also great for writing tests for new code, for many of the reasons described in the OP.