Как итеративно протестировать Haskell с помощью QuickCheck? - PullRequest
1 голос
/ 16 января 2020

Как создать случайный экземпляр в Haskell QuickCheck, а затем запустить дополнительные тесты для этого самого экземпляра?

Позвольте мне продемонстрировать, приведя пример. В следующем фрагменте кода я генерирую Int, а затем хочу запустить дополнительные тесты на этом самом Int:

{-# OPTIONS -Wall #-}

import           Test.Tasty
import           Test.Tasty.QuickCheck as QC
import qualified Debug.Trace as Trace

main :: IO()
main = defaultMain tests

test1 :: Int -> Property
test1 i = withMaxSuccess 2 (test2 i)

test2 :: Int -> (Int, Int) -> Property
test2 i (a, b) =
  Trace.trace ("(n,a,b) = " ++ show (i, a, b)) $
  property True

tests :: TestTree
tests =
  testGroup
  "Test suite"
  [
    QC.testProperty "Test" (withMaxSuccess 3 test1)
  ]

В качестве вывода я хочу получить что-то вроде:

(n,a,b) = (0,0,0)
(n,a,b) = (0,1,2)
(n,a,b) = (-1,-1,-1)
(n,a,b) = (-1,-2,-3)
(n,a,b) = (2,0,-2)
(n,a,b) = (2,1,-1)

Но вместо этого я получаю:

(n,a,b) = (0,0,0)
(n,a,b) = (-1,-1,-1)
(n,a,b) = (2,0,-2)

Я нашел этот пост (Как QuickCheck может проверить все свойства для каждого образца) , но он мне не очень помог.

1 Ответ

3 голосов
/ 16 января 2020

Рассмотрим функцию withMaxSuccess:

withMaxSuccess :: Testable prop => Int -> prop -> Property

Эта функция принимает любой Testable и превращает его в Property. Получившийся Property будет иметь поведение, которое будет выполняться для максимального числа, как указано Int.

Функция test1 является экземпляром Testable. Когда вы вызываете withMaxSuccess 3 test1, вы изменяете поведение test1, поэтому при запуске работает максимум три раза.

В то время как test1 возвращает Property при поведении, которое он запускает только два раза (withMaxSuccess 2), он переопределяется на withMaxSuccess 3.

Функция withMaxSuccess не запускает тест, она просто меняет определение свойства. withMaxSuccess 3 является последней модификацией свойства, поэтому вы видите, что оно работает три раза.

...