2012-12-04 23 views
3

我有一個QuickCheck屬性測試函數f。該屬性將函數f映射到某個列表xs並檢查結果的一些元素明智的屬性。在失敗的情況下,我想顯示與此失敗相關的xs的元素。考慮以下屬性:顯示QuickCheck屬性失敗的原因並處理測試函數中的異常

prop x = 
    printTestCase ("Failed for value " ++ show failure) $ isNothing failure 
    where 
    failure = fmap fst $ find (not . snd) $ map (\n -> (n, f x n == n)) [10..20] 

也能正常工作的實施

f = (+) 

quickcheck prop輸出

*** Failed! Falsifiable (after 2 tests):     
1 
Failed for value Just 10 

但是,如果f拋出一個異常,即

f = undefined 

然後quickcheck prop輸出

*** Failed! Exception: 'Prelude.undefined' (after 1 test): 
() 
Failed for value Exception thrown by generator: 'Prelude.undefined' 

我如何可以寫一個捕獲此第二個異常並返回「只需0」 爲前面的例子中的屬性?我想,可以使用whenFailwhenFail'這個,但我還沒有理解QuickCheck的內部。

+0

是否有一個原因,您不定義元素類型的屬性,並讓QuickCheck一次測試一個元素?然後QuickCheck會告訴你它失敗的價值。 –

+0

是的,我忘了提到這一點。在我的真實代碼中,我通過在所有估值的詳盡列表上比較它們來測試布爾公式的等價性。產出應該給我第一次估價,這些公式有偏差。 –

+0

我改變了問題,給出了一個更接近我真實代碼的例子。 –

回答

0

感謝#haskell頻道上的aavogt,我找到了模塊Control.Spoon,它提供了可用於解決此問題的勺子和茶匙功能。但是,我不知道使用這個軟件包有多安全(使用unsafePerformIO internally)。

總之,使用Control.Spoonprop可以改寫的方式如下:

prop x = 
    printTestCase ("Failed for value " ++ show pureFailure) $ isNothing excFailure 
    where 
    pureFailure = failure (fromMaybe True . teaspoon) 
    excFailure = failure id 
    failure g = fmap fst $ find (g . not . snd) $ map (\n -> (n, f x n == n)) [10..20] 

包裝紙與fromMaybe True . teaspoon查找謂詞有find返回 第一元素或者滿足謂語或拋出異常的影響。

由於teaspoon只能用於查看發生了異常,但不能用於此,因此我在此處使用 excFailure以便QuickCheck仍會看到異常。缺點是發現 需要評估兩次。 teaspoon只評估爲WHNF,如果您需要深入評估以觸發異常,請改用spoon

teaspoon只捕獲了一些選擇異常,這對我來說很好,因爲我只關心未定義和無窮無盡的模式匹配。

+0

我仍然想知道是否有不使用unsafePerformIO的解決方案。 –