FsCheck使用sprintf "%A"
測試參數轉換爲字符串測試輸出,所以你需要做的就是控制你的類型是如何由%A
格式格式化。根據How do I customize output of a custom type using printf?,要做到這一點的方法是StructuredFormatDisplay
attribute。該屬性的值應該是格式爲PreText {PropertyName} PostText
的字符串,其中PropertyName
應該是您的類型的屬性(而不是函數!)。例如,假設您的樹葉結構中包含一些複雜的信息,但對於您的測試,您只需要知道樹葉的數量,而不是其中的內容。所以你會從這樣的數據類型開始:
// Example 1
type ComplicatedRecord = { ... }
type Tree =
| Leaf of ComplicatedRecord
| Node of Tree list
with
member x.LeafCount =
match x with
| Leaf _ -> 1
| Node leaves -> leaves |> List.sumBy (fun x -> x.LeafCount)
override x.ToString() =
// For test output, we don't care about leaf data, just count
match x with
| Leaf -> "Tree with a total of 1 leaf"
| Node -> sprintf "Tree with a total of %d leaves" x.LeafCount
現在,到目前爲止,這不是你想要的。這種類型的確不是而是具有聲明的自定義%A
格式,所以FsCheck(以及其他任何使用sprintf "%A"
來格式化的格式)將最終輸出樹的整個複雜結構及其所有不相關的測試葉數據。爲了讓FsCheck輸出你想看到的內容,你需要設置一個屬性,而不是一個函數(ToString
不能用於這個目的),它會輸出你想看到的內容。例如: -
// Example 2
type ComplicatedRecord = { ... }
[<StructuredFormatDisplay("{LeafCountAsString}")>]
type Tree =
| Leaf of ComplicatedRecord
| Node of Tree list
with
member x.LeafCount =
match x with
| Leaf _ -> 1
| Node leaves -> leaves |> List.sumBy (fun x -> x.LeafCount)
member x.LeafCountAsString = x.ToString()
override x.ToString() =
// For test output, we don't care about leaf data, just count
match x with
| Leaf -> "Tree with a total of 1 leaf"
| Node -> sprintf "Tree with a total of %d leaves" x.LeafCount
注:我還沒有在F#中測試了這個,只是輸進了堆棧溢出評論框 - 所以它可能是我搞砸ToString()
部分。 (我不記得,也無法用Google快速找到,覆蓋是否在with
關鍵字之後或之前)。但我知道StructuredFormatDisplay
屬性就是你想要的,因爲我自己使用這個來獲得FsCheck的自定義輸出。
順便說一句,你也可以在我的例子中的複雜記錄類型上設置StructuredFormatDisplay
屬性。舉例來說,如果你有,你關心的樹形結構,但不是葉子的內容,你會寫一個測試,如:
// Example 3
[<StructuredFormatDisplay("LeafRecord")>] // Note no {} and no property
type ComplicatedRecord = { ... }
type Tree =
| Leaf of ComplicatedRecord
| Node of Tree list
with
member x.LeafCount =
match x with
| Leaf _ -> 1
| Node leaves -> leaves |> List.sumBy (fun x -> x.LeafCount)
override x.ToString() =
// For test output, we don't care about leaf data, just count
match x with
| Leaf -> "Tree with a total of 1 leaf"
| Node -> sprintf "Tree with a total of %d leaves" x.LeafCount
現在所有的ComplicatedRecord
情況下,不管他們的內容,將在輸出中顯示爲文本LeafRecord
,您可以更好地專注於樹形結構 - 並且不需要在Tree
類型上設置StructuredFormatDisplay
屬性。
這不是一個完全理想的解決方案,因爲您可能需要隨時調整StructuredFormatDisplay
屬性,正如您正在運行的各種測試所需的那樣。 (對於某些測試,您可能需要關注葉數據的一部分,對於其他人,您希望完全忽略葉數據,等等)。在您投入生產之前,您可能需要將該屬性取出。但是,直到FsCheck獲得「給我一個功能,用」config參數格式化失敗的測試數據,這是讓您的測試數據格式化爲您需要的最佳方式。
你怎麼做你的斷言?即使使用NUnit來運行測試,也有不同的方法來斷言。這將有助於提供一個示例測試,甚至是最後一行。 – TheQuickBrownFox
我剛剛添加了一些代碼示例。最難的部分是讓發電機工作。對於屬性本身,我得到隨機輸入,用這個輸入調用待測方法並返回一個布爾值(在這種情況下爲比較結果)。 –
是'圖<_,_>'是一個記錄還是一個類?你能否提供(或許已被剝離)的定義?你看到的實際輸出是什麼? – TheQuickBrownFox