1. ホーム
  2. unit-testing

Haskellのユニットテスト

2023-07-23 15:20:20

質問

私はhaskellの初心者で、ユニットテストに取り組んでいますが、エコシステムが非常に分かりにくいと感じています。 HTFとHUnitの関係で混乱しています。

いくつかの例では、テストケースを設定し、それらをテストリストにエクスポートし、そしてghciで次のように実行します。 runTestsTT (のように)。 この HUnit の例 ).

他の例では、cabal ファイルに結びついたテストランナーを作成し、プリプロセッサの魔法を使って次のようにテストを探します。 git の例 . また、HTF のテストはプレフィックスとして test_ を付けなければ実行されないようです。私はそれに関するドキュメントを見つけるのに苦労しましたが、私はちょうど誰もが持っていたパターンに気づきました。

とにかく、誰かが私のためにこれを解決するのを助けることができますか?Haskell で物事を行う標準的な方法と考えられているものは何ですか?ベストプラクティスは何でしょうか。セットアップとメンテナンスが最も簡単なのは何ですか?

どのように解決するのですか?

一般に、重要なHaskellのプロジェクトはすべて Cabal . これはビルド、配布、ドキュメント作成(haddockの助けを借りて)、そしてテストの面倒を見ます。

標準的なアプローチでは、テストは test ディレクトリに置き、テストスイートを .cabal ファイル内にテストスイートを設定します。これについては ユーザーマニュアル . 私のプロジェクトの1つのテストスイートは以下のようになります。

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 .

軽量なテストには クイックチェック . これは、短いプロパティを書いて、一連のランダムな入力に対してそれらをテストすることができます。例えば

 -- 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)