我应该如何去测试一个单一的可执行包?

How should I go about testing a monolithic executable package?

我有一个包含多个模块的整体 executable 包。 (我说的"monolithic"的意思是它的cabal文件里只有一个子句,也就是executable。)目前正在测试中使用 shell 脚本,以黑盒方式。我以为我想为一些个别功能写单元测试,但是cabal不同意:

% cabal new-test
cabal: Cannot test the package x-0.0.0.0 because none of the
components are available to build: the test suite 'x-test' is not
available because the solver did not find a plan that included the test suites

以下是package.cabal的相关部分:

executable x
  ...
  other-modules: ...
  ...

test-suite x-test
    type: exitcode-stdio-1.0
    main-is: Test.hs
    build-depends: base, x
    hs-source-dirs: test

我的理解是,我应该将尽可能多的模块移动到一个内部库中,这将使测试套件可以依赖它们。然而,我不确定维护者是否会赞成这种彻底的改变。有没有侵入性更小的方法?

我的另一个担忧是,就 Main.hsexecutable x 子句中而言,我们无法将其导入 x-test,其中的函数(至少 main) 将无法用于测试。那么除了 shell 脚本之外,我应该如何测试这些功能?

完全可以将模块移至 library 节(如果您不想公开这些模块,则移至内部库节)。

How should I go about testing it, beside shell scripts?

在 Haskell 世界中有一种常见的做法是将所有内容(甚至 main 函数)移动到 library 中,因此您的 Main.hs 看起来像这样:

module Main where

import MyLib as Lib (main)

main :: IO ()
main = Lib.main

使用这种方法,您可以通过 Haskell 单元测试库完全测试所有内容。

However, I am not sure the maintainers will approve of such radical change. Is there a less invasive way?

好吧,如果维护者关心他们的包,如果他们想要更好的测试,他们应该同意这种重构。

如果将包移动到(可能是内部的)库不是一个选项,您可以简单地将可执行文件的所有源添加到测试套件的 hs-source-dirs,并添加依赖项可执行到测试套件的 build-depends

这样做的缺点是您将编译相同的文件两次:一次用于可执行文件,一次用于测试套件。