[英]Haskell unit testing
我是haskell的新手,正在進行單元測試,但我發現生態系統非常混亂。 我對HTF和HUnit之間的關系感到困惑。
在一些示例中,我看到您設置測試用例,將它們導出到測試列表中,然后使用runTestsTT
在ghci中運行( 如此HUnit示例 )。
在其他示例中,您創建一個綁定到cabal文件的測試運行器,該文件使用一些預處理器魔法來查找您的測試,就像在這個git示例中一樣 。 似乎HTF測試需要以test_
為前綴,否則它們不會運行? 我很難找到任何相關的文檔,我只是注意到每個人都有的模式。
無論如何,有人可以幫我解決這個問題嗎? 什么被認為是在Haskell做事的標准方式? 什么是最佳做法? 什么是最容易設置和維護?
通常,任何重要的Haskell項目都與Cabal一起運行。 這需要建立,分發,文檔(在haddock的幫助下)和測試。
標准方法是將測試放在test
目錄中,然后在.cabal
文件中設置測試套件。 這在用戶手冊中有詳細說明。 這是我的一個項目的測試套件的樣子
Test-Suite test-melody
type: exitcode-stdio-1.0
main-is: Main.hs
hs-source-dirs: test
build-depends: base >=4.6 && <4.7,
test-framework,
test-framework-hunit,
HUnit,
containers == 0.5.*
然后在文件test/Main.hs
import Test.HUnit
import Test.Framework
import Test.Framework.Providers.HUnit
import Data.Monoid
import Control.Monad
import Utils
pushTest :: Assertion
pushTest = [NumLit 1] ^? push (NumLit 1)
pushPopTest :: Assertion
pushPopTest = [] ^? (push (NumLit 0) >> void pop)
main :: IO ()
main = defaultMainWithOpts
[testCase "push" pushTest
,testCase "push-pop" pushPopTest]
mempty
Utils
定義了一些比HUnit更好的接口。
對於輕量級測試,我強烈建議您使用QuickCheck 。 它允許您編寫短屬性並通過一系列隨機輸入對其進行測試。 例如:
-- Tests.hs
import Test.QuickCheck
prop_reverseReverse :: [Int] -> Bool
prop_reverseReverse xs = reverse (reverse xs) == xs
然后
$ ghci Tests.hs
> import Test.QuickCheck
> quickCheck prop_reverseReverse
.... Passed Tests (100/100)
我也是新手哈斯克勒,我發現這個介紹真有幫助:“ HUnit入門 ”。 總而言之,我將在這里放置一個沒有.cabal
項目文件的HUnit用法的簡單測試示例:
我們假設我們有模塊SafePrelude.hs
:
module SafePrelude where
safeHead :: [a] -> Maybe a
safeHead [] = Nothing
safeHead (x:_) = Just x
我們可以將測試放入TestSafePrelude.hs
,如下所示:
module TestSafePrelude where
import Test.HUnit
import SafePrelude
testSafeHeadForEmptyList :: Test
testSafeHeadForEmptyList =
TestCase $ assertEqual "Should return Nothing for empty list"
Nothing (safeHead ([]::[Int]))
testSafeHeadForNonEmptyList :: Test
testSafeHeadForNonEmptyList =
TestCase $ assertEqual "Should return (Just head) for non empty list" (Just 1)
(safeHead ([1]::[Int]))
main :: IO Counts
main = runTestTT $ TestList [testSafeHeadForEmptyList, testSafeHeadForNonEmptyList]
現在使用ghc
運行測試很容易:
runghc TestSafePrelude.hs
或hugs
-在這種情況下TestSafePrelude.hs
已重命名為Main.hs
(據我所熟悉的擁抱)(不要忘記更改模塊頭太):
runhugs Main.hs
或任何其他haskell
編譯器;-)
當然在HUnit
有更多,所以我真的建議閱讀建議的教程和庫用戶指南 。
你已經得到了大部分問題的答案,但你也問過HTF,以及它是如何工作的。
HTF是一個專為單元測試而設計的框架 - 它向后兼容HUnit(它集成並包裝它以提供額外的功能) - 以及基於屬性的測試 - 它與quickcheck集成。 它使用預處理器來定位測試,這樣您就不必手動構建列表。 使用編譯指示將預處理器添加到測試源文件中:
{-# OPTIONS_GHC -F -pgmF htfpp #-}
(或者,我猜你可以在你的cabal文件中為你的ghc-options
屬性添加相同的選項,但我從來沒有嘗試過,所以不知道它是否有用)。
預處理器掃描模塊以test_xxxx
名為test_xxxx
或prop_xxxx
頂級函數,並將它們添加到模塊的測試列表中。 您可以直接使用此列表,方法是在模塊中放置一個main
函數並運行它們( main = htfMain htf_thisModuleTests
)或從模塊中導出它們,並為多個模塊提供主要測試程序,這些模塊通過測試導入模塊並運行所有模塊他們:
import {-@ HTF_TESTS @-} ModuleA
import {-@ HTF_TESTS @-} ModuleB
main :: IO ()
main = htfMain htf_importedTests
該程序可以使用@jozefg描述的技術與cabal集成,或者加載到ghci並以交互方式運行(盡管不在Windows上 - 有關詳細信息,請參閱https://github.com/skogsbaer/HTF/issues/60 )。
Tasty是另一種提供集成不同類型測試的方法。 它沒有像HTF這樣的預處理器,但有一個使用Template Haskell執行類似功能的模塊。 與HTF一樣,它也依賴於命名約定來識別您的測試(在這種情況下, case_xxxx
而不是test_xxxx
)。 除了HUnit和QuickCheck測試之外,它還具有用於處理許多其他測試類型的模塊。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.