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