Tôi sẽ bắt đầu với sndBigger
- đó là một chức năng rất đơn giản, nhưng bạn có thể viết một số tài sản mà nên giữ về nó. Ví dụ, những gì sẽ xảy ra khi bạn đảo ngược các giá trị trong các tuple:
// 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
EDIT: này quy tắc prop_sndBiggerSwap
không phải lúc nào giữ (xem bình luận bởi kvb). Tuy nhiên những điều sau đây nên chính xác:
// 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))
Về pairs
chức năng, kvb đã được đăng một số ý tưởng tốt. Ngoài ra, bạn có thể kiểm tra việc chuyển danh sách được chuyển trở lại thành danh sách các phần tử trả về danh sách gốc (bạn cần xử lý trường hợp khi danh sách đầu vào là lẻ - tùy thuộc vào chức năng pairs
sẽ làm trong trường hợp này):
let prop_pairsEq (x:_ list) =
if (x.Length%2 = 0) then
x |> pairs |> List.collect (fun (a, b) -> [a; b]) = x
else true
Đối splitOn
, chúng ta có thể kiểm tra điều tương tự - nếu bạn nối tất cả các danh sách trở lại, nó sẽ cho danh sách ban đầu (điều này không xác minh hành vi chia tách, nhưng nó là một điều tốt để bắt đầu - nó ít nhất đảm bảo rằng không có yếu tố nào sẽ bị mất).
let prop_splitOnEq f x =
x |> splitOn f |> List.concat = x
Tôi không chắc chắn nếu FsCheck có thể xử lý mặc dù điều này (!) Vì tài sản mất một chức năng như một cuộc tranh cãi (vì vậy nó sẽ cần phải tạo ra "chức năng ngẫu nhiên"). Nếu điều này không hiệu quả, bạn sẽ cần phải cung cấp một vài thuộc tính cụ thể hơn với một số hàm viết tay f
. Tiếp theo, thực hiện việc kiểm tra rằng f
lợi nhuận đúng đối với tất cả các cặp liền kề trong danh sách tách (như kvb gợi ý) không phải là thực sự là khó khăn:
let prop_splitOnAdjacentTrue f x =
x |> splitOn f
|> List.forall (fun l ->
l |> Seq.pairwise
|> Seq.forall (fun (a, b) -> f a b))
Có lẽ điều cuối cùng duy nhất mà bạn có thể kiểm tra là f
trả về false
khi bạn cho nó phần tử cuối cùng từ một danh sách và phần tử đầu tiên từ danh sách tiếp theo. Sau đây là không hoàn toàn đầy đủ, nhưng nó cho thấy con đường để đi:
let prop_splitOnOtherFalse f x =
x |> splitOn f
|> Seq.pairwise
|> Seq.forall (fun (a, b) -> lastElement a = firstElement b)
Mẫu cuối cùng cũng cho thấy rằng bạn nên kiểm tra xem splitOn
chức năng có thể trả về một danh sách rỗng như một phần của danh sách trả về kết quả (vì trong trường hợp đó, bạn không thể tìm thấy phần tử đầu tiên/cuối cùng).
Cảm ơn các mẹo. Tôi đã kiểm tra ngoại lệ với xUnit, vì vậy không có giá trị gia tăng ở đó (theo như tôi có thể nói?).Tất cả dường như rất suy nghĩ cho tôi vào lúc này, và như bạn nói, trong những trường hợp cụ thể này, rủi ro kiểm tra phức tạp hơn bản gốc. – Benjol
Séc không nên phức tạp hơn - điều đó thực sự đánh bại mục đích thử nghiệm. nhưng chúng có thể phức tạp như nhau, theo kinh nghiệm của tôi. Theo thời gian, việc triển khai của bạn có thể trở nên phức tạp hơn (ví dụ: tối ưu hóa), trong khi các thuộc tính/thông số thường ít nhiều giống nhau. Vì vậy, trong khi nó có thể không có ý nghĩa bây giờ, bạn có thể sẽ được hạnh phúc với các thuộc tính sau này. –