2

首先,让我介绍一下 F# 中的测试设置(在 NUnit 之上使用 FsUnit):

type SimpleRecord = { A: int; B: int } 
                    override x.ToString() = x.A.ToString()

[<TestFixture>]
type ``Simple Test Cases``() =     
    static member SimpleDataSource =
        [|
            [|{ A = 1; B = 2} ,3|]
        |]

    [<TestCaseSource("SimpleDataSource")>]
    member x.``SimpleTest`` (testData: SimpleRecord * int) =
        let data, expected = testData
        data.A + data.B
        |> should equal expected

此测试将按预期运行并通过。但是,将ToString覆盖更改为包含调用Guid.ToString()将阻止运行测试:

type SimpleRecord = { A: int; B: int } 
                    override x.ToString() = x.A.ToString() + Guid.NewGuid().ToString()

通过上述更改,测试仍然出现在测试资源管理器中,但不会运行。即使右键单击它并选择 Run Selected Tests 也不会执行测试。没有报告构建错误。

我也尝试过使用DateTime.ToString()而不是Guid.ToString(),但这也拒绝运行:

type SimpleRecord = { A: int; B: int } 
                    override x.ToString() = x.A.ToString() + DateTime.Now.ToString()

为什么调用Guid.ToString()或覆盖正在测试的类型会导致测试不运行DateTime.ToString()ToString

4

1 回答 1

2

Charlie Poole 解释了根本原因:

当使用 NUnit 控制台或 gui 运行器运行测试时,它们首先被加载(发现)然后执行。在适配器下运行时,测试会加载两次,一次在发现阶段,另一次在执行阶段开始。这是 VS 测试窗口工作方式的结果:发现和执行在 VS 创建的单独进程中运行。

在大多数情况下,这不会导致问题。测试被加载两次,这意味着用于创建任何测试数据的代码会运行两次。通常,两次都会生成相同的数据。

但是,当使用随机数据时,众所周知,每个阶段都会生成不同的数据。在运行“未知”测试时,初始发现中显示的测试似乎消失了。

在您的情况下,guid 会生成两次。第一个用作测试名称的一部分,因此,该测试在执行阶段消失。

这是一个演示解决方法的示例:

type ProblemRecord = { A: int; B: int } 
                     override x.ToString() = Guid.NewGuid().ToString()

[<TestFixture>]
type ``Test Cases``() =     
    // Using TestCaseData and explicitly setting a name will resolve the problem
    member x.SolutionDataSource =
        [
            TestCaseData(({ A = 1; B = 2} : ProblemRecord), 3)
                .SetName("Workaround")
        ]

    // This test case will be run by Test Explorer
    [<TestCaseSource("SolutionDataSource")>]
    member x.``SolutionTest`` (data: ProblemRecord, expected: int) =
        data.A + data.B
        |> should equal expected
于 2015-08-15T17:09:25.573 回答