Hacker News new | ask | show | jobs
by hitchstory 515 days ago
Id say if you think tests and types are doing the same thing in the same way you are badly abusing at least one of them.

One attacks the problem of bugs from the bottom up and the other from the top down. They both have diminishing returns on investment the closer they get to overlapping on covering the same types of bug.

The haskell bros who think tests dont do anything useful because "a good type system covers all bugs" themselves havent really delivered anything useful.

2 comments

> The haskell bros who think tests dont do anything useful because "a good type system covers all bugs" themselves havent really delivered anything useful.

Please don't do this. It's not constructive.

I'm a Haskell bro and I love testing. You misunderstand me, though. All I say is that maybe _some_ of those tests deliver value by just making sure that code even runs, which is otherwise covered by types.
When I do TDD (virtually every time i write a line of code) each test scenario isnt just a way to verify that the code is working, it's also a specification - often for a previously unconsidered edge case.

Throwing away the test means throwing away that user story and the value that comes with it.

I believe you (other than tests being specifications, they are examples at best). But that doesn't change the fact that TDD looks more adopted in untyped languages, and that deserves an explanation.

Mine is that a lot of potential errors (typos, type mismatches) don't need to be exercised by running code in typed language.

Yours is... well, you don't really address it.

>I believe you other than tests being specifications

If you're not, that suggests you're not doing them right which in turn suggests why you might have an issue with them...

How would you make a test a specification?

I suppose you could do something like, enumerate every possible combination of inputs and check that some property holds for all of them. Or, maybe you could instead randomly select a number of combinations of inputs and check that a property holds for each of those random combinations, but that wouldn't be guaranteed to find the inputs for which the specification isn't satisfied.

I guess maybe if the test passed to the function to be tested, mock values, such that the function is effectively evaluated symbolically (where any branching that depends on the inputs to the function, would maybe have the mocked object specify what the result of the conditional should be, with different tests for different cases?) ?

Or.. Can you explain how you write tests such that they truly function as specifications?

Good question - and there's been lots of work on this area. See for example property testing and fuzz testing, which can do something similar to what your second paragraph suggests.

You should be able to find a property testing library in your favourite language such as Hypothesis (python), Quickcheck (Haskell), Fastcheck (JS/typescript), etc.

Jane logs in, enters her DOB which is 11/5/1998, does Y the result of which is Z.

Where X, Y and Z are very specific.

These example scenarios work well as a communication medium for discussing intended program behavior as well as translating well into tests.

>enumerate every possible combination

Whereas if you start doing this you will probably confuse your stakeholders.

Specific examples tend to make better specifications.

That’s exactly what those tests are for. When you no longer have to worry if you invoked .foo() or .fooTypo(), you eliminated one class of bug. Namely trying to run things that do not exist.

Maybe you meant to invoke .bar(), but at least we know thanks to type checks that the target exists.