Why is that? Is it a cultural thing, or is Haskell's strict type system and immutability so helpful that unit tests are not so necessary comparing to for instance Java?
Why is that? Is it a cultural thing, or is Haskell's strict type system and immutability so helpful that unit tests are not so necessary comparing to for instance Java?
HUnit, directly based on JUnit: http://hackage.haskell.org/package/HUnit
Quickcheck, which uses randomized testing: http://hackage.haskell.org/package/QuickCheck
HUnit will be very familiar to you, Quickcheck is definitely more interesting. You specify some invariants and the heuristic algorithm tries to come up with random inputs to break your function. It's potentially less accurate as good unit tests, but it's also a ton less work.
I can just say something like "This function takes an array of integers as input, and I expect an output array of the same size, where all numbers are even, and there are no duplicates" (in math-y form, of course), and quickcheck will try however man random inputs I specify to try to find a case that breaks that invariant.
Consider a well known Haskell library, attoparsec. It has extensive tests and benchmarks: https://github.com/bos/attoparsec
That being said, there are those in the Haskell community who take Haskell's referential transparency and equational reasoning to a whole new level and don't write tests, but instead write proofs.
For an example, see the popular Pipes library: https://github.com/Gabriel439/Haskell-Pipes-Library/blob/mas...
That said, I do feel that the type of testing I do in Haskell is often quite different from other languages. Due to the strict type system, some types of errors can be eliminated at compile time, and thus do not need to be tested for. Of course, as the parent pointed out, some people take this to a (very awesome) extreme, but even in a less rigorous form the static guarantees can eliminate many things that I would write unit tests for in other languages.
Finally, you may also be interested in SmallCheck, an alternative to QuickCheck. From its documentation:
> The big difference [between SmallCheck and QuickCheck] is that instead of using a sample of randomly generated values, SmallCheck tests properties for all the finitely many values up to some depth, progressively increasing the depth used. For data values, depth means depth of construction. For functional values, it is a measure combining the depth to which arguments may be evaluated and the depth of possible results.
This means that SmallCheck will often find small and interesting counterexamples to the properties you wish to affirm. (As an aside, note that writing property-based tests is a skill, just like writing good unit tests.)
tl;dr: Testing can sometimes be less necessary, but is certainly not unnecessary, and there are some very high quality and well-documented libraries for testing in Haskell.
gamegoblin is absolutely correct that there is some great tooling for tests in Haskell.
Bigger and longer-lived projects benefit enormously from an automated test suite no matter what they're written in.
That said, when you refactor a program in Haskell, instead of running the tests and some functionality falling, usually the compiler itself will tell you there's a problem at line X of file Y.
That use case of tests is just not there - and that's the main selling point of unit tests. Thus, I'd expect Haskell developers to not write as much of this kind of tests. But again, you'll always need some kind of it.