代码之家  ›  专栏  ›  技术社区  ›  Friedrich Gretz

自定义FsCheck输出

  •  4
  • Friedrich Gretz  · 技术社区  · 8 年前

    目前的问题是:我设法生成了随机图(用于测试一些图功能),但当测试失败时,FsCheck会吐出整个图,并且它不使用ToString,因此它实际上会转储原始记录列表,您在其中看不到任何内容。

    那么,我如何更改FsCheck的输出行为,以便

    • 实际上在输入图上调用我的ToString方法
    • 输出更多信息

    module GraphProperties
    
    open NUnit.Framework
    open FsCheck
    open FsCheck.NUnit
    
    let generateRandomGraph =
        gen {
            let graph: Graph<int,int> = Graph<_,_>.Empty()
            // fill in random nodes and transitions...
            return graph
        }
    
    type MyGenerators =
        static member Graph() =
            {new Arbitrary<Graph<int,int>>() with
                override this.Generator = generateRandomGraph
                override this.Shrinker _ = Seq.empty }
    
    [<TestFixture>]
    type NUnitTest() =
        [<Property(Arbitrary=[|typeof<MyGenerators>|], QuietOnSuccess = true)>]
        member __.cloningDoesNotChangeTheGraph (originalGraph: Graph<int,int>) =
            let newGraph = clone originalGraph
            newGraph = originalGraph
    
    2 回复  |  直到 8 年前
        1
  •  2
  •   rmunn    8 年前

    FsCheck使用 sprintf "%A" %A 格式化程序。根据 How do I customize output of a custom type using printf? ,方法是使用 StructuredFormatDisplay attribute PreText {PropertyName} PostText 哪里 PropertyName 应该是一个属性( 函数!)根据你的类型。E、 例如,假设你有一个树结构,叶子中有一些复杂的信息,但在测试中,你只需要知道叶子的数量,而不需要知道叶子中有什么。因此,您可以从以下数据类型开始:

    // 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” 所有物 ,不是函数( 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() with 关键字)。但我知道 结构化格式显示

    顺便说一句,你也可以设置一个 结构化格式显示

    // 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 类型

    这不是一个完全理想的解决方案,因为您可能需要调整