簡體   English   中英

Haskell單元測試

[英]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_xxxxprop_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM