Может ли кто-нибудь дать мне краткий пример тестирования действий ввода-вывода с использованием Monadic QuickCheck?
Тестирование операций ввода-вывода с помощью Monadic QuickCheck
Ответы (2)
Тест монадического свойства имеет тип PropertyM m a
, где m
— монада, в которой выполняется тест, а a
в конечном счете игнорируется. В случае PropertyM IO a
вы преобразуете монадический тест в Property
, используя monadicIO
; для всех других монад вместо этого вы используете monadic
(который использует функцию для запуска монады, чего нет у IO
).
В монадическом тесте значение return
ed вне монады игнорируется. Чтобы проверить выражение, используйте 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
Стандартный справочник по тестированию монадического кода: "Тестирование монадического кода с помощью QuickCheck" а>. Он показывает различные способы тестирования в контексте такой монады, как IO.
Но вам действительно следует подумать о том, чтобы опубликовать более конкретный вопрос о том, что вы хотели бы протестировать.