You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cabal测试覆盖率报告为空及多报告文件问题咨询

Haskell Cabal 覆盖率报告问题解析

项目背景

项目结构

.git
src/
  exe/
    Main.hs
  lib/
    ModuleA/
    ModuleB/
    UnitTests/
      UnitTests.hs
    MainLib.hs
giter.cabal

可执行文件代码(src/exe/Main.hs)

import qualified MainLib

main :: IO ()
main = MainLib.main

Cabal 配置片段(giter.cabal)

library 
    import: shared-properties
    exposed-modules: MainLib
    other-modules:
        ModuleA
        ModuleB

    build-depends:
      , brick
      , directory
      , fsnotify

    hs-source-dirs:   src/lib

executable giter
    import: shared-properties
    main-is:          Main.hs
    other-modules:

    build-depends:
        , giter
        , base
        , brick
    hs-source-dirs:   src/exe

test-suite giter-test
    type:             exitcode-stdio-1.0
    hs-source-dirs:   src/lib
    main-is:          UnitTests/UnitTests.hs
    default-language: Haskell2010
    other-modules:
        ModuleA
        ModuleB
    build-depends:
        , base
        , directory
        , HUnit
        , QuickCheck

问题现象

执行命令 cabal new-test all --enable-coverage 后测试全部通过,但生成的两个HTML覆盖率报告均无有效数据,示例如下:

module  Top Level Definitions   Alternatives    Expressions
%   covered / total %   covered / total %   covered / total
  Program Coverage Total    -   0/0     -   0/0     -   0/0  

问题解答

1. 覆盖率报告缺失数据的原因

  • 测试套件未复用库的插桩编译产物:测试套件giter-test的hs-source-dirs设为src/lib,并直接将ModuleA、ModuleB列为other-modules,这会让Cabal重新编译这些模块且未启用覆盖率插桩。测试运行的是无插桩的模块,自然无法收集覆盖率数据。
  • 库目标未启用覆盖率编译:默认情况下,--enable-coverage仅为测试套件启用覆盖率插桩,库目标需要显式开启,否则测试依赖的库模块没有覆盖率收集能力。

2. 生成两个报告的原因

  • 命令中的all会触发所有目标的覆盖率收集,包括库目标和测试套件目标,两者各自生成报告。
  • 你的测试套件配置直接编译src/lib下的业务模块,相当于独立构建了一个包含这些模块的二进制,而非依赖已编译的库,这会额外生成一份测试套件自身的覆盖率报告。

修复方案

调整测试套件配置

修改test-suite giter-test部分,让它依赖库目标giter,仅编译测试代码:

test-suite giter-test
    type:             exitcode-stdio-1.0
    hs-source-dirs:   src/lib/UnitTests  # 仅指向测试代码目录
    main-is:          UnitTests.hs
    default-language: Haskell2010
    build-depends:
        , base
        , directory
        , giter  # 依赖库目标,复用带插桩的业务模块
        , HUnit
        , QuickCheck

全局启用覆盖率

运行测试时显式开启库和测试的覆盖率:

cabal new-test giter-test --enable-coverage --enable-library-coverage

或者在项目根目录创建cabal.project文件,添加全局配置:

coverage: True
library-coverage: True

内容的提问来源于stack exchange,提问作者Refael Sheinker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 09:15:54