【问题标题】:Unable to run TestCaseSource tests when the type under test overrides ToString当被测类型覆盖 ToString 时无法运行 TestCaseSource 测试
【发布时间】:2015-08-14 16:15:19
【问题描述】:

首先,让我介绍一下 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()

为什么在 ToString 覆盖内调用 Guid.ToString()DateTime.ToString() 会导致测试未运行?

【问题讨论】:

  • 这对我来说似乎是一个测试运行程序问题。我可以使用 Visual Studio 的 NUnit 测试适配器重现它,但如果我使用 nunit-console.exe 运行测试,它可以正常工作。它也适用于 TestDriven.Net。
  • 我猜你说的是 ReSharper 测试运行器?
  • @MarkSeemann 你是对的!我已经在下面发布了解释和解决方案。
  • @Matthias 我正在使用带有 NUnit 测试适配器的 Visual Studio 2013 测试资源管理器。

标签: unit-testing f# nunit fsunit testcasesource


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2016-01-27
    • 1970-01-01
    • 2021-05-02
    • 1970-01-01
    • 1970-01-01
    • 2016-11-09
    • 1970-01-01
    • 2019-09-10
    • 1970-01-01
    相关资源
    最近更新 更多