Monadic QuickCheck で IO アクションをテストする 質問する

Monadic QuickCheck で IO アクションをテストする 質問する

Monadic QuickCheck を使用して IO アクションをテストする簡単な例を教えていただけますか?

ベストアンサー1

テスト.クイックチェック.モナディックモジュールを使用すると、 で実行されるものであっても、モナドコードをテストできますIO

モナド プロパティ テストは 型でPropertyM m a、 はmテストが実行されるモナドであり、a最終的には無視されます。 の場合、 を使用してPropertyM IO aモナド テストを に変換します。他のすべてのモナドの場合は、代わりに を使用します (これは、モナドを実行する関数を取りますが、 には含まれていません)。PropertymonadicIOmonadicIO

returnモナドテストでは、モナドから出力された値は無視されます。式をチェックするには、 assert;を使用します。assert偽の値を入力するとテストは失敗します。runテスト対象のモナドのコードを実行するには を使用します。

他にも自由に使えるモナドアクションがあります。たとえば、pickは から新しいテスト入力を生成しGen a、はpreテストの前提条件をチェックします。これらは、テスト入力または前提条件自体がテスト対象のモナドによって計算された値に依存している場合に役立ちます。その場合、通常の方法で入力を生成したり前提条件をチェックしたりすることはできません。

以下に、コードをテストする例を示しますIO。一時ファイルに何かを書き込んだ後、同じデータを読み戻せるかどうかを確認します。デモンストレーションの目的で、ファイルに少なくとも 1 バイトを書き込むという前提条件を課します。2 つのテスト プロパティは同じことを行います。一方はとpickpre不必要に使用しますが、もう一方は と を使用しません。

import System.Directory (removeFile)
import System.IO (hGetContents, hPutStr, hSeek, openBinaryTempFile, SeekMode (..))
import Test.QuickCheck (arbitrary, Property, quickCheck, (==>))
import Test.QuickCheck.Monadic (assert, monadicIO, pick, pre, run)

-- Demonstrating pick and pre as well:
prop_writeThenRead :: Property
prop_writeThenRead = monadicIO $ do writtenData <- pick arbitrary
                                    pre $ not (null writtenData)
                                    readData <- run $ writeThenRead writtenData
                                    assert $ writtenData == readData

-- A more idiomatic way to write the above:
prop_writeThenRead2 :: [Char] -> Property
prop_writeThenRead2 writtenData = not (null writtenData) ==> monadicIO test
    where test = do readData <- run $ writeThenRead writtenData
                    assert $ writtenData == readData

writeThenRead :: [Char] -> IO [Char]
writeThenRead output = do (path, h) <- openBinaryTempFile "/tmp" "quickcheck.tmp"
                          removeFile path
                          hPutStr h output
                          hSeek h AbsoluteSeek 0
                          hGetContents h

main :: IO ()
main = do quickCheck prop_writeThenRead
          quickCheck prop_writeThenRead2

おすすめ記事