# Unit testing not as straightforward as expected

**URL:** <https://discourse.haskell.org/t/unit-testing-not-as-straightforward-as-expected/3921>\
**Category:** Learn\
**Created:** [January 14, 2022, 2:59pm UTC](https://discourse.haskell.org/t/unit-testing-not-as-straightforward-as-expected/3921 "2022-01-14T14:59:15Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![rubenmoor](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/rubenmoor/32/2075_2.png) [@rubenmoor](https://discourse.haskell.org/u/rubenmoor)\
**Post date:** [January 14, 2022, 2:59pm UTC](https://discourse.haskell.org/t/unit-testing-not-as-straightforward-as-expected/3921/1 "2022-01-14T14:59:15Z")

</div>

I needed some quick unit testing for a library, to rule out a run-time error. In the end, it wasn’t that complicated, but the “straightforward” way of implmenting unit testing with haskell/cabal isn’t as straightforward as it could be.

I ended up implementing this guy’s solution ([stackoverflow.com](http://stackoverflow.com), 8 years ago):

> <https://stackoverflow.com/questions/20331209/haskell-unit-testing/20331512#20331512>

… which is a combination of

`test-framework`, `HUnit`, `test-framework-hunit`

with cabal Test Suite `exitcode-stdio-1.0`.

It does exactly what I needed, only the following things felt a bit awkard:

- What is this alternative cabal test suite `detailed-0.9`? [Documentation](https://cabal.readthedocs.io/en/latest/cabal-package.html?highlight=detailed#example-package-using-detailed-0-9-interface) is slim. When should I use one over the other?
- Those three libraries are fine, I guess, but given the basic nature of the task: Why isn’t it just one thing? I tried working with `HUnit` alone, BUT `exitcode-stdio-1.0` requires working with exit codes that I have to put in place manually … thus I prefer the `defaultMain` from `test-framework`.

* * *

I certainly don’t mean to complain. Maybe there is a more straightforward way of implementing unit testing that I overlooked.

If, however, this is how it’s done, I hope this posts contributes to the documentation of the topic.

---

<div class="post-metadata">

**Author:** ![f-a](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/f-a/32/2740_2.png) [@f-a](https://discourse.haskell.org/u/f-a)\
**Post date:** [January 14, 2022, 3:25pm UTC](https://discourse.haskell.org/t/unit-testing-not-as-straightforward-as-expected/3921/2 "2022-01-14T15:25:29Z")

</div>

Nowadays [`hspec`](https://hackage.haskell.org/package/hspec) is a popular testing framework, with [nice introductory material](http://hspec.github.io/).

It borrows from `rspec` and seems for sure a better experience than what suggested in that stackoverflow answer. If `hspec` if fit for your purposes, I suggest giving it a go!

---

<div class="post-metadata">

**Author:** ![jaror](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/jaror/32/3271_2.png) [@jaror](https://discourse.haskell.org/u/jaror)\
**Post date:** [January 14, 2022, 3:32pm UTC](https://discourse.haskell.org/t/unit-testing-not-as-straightforward-as-expected/3921/3 "2022-01-14T15:32:41Z")

</div>

> [@rubenmoor](#):
>
> What is this alternative cabal test suite `detailed-0.9`? [Documentation](https://cabal.readthedocs.io/en/latest/cabal-package.html?highlight=detailed#example-package-using-detailed-0-9-interface) is slim. When should I use one over the other?

I believe exitcode-stdio is the standard way to test and the other ways are not really used anymore.

> [@rubenmoor](#):
>
> I tried working with `HUnit` alone, BUT `exitcode-stdio-1.0` requires working with exit codes that I have to put in place manually …

I didn’t run into issues with using HUnit directly with this code:

```haskell
module Main where

import Test.HUnit

foo :: Int -> (Int, Int)
foo 3 = (1, 2)
foo _ = (0, 0)

partA :: Int -> IO (Int, Int)
partA _ = pure (5, 2) -- change to (5,3) if you want the tests to succeed

partB :: Int -> IO Bool
partB x = pure (x == 3) 

test1, test2 :: Test
test1 = TestCase $ assertEqual "for (foo 3)," (1, 2) (foo 3)
test2 = TestCase $ do
  (x, y) <- partA 3
  assertEqual "for the first result of partA," 5 x
  b <- partB y
  assertBool ("(partB " ++ show y ++ ") failed") b

main :: IO ()
main = runTestTTAndExit (TestList [TestLabel "test1" test1, TestLabel "test2" test2])

```

---

<div class="post-metadata">

**Author:** ![rubenmoor](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/rubenmoor/32/2075_2.png) [@rubenmoor](https://discourse.haskell.org/u/rubenmoor)\
**Post date:** [January 14, 2022, 3:43pm UTC](https://discourse.haskell.org/t/unit-testing-not-as-straightforward-as-expected/3921/4 "2022-01-14T15:43:25Z")

</div>

nice, the `runTestTTAndExit` is all I need for straightforwardness

---

<div class="post-metadata">

**Author:** ![ketzacoatl](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ketzacoatl/32/1203_2.png) [@ketzacoatl](https://discourse.haskell.org/u/ketzacoatl)\
**Post date:** [January 15, 2022, 4:08pm UTC](https://discourse.haskell.org/t/unit-testing-not-as-straightforward-as-expected/3921/5 "2022-01-15T16:08:30Z")

</div>

[CS SYD - Blog](https://cs-syd.eu/blog) has a few posts on testing in general and with haskell, you might find those useful. I’d also recommend at least reviewing what [GitHub - NorfairKing/sydtest: A modern testing framework for Haskell with good defaults and advanced testing features.](https://github.com/NorfairKing/sydtest) can do and if that would be useful for your projects.
