2012-10-14 90 views
9

我寫了一個快速檢查屬性,用於合併兩個已排序輸入到排序輸出的函數:條件快速檢查屬性

prop_merge xs ys = 
    if (sorted xs && sorted ys) then (sorted (merge xs ys)) else True 

也就是說,當輸入被排序,輸出的排序也是如此。它也可以寫成:

prop_merge xs ys = not(sorted xs && sorted ys) || (sorted (merge xs ys)) 

但我並不喜歡這兩種版本。 QuickCheck中有沒有更好的「條件屬性」語法?

回答

27

可以使用==>操作的布爾條件附加到您的屬性:

prop_merge xs ys = (sorted xs && sorted ys) ==> sorted (merge xs ys) 

這不僅是一個更好的語法,但允許快速檢查測試情況下,測試成功和測試用例之間的區分不符合先決條件。在後一種情況下,測試不計和快速檢查生成新的輸入。

然而,在大多數輸入不滿足條件的情況下,這將導致你的測試無論是運行速度比較慢,或者,如果有足夠的投入被丟棄,快速檢查將最終放棄。由於隨機列表是不可能進行排序,這是非常有可能與上面的例子發生:

> quickCheck (prop_merge :: [Int] -> [Int] -> Property) 
*** Gave up! Passed only 15 tests. 

(請注意,使用標準的布爾運算符,而不是使用==>,快速檢查將提高所有測試被傳遞,當他們大多是無用由於失敗的先決條件)

出於這個原因,它通常要好得多隻有直接生成所需的測試用例。對於簡單的情況下,Test.QuickCheck.Modifiers模塊包含修改生成的輸入的方式幾個有用newtypes。例如,OrderedList修飾符將只生成排序列表,因此我們可以將您的屬性寫爲:

prop_merge (Ordered xs) (Ordered ys) = sorted (merge xs ys) 
+0

啊,那看起來好多了! – fredoverflow

+2

我認爲明確指出'==>'不僅是一種更好的語法,而且允許QuickCheck區分測試成功的測試用例和不滿足前提條件的測試用例。在後一種情況下,測試不計和快速檢查生成新的輸入。這是什麼使快速檢查給你了「***放棄了!只傳遞15的測試。」消息「。如果通過標準布爾運算符表達前提條件,QuickCheck將提升所有通過的測試,由於前提條件失敗,其中大部分測試都無效。 –

+0

@cebewee:感謝您的建議。因爲他們被審稿人拒絕。 – hammar