单元测试:模块重新导出可以避免必须“暴露”所有可测试模块

时间:2015-11-09 23:19:35

标签: haskell

TLDR:是否可以使用模块重新导出以避免“暴露”所有可测试模块?

我在Haskell项目中使用了类似于Chris Done模板的东西。我的ventureforth.cabal文件包含以下部分:

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

我的代码是

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

我已将VForth.hs设置为重新导出VForth.Location

module VForth (
    module VForth.Location
) where

import VForth.Location

VForth.LocationSpec单元测试中,我只需要import VForth来测试Location类型。

但是,除非我在“暴露模块”列表中添加VForth.Location,否则在尝试运行cabal test时会遇到链接器错误。

我曾想过暴露一个模块VForth,它重新导出所有其他模块,就足够了。我是否真的陷入了必须列出cabal中每个源文件的情况?

1 个答案:

答案 0 :(得分:2)

所以最后这是不可避免的。然而,经过反思,这也是一种很好的行为。由于我正在创建一个库,并且Haskell语言无法控制模块可见性,因此我必须指定要在Cabal中导出哪些模块。

为了充当测试,我的测试不应该对我的库客户端所做的应用程序有任何额外的访问权限。因此,我的测试无法访问我的库的客户端也无法访问的任何模块是可以接受的。

然而,在实践中,我想要测试一些未公开的内部元素。因此,我将测试套件拆分为两个,一个是内部测试套件,另一个是外部测试套件,用于测试这些不同的方面。

 <component class="com.foo.CustomJavaComponent" doc:name="Java"/>

内部测试可以直接访问源代码,因此不会导入库。

最后作为“内部”测试的第二个来源,我也使用doctests,如Haskeleton project setup guide

中所述

最后,对于构建Haskell项目的任何其他人,请注意您可以使用Haskell Init tool在同名目录中创建名为public class CustomJavaComponent implements Callable{ @Override public Object onCall(MuleEventContext eventContext) throws Exception { MuleMessage muleMessage = eventContext.getMessage(); FileInputStream fis = (FileInputStream)muleMessage.getPayload(); //Do something with this stream return "Hello world"; } } 的骨架项目,其中包含所有测试位和bobs集准备好了

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

存储库标志提供模板项目的路径。 Haskeleton模板具有单元测试,文档测试和基准测试。其他项目tempaltes,例如web-apps,可以在HI templates page上找到。要安装Haskell Init工具,只需键入

即可
my-project-name