Comment by bern4444

3 years ago

> Tests live in their own directory and are written against the public interface, or, when testing private implementations, against a For_testing module exported just for that purpose.

That is a nice and unique idea. I dislike exposing code just to make it testable, but exposing something under an explicit name is a great compromise.

Having a test runner with a `watch` mode is extremely helpful, as is a runner that will output expected vs actual diffs when a test fails, or provide contextual information about why a test failed.

The premise of initial test in the article - testing a fibonacci function - is also slightly at odds with a better property based testing approach. Validating a function works for a specific input isn't so helpful. We want to validate it works for any number of input!

I'd use the actual definition as a property based test and fuzz over the value:

    const n = generateRandomIntegerBetween(0, 100);
    expect(fib(n) + fib(n+1)).toEqual(fib(n+2))

I also like having precondition and postcondition assertions in my tests.

One example of this is validating the argument generated to pass to the function under test has the correct structure and state before its passed into the function under test.

We can also validate that after the function under test has completed, the argument it received wasn't mutated in any way.