仅构建可执行文件的Haskell项目中的代码覆盖率

xzv2uavs  于 2023-04-30  发布在  其他
关注(0)|答案(1)|浏览(133)

我有一个阴谋集团的项目,它构建了一个可执行文件。
当我运行cabal test --enable-coverage时,我得到以下错误:

All 9 tests passed (0.98s)
Test suite giter-test: PASS
Test suite logged to:
/home/refaelsh/repos/giter/dist-newstyle/build/x86_64-linux/ghc-9.2.7/giter-0.1.0/test/giter-0.1.0-giter-test.log
Error: .cabal-wrapped: Test coverage is only supported for packages with a
library component.

Error: cabal: Tests failed for giter-0.1.0.

1.有人能解释一下这是怎么回事吗?
1.当我的cabal项目只有一个可执行文件而没有库时,这个错误是正常的吗?
1.我是否应该只创建一个我想要的单元测试部分的库,并使我的exe依赖于该库?
1.如果是,这是惯用Haskell中的常见做法吗?
1.如果是的话,那么为了适应单元测试而对源代码和/或项目结构进行更改,感觉就像是一种代码气味。

9jyewag0

9jyewag01#

我认为this issue中涵盖了潜在的技术问题。Cabal假设你不想要单元测试代码本身的覆盖率报告,只想要被测试的代码,所以它调用hpc的方式是排除单元测试代码,只有实际被测试的源代码才包含在覆盖率报告中。如果代码是单独编译的库的一部分,这很容易做到:涵盖了库,但不涵盖任何属于单元测试的模块。
但是,如果您没有library节,只有executabletest-suite节使用共享的模块集,则没有明显的方法来区分单元测试中不应覆盖的test-suite模块和应覆盖的被测试代码中的模块。
更普遍地说,Cabal对测试executable节的支持很差。根据this issue中的讨论,真正测试executable的唯一方法是使用hack -要么指定executabletest-suite节共享相同的hs-source-dirs,最终双重编译所有内容,要么将重要的内容移动到library中,并将executable作为存根。你可能使用的是前一种方法,而不是后一种,但两者都很糟糕。开发人员似乎已经决定“将所有内容都移动到library中”是推荐的方法,即使不是所有的文档和/或教程材料都清楚地说明了这一点。
请注意,Stack的情况与此类似--默认模板通常有一个存根应用程序,其中只包含一个main函数,其他所有内容都被移到库中。
我想我会建议将整个应用程序(而不仅仅是你想要测试的部分)移动到library中,并为你的executable编写一个stub main函数,如下所示:

module Main where

import qualified Lib

main :: IO ()
main = Lib.main

test-suiteexecutable都取决于library

相关问题