【问题标题】:Automatically running unit tests in Haskell在 Haskell 中自动运行单元测试
【发布时间】:2026-02-19 15:30:01
【问题描述】:

有没有办法用我的构建命令运行我的测试套件?我能找到的只是我可以运行,例如cabal testcabal build 之后。我想要的是一种在运行时自动运行测试的方法,例如cabal build.

我想要一个解决方案,它可以为任何构建包的人自动执行此操作,而无需他们运行不同的脚本。一个类比是一个 java 构建脚本,其中默认构建目标在编译后运行单元测试。

【问题讨论】:

  • 使用stack,您可能会喜欢stack test
  • @Redu with Cabal 你可能会喜欢cabal test,就这个问题而言,Stack 和 Cabal 之间没有区别。
  • 您能解释一下为什么您想将运行测试的计算成本强加给构建您的程序包的任何人吗?这似乎是一个 XY 问题,您实际上要寻找的是一个好的持续集成框架。
  • @leftaroundabout 如果每次更改代码时都不运行单元测试,那么进行单元测试的意义何在?作为构建的一部分运行它们在 Java 和其他语言中很常见。回复:计算成本:是的,单元测试应该运行得很快;这是一个正交问题。
  • @jsbg 确切地说,您应该在开发期间使用与您指示最终用户使用的目标不同的目标进行构建。也就是说,使用cabal test,而其他人只会使用cabal buildcabal install

标签: haskell cabal


【解决方案1】:

您可以在使用 cabal v2 项目时使用 cabal.project.local 来执行此操作(如 cabal v2-build 这是默认设置,因此与 cabal 3.0 及更高版本的 cabal build 相同)。

策略就是在build目录下放一个cabal.project.local文件,内容如下:

tests: true

【讨论】:

    【解决方案2】:

    我发现这是一个非常糟糕的主意,因为它是破坏交叉编译的意外、非规范行为,但您可以将它与 Custom 构建类型一起破解。

    这是一个例子mypackage.cabal

    cabal-version:       >=2.0
    name:                mypackage
    version:             0.1.0.0
    author:              None
    maintainer:          none@example.com
    build-type:          Custom
    
    custom-setup
      setup-depends:
        base  >= 4.5,
        Cabal >= 2.0
    
    executable mypackage
      main-is: Main.hs
      build-depends: base >= 4
      default-language: Haskell2010
    
    test-suite test
      type: exitcode-stdio-1.0
      build-depends: base >= 4
      main-is: Test.hs
    

    以及对应的Setup.hs:

    import Control.Monad
    import Distribution.Simple
    import Distribution.Simple.Setup
    import Distribution.Simple.Test
    import Distribution.Simple.Build
    
    main = defaultMainWithHooks simpleUserHooks {
      postBuild = myPostBuild
    }
    
    myPostBuild args flags desc info =
      when ("exe:mypackage" `elem` buildArgs flags) $ do
        build desc info defaultBuildFlags { buildDistPref = buildDistPref flags } []
        test ["test"] desc info defaultTestFlags {
          testDistPref = buildDistPref flags
        }
    

    这确实导致了一个项目,其中cabal build 也在我的 Cabal 3.0.0.0 系统上构建和运行测试,但我不知道这有哪些额外的警告。

    【讨论】:

    • 你能解释一下为什么它会破坏交叉编译吗?
    • @jsbg 交叉编译时构建和运行测试套件会失败,因为编译后的输出无法在主机系统上执行。 Cabal 不支持区分主机和交叉编译器 afaik。
    • 谢谢,我不关心交叉编译(不分发源代码)所以这很好。