2011-01-23 88 views
8

當通過QuickCheck測試失敗的屬性測試時,顯示原因的最佳做法是什麼?如何使用quickcheck顯示失敗測試屬性的原因?

考慮例如:

prop a b = res /= [] 
    where 
     (res, reason) = checkCode a b 

然後會話可能看起來像:

> quickCheck prop 
Falsifiable, after 48 tests: 
42 
23 

但對於調試這將是非常方便的,以示對失敗原因的快速檢查falsifable的一部分報告。

我已經破解這樣的:

prop a b = if res /= [] then traceShow reason False else True 
    where 
     (res, reason) = checkCode a b 

是否有更好的/更好以上quickcheckish辦法做到這一點?

回答

9

我假設你的「原因」變量包含某些特定於測試的數據。您可以返回一個「結果」,其中包含成功/失敗/無效條件和解釋錯誤的字符串。返回結果的屬性由QuickCheck以與返回Bool的屬性完全相同的方式處理。

(編輯)所示:

module QtTest where 

import Test.QuickCheck 
import Test.QuickCheck.Property as P 


-- Always return success 
prop_one :: Integer -> P.Result 
prop_one _ = MkResult (Just True) True "always succeeds" False [] [] 


-- Always return failure 
prop_two :: Integer -> P.Result 
prop_two n = MkResult (Just False) True ("always fails: n = " ++ show n) False [] [] 

請注意,這是在Test.QuickCheck.P​​roperty定義你想要的 「結果」 的類型。

也有Test.QuickCheck.P​​roperty定義了一些組合程序,幫助您撰寫的結果,而不是直接調用構造函數,如

prop_three :: Integer -> Property 
prop_three n = printTestCase ("always fails: n = " ++ show n) False 

我想這將是更好的風格來使用的。

2

由於QuickCheck爲您提供了函數的輸入,並且由於被測試的代碼是純的(它是正確的?),您可以將這些輸入提供給函數並獲得結果。這更加靈活,因爲通過這些輸入,您還可以重複測試原始功能,直到它正確爲止。

+2

那麼,問題的關鍵是方便。成功的測試都是關於儘可能的自動化。不得不打開一個ghci會話並重新計算一個潛在的昂貴函數是沒有意義的。我的意思是,QuickCheck已經提供`collect`,`classify`來豐富*非失敗*屬性測試的輸出。這種富集是可選的,並不會降低靈活性。 – maxschlepzig 2011-01-23 12:33:23

+1

我的意思是,這裏還有一個實際的原因:QuickCheck屬性可以是任意複雜的,所以任何給定測試的「輸出」都不一定是明顯的:你需要將你的代碼按照「嘿」 ,這裏是我感興趣的中間值!「假設你願意做這個重寫,雖然沒有理由不提供這種功能,但是IIRC QuickCheck沒有爲此目的而烘焙的東西。 – 2011-01-23 12:52:18

相關問題