Alternative doctest implementation that extracts comments to modules

root

Known Issues

  • For compatibility with original doctest parser you cannot write

    {-# LANGUAGE MyPreferredExtension #-}

    Instead you must write

    :set -XMyPreferredExtension
  • In Literal Haskell files only \\begin{code} ... \\end{code} blocks are scanned, but not bird style code blocks.

  • prop> supports multi-line code, but both original doctest and haddock do not support it.

  • IO tests are not supported as doctest examples, so far. We need a syntactic distinction for IO tests, because doctest-extract does not employ a type-checker. We could mark IO tests with a specific id function, as in ioTest $ runMyTest or a type annotation, as in runMyTest :: IO ().

Tipps and Tricks

Interaction with editor

You may extract your doctests using the --verbose option. This emits the tested expression before each test and it formats the source location in a way that is recognized by Emacs et.al. , i.e. you can click on the source location and thus jump to the according doctest.

Synchronize test module list between Cabal and doctest-extract

We recommend maintaining the list of test modules with unique name prefixes in the Cabal package description and extract this list using grep.

E.g.:

  Other-Modules:
    DocTest.MyProject.ABC
    DocTest.MyProject.DEF
    DocTest.MyProject.GHJ

Your grep expression should only accept lines that start with spaces exclusively. This way, modules are skipped if they are outcommented in the Cabal file.

How to disable selected tests?

For focussing on certain tests it can be useful to disable other ones. We have not implemented a mechanism to disable parts of the test suite in doctest-extract, because this would require to implement a way to identify tests. You can still disable some of the tests without explicit support by doctest-extract.

  • If you want to disable whole modules, you may make a copy of the auto-generated Test/Main.hs and remove the modules that you want to skip. If you grep the module list from the Cabal package description, then outcomment the according modules there.

  • For disabling all tests on a function you may turn a Haddock comment into a plain comment by removing the bar after the opening of the comment.

  • For disabling individual tests you may prefix >>> and prop> with an asterisk or the like.

These tricks work best in conjunction with a revision control systen, such that it always reminds you that there are tests disabled temporarily.

Sharing in properties

If you have a doctest property like ~~ prop> let x = ... in -> p x y ~~ then x will be re-evaluated for every of the 100 randomized QuickCheck tests. If you want to precompute a value once and re-use it in all QuickCheck runs, you may abuse QuickCheck.forAllBlind like so: ~~ prop> forAllBlind (return ...) $ y -> p x y ~~

Tests in the IO monad

As said above, tests in the IO monad are currently not directly supported. However, for properties you may use QuickCheck.ioProperty or QuickCheck.idempotentIOProperty. For Doctest examples you may roll your own unsafePerformIO hacks. Maybe we officially provide some in the future by ourselves.