, 나는 그것이 이런 식 추측입니다 :
gen :: a -> ([a] -> [a]) -> ([a] -> Bool) -> a
gen init next stop = loop [init]
where
loop xs | stop xs = head xs
| otherwise = loop (next xs)
테스트 할 속성은 next
이 빈 목록을 제공하지 않습니다 것입니다 . 이것을 테스트하는 데 걸림돌이되는 것은 내부 루프 불변 값이 gen
안에 있는지 확인하려는 것이므로 외부에서 사용할 수 있어야합니다. 우리가이 정보를 반환 gen
을 수정할 수 :
genWitness :: a -> ([a] -> [a]) -> ([a] -> Bool) -> (a,[[a]])
genWitness init next stop = loop [init]
where
loop xs | stop xs = (head xs,[xs])
| otherwise = second (xs:) (loop (next xs))
우리는 Control.Arrow에서 second
를 사용합니다. 원래 gen
쉽게 게으른 평가 genWitness:
gen' :: a -> ([a] -> [a]) -> ([a] -> Bool) -> a
gen' init next stop = fst (genWitness init next stop)
감사의 용어로 정의되어이 많은 오버 헤드 우리를 제공하지 않습니다. 속성으로 돌아 가기! QuickCheck에서 생성 된 기능을 표시하려면 모듈 Test.QuickCheck.Function을 사용합니다. 여기에 꼭 필요한 것은 아니지만 속성을 단조로 변경하는 것이 좋습니다. 을 단위 목록으로 만드는 대신 Int
의 목록을 사용합니다.
prop_gen :: Int -> (Fun [Int] [Int]) -> (Fun [Int] Bool) -> Bool
prop_gen init (Fun _ next) (Fun _ stop) =
let trace = snd (genWitness init next stop)
in all (not . null) trace
우리는이 QuickCheck으로 실행 해 봅시다 : 우리가 지금 에게 재산 명시하자 ...
ghci> quickCheck prop_gen
뭔가 루프 것을 네 물론 다음 목록에 gen
루프 stop
경우 next
은 결코 True
입니다!
prop_gen_prefix :: Int -> (Fun [Int] [Int]) -> (Fun [Int] Bool) -> Int -> Bool
prop_gen_prefix init (Fun _ next) (Fun _ stop) prefix_length =
let trace = snd (genWitness init next stop)
in all (not . null) (take prefix_length trace)
우리는 지금 빨리 AA 카운터 - 예를 얻을 : 두 번째 함수는 인수 next
입니다
385
{_->[]}
{_->False}
2
을하고 있다면 우리는 대신에 대신 입력 추적 의 유한 접두사 살펴 봅시다 빈 목록, 을 반환하면 gen
의 루프는 next
에 빈 목록을 제공합니다.
이 질문에 대한 답변과 QuickCheck를 사용하여 고차원 함수를 테스트하는 방법에 대한 약간의 통찰력을 얻으시기 바랍니다.
다음과 같은 관련 속성이 있습니다. "비어 있지 않은 입력의 경우 '다음'은 비어 있지 않은 출력을 생성합니다." 언급 한 속성 대신이 속성을 테스트하거나 테스트 할 수도 있습니다. –
@ JohnL 사실! 하지만 그것은'gen'이 아닌'next'의 속성이고'next'는 first-order이므로 테스트하는 법을 압니다. –