对于这个有点笼统的问题感到抱歉。我是Haskell的新手,我是那种通过潜入问题并在我进行中弄清楚所需的部分而学习的人。所以,我已经开始开发一个Haskell模块,旨在进行简单的线性回归。这是我的目录设置:
mymod/
- mymod.cabal
- src/
-- MyMod/
--- Linear.hs
--- Linear/
---- Regression.hs
--- Data.hs
--- Data/
---- Examples.hs
- tst/
我的cabal文件如下所示:
library
exposed-modules: MyLib.Linear, MyLib.Linear.Classifier,
MyLib.Data, MyLib.Data.Examples
build-depends: base == 4.6.*
hs-source-dirs: src
现在,我正在编写Examples
模块,它本质上是一个CSV文件解析器。看起来像这样:
module Exampels (load) where
import Text.ParserCombinators.Parsec
import Control.Applicative
examples = line `endBy` eol
line = cell `sepBy` (char ',')
cell :: GenParser Char st Double
cell = rd <$> many1 (noneOf ",\n")
where rd = read :: String -> Double
eol = char '\n'
load :: String -> Either ParseError [[Double]]
load input = parse examples "(unknown)" input
这是我写的系统的第一部分。我使用ghci
中的:l Examples.hs
和mylib/src/MyLib/Data/
后跟load "5\n"
对此进行了测试,并验证了结果。现在我想开始编写回归逻辑,但我想结合我已编写的CSV解析器来测试这段代码。人们通常会如何测试这样的代码?
例如,在Java中,我通常会创建一个新的包,其中包含一个包含main方法的类。使用Java,这对我来说很简单,因为我理解了类路径是如何工作的,并且可以指示编译器查找我想要运行的类。我如何在Haskell中执行此操作?
谢谢!
答案 0 :(得分:13)
基本上有四种方法:编写测试,编写可执行文件,试验REPL(GHCI)和编写基准。幸运的是,最新的Cabal(1.18)支持所有这些。另外作为参考我有一个项目,exhibits some。
当您需要测试某些功能时,最好的方法可能就是编写单元测试。随着项目的发展而累积测试是其可靠性的关键。
有三个主要框架:HUnit用于单元测试,QuickCheck用于属性测试,doctest用于测试文档注释中的示例。还有一些圆顶框架,比如HTF,它将HUnit和QuickCheck结合在一起,让你从一些模板中解脱出来。
在Cabal中,您可以将测试套件定义为具有各自设置的单独编译单元。 Here is an example。然后,您可以使用cabal test
运行它们。
在某些情况下,测试并未真正涵盖要求。标准案例是一个程序,它演示了如何使用库。 Here is an example
您也可以使用可执行文件作为沙箱来测试库的API,但同样,更明智的方法是编写测试。
您可以使用cabal run [name]
运行可执行文件,其中“name”指定可执行文件名称(如果需要消除歧义)(例如,当您有多个时)。
主要好处是,当您加载内部模块,运行其功能并在更新时重新加载它们时,它允许您以“实时”模式试验项目模块的API。这可能对分析API很有用,但我个人发现上述两种方法涵盖了我可能需要的大部分内容。
您可以使用cabal repl [name]
在项目上运行GHCI。
Criterion是用于基准测试的单一主导库。与上面类似,您可以使用benchmark [name]
块在cabal中声明基准可执行文件。然后,您可以使用cabal bench
运行它们。