Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

haskell - Unit-Testing: Can module re-exports avoid having to "expose" all testable modules

TLDR: Is it possible to use module re-exports to avoid having "expose" all testable modules?

I've used something similar to the Chris Done template for my Haskell project. My ventureforth.cabal file has the following sections:

library
  hs-source-dirs:      src
  exposed-modules:     VForth,
                       VForth.Location
  build-depends:       base >= 4.7 && < 5
  ghc-options:         -Wall -Werror
  default-language:    Haskell2010

executable ventureforth
  hs-source-dirs:      app
  main-is:             Main.hs
  build-depends:       base >= 4.7 && < 5,
                       ventureforth -any
  ghc-options:         -Wall -Werror -threaded -rtsopts -with-rtsopts=-N
  default-language:    Haskell2010

test-suite ventureforth-test
  type:                exitcode-stdio-1.0
  hs-source-dirs:      test
  main-is:             Spec.hs
  build-depends:       base >= 4.7 && < 5,
                       ventureforth -any,
                       doctest >= 0.9 && < 0.11,
                       hspec -any
  ghc-options:         -Wall -Werror -threaded -rtsopts -with-rtsopts=-N
  default-language:    Haskell2010

My code is laid out as

ventureforth/
 |
 +- ventureforth.cabal
 +- app/
 |   |
 |   +- Main.hs
 |
 +- src/
 |   |
 |   +- VForth.hs
 |   +- VForth/
 |       |
 |       +- Location.hs
 |
 +- test/
 |   |
 |   +- Spec.hs
 |   +- VForth
 |       |
 |       +- LocationSpec.hs

I've set up VForth.hs to re-export VForth.Location

module VForth (
    module VForth.Location
) where

import VForth.Location

And in the VForth.LocationSpec unit-test I need only import VForth to test the Location type.

However unless I add add VForth.Location to the list of "exposed modules" I encounter linker errors when trying to run cabal test.

I had thought exposing a single module, VForth, which re-exported all other modules, would have sufficed. Am I really stuck in the situation of having to list every single source file in cabal?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

So in the end this is unavoidable. However, on reflection, it is also good behaviour. Since I'm creating a library, and the Haskell language can't control module visibility, I have to specify which modules are to be exported in Cabal.

In order to function as tests, my tests should not have any additional access to an application that my library client does. Therefore it's acceptable that my tests can't access any modules that are also inaccessible to clients of my library.

In practice however, there are some internal elements I will want to test which are not exposed. Therefore, I've split my test-suite in two, one internal, and the other external, which test these different aspects.

test-suite ventureforth-test-external
  type:                exitcode-stdio-1.0
  hs-source-dirs:      test
  main-is:             Spec.hs
  build-depends:       base >= 4.7 && < 5,
                       ventureforth -any,
                       hspec -any
  ghc-options:         -Wall -Werror -threaded -rtsopts -with-rtsopts=-N
  default-language:    Haskell2010

test-suite ventureforth-test-internal
  type:                exitcode-stdio-1.0
  hs-source-dirs:      test,src
  main-is:             Spec.hs
  build-depends:       base >= 4.7 && < 5,
                       hspec -any
  ghc-options:         -Wall -Werror -threaded -rtsopts -with-rtsopts=-N
  default-language:    Haskell2010

The internal test has access to the source-code directly, and so doesn't import the library.

Lastly as a second source of "internal" testing, I'm also using doctests, as described in the Haskeleton project setup guide

Finally, for anyone else structuring a Haskell project, note that you can use the Haskell Init tool to create a skeleton project called my-project-name in a directory of the same name with all the testing bits and bobs set up and ready to go

hi my-project-name 
    --repository git://github.com/tfausak/haskeleton.git 
    --package-name my-project-name 
    --module-name MyProjectName 
    --author Bryan Feeney 
    --email [email protected]

The repository flag gives a path to a template project. The Haskeleton template features unit-tests, documentation tests and benchmarks. Other project tempaltes, such as web-apps, can be found on the HI templates page. To install the Haskell Init tool, just type

cabal install hi

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...