Тестирование действий IO с Одноместным QuickCheck

Кто-либо может дать мне краткий пример тестирования действий IO с помощью Одноместного QuickCheck?

49
задан maxschlepzig 22 January 2011 в 22:19
поделиться

2 ответа

Модуль Test.QuickCheck.Monadic позволяет вам тестировать монадический код, даже то, что выполняется в IO.

Монадический тест свойств имеет тип PropertyM m a, где m - монада, в которой выполняется тест, а a в конечном итоге игнорируется. В случае PropertyM IO a вы преобразуете монадический тест в Property с помощью monadicIO; для всех остальных монад вместо этого используется monadic (которая принимает функцию для запуска монады, чего нет у IO).

В монадической проверке значение возвращаемое из монады игнорируется. Для проверки выражения используйте assert; assertвозврат ложного значения приведет к провалу теста. Используйте run для выполнения кода в тестируемой монаде.

В вашем распоряжении есть и другие монадические действия. Например, pick будет генерировать новые тестовые входы из Gen a, а pre будет проверять предварительные условия теста. Они полезны, если тестовые входы или предусловия сами зависят от значений, вычисляемых через тестируемую монаду, в этом случае обычный способ генерации входов или проверки предусловий не будет работать.

Вот пример тестирования некоторого IO кода: мы проверяем, что после записи чего-либо во временный файл мы можем прочитать эти же данные обратно. В демонстрационных целях наложим предварительное условие, что мы запишем в файл хотя бы один байт. Два тестовых свойства делают одно и то же; одно использует pick и pre без необходимости, а другое - нет.

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
57
ответ дан 7 November 2019 в 11:52
поделиться

Стандартным справочником по тестированию монадического кода является «Тестирование монадического кода с помощью QuickCheck» . Он показывает различные способы тестирования в контексте монады, такой как IO.

Но вам действительно стоит подумать о том, чтобы задать более конкретный вопрос о том, что вы хотите протестировать.

7
ответ дан 7 November 2019 в 11:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: