我會sndBigger
開始 - 這是一個很簡單的功能,但你可以編寫應持有關它的一些特性。例如,什麼,當你扭轉元組中的值發生了:
// Reversing values of the tuple negates the result
let swap (a, b) = (b, a)
let prop_sndBiggerSwap x =
sndBigger x = not (sndBigger (swap x))
// If two elements of the tuple are same, it should give 'false'
let prop_sndBiggerEq a =
sndBigger (a, a) = false
編輯:此規則prop_sndBiggerSwap
並不總是持有(見註釋由KVB)。但是下面應該是正確的:
// Reversing values of the tuple negates the result
let prop_sndBiggerSwap a b =
if a <> b then
let x = (a, b)
sndBigger x = not (sndBigger (swap x))
關於pairs
功能,KVB已經張貼一些好的想法。另外,您可以檢查將變換後的列表變回到元素列表中,以返回原始列表(當輸入列表爲奇數時,您需要處理這種情況 - 這取決於在這種情況下函數應該做什麼):
let prop_pairsEq (x:_ list) =
if (x.Length%2 = 0) then
x |> pairs |> List.collect (fun (a, b) -> [a; b]) = x
else true
對於splitOn
,我們可以測試類似的事情 - 如果您連接所有返回的名單,也應該給原始列表(不驗證分裂行爲,但它是先從一件好事 - 它至少保證沒有元素會丟失)。
let prop_splitOnEq f x =
x |> splitOn f |> List.concat = x
我不知道如果FsCheck可以處理這個問題,但(!),因爲該屬性需要一個函數作爲參數(因此它需要生成「隨機函數」)。如果這不起作用,您需要提供幾個更具體的屬性,並使用一些手寫功能f
。接下來,實施檢查f
返回true,在分裂列出了所有相鄰的一對(如KVB建議)實際上不是那麼困難:
let prop_splitOnAdjacentTrue f x =
x |> splitOn f
|> List.forall (fun l ->
l |> Seq.pairwise
|> Seq.forall (fun (a, b) -> f a b))
大概只有最後,你可以檢查的是f
返回false
當您從一個列表中獲取最後一個元素並從下一個列表中獲取第一個元素時。以下是沒有完全完成,但它顯示的路要走:
let prop_splitOnOtherFalse f x =
x |> splitOn f
|> Seq.pairwise
|> Seq.forall (fun (a, b) -> lastElement a = firstElement b)
最後的樣本也顯示,您應檢查splitOn
功能是否可以返回一個空列表作爲結果返回列表的一部分(因爲在那種情況下,你找不到第一個/最後一個元素)。
感謝您的提示。我已經在使用xUnit檢查異常,所以沒有增加值(據我所知?)。對於我來說,這一切似乎都是非常具有挑戰性的,正如你所說的,在這些特定情況下,測試的風險比原始測試更復雜。 – Benjol 2010-03-15 14:39:18
檢查不應該更復雜 - 確實會影響測試的目的。但根據我的經驗,它們可能同樣複雜。隨着時間的推移,您的實現可能會變得更加複雜(例如優化),而屬性/規範通常保持大致相同。因此,雖然現在可能沒有意義,但您稍後可能會對這些屬性感到滿意。 – 2010-03-16 19:15:26