首先,让我介绍 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()
经过上述更改,测试仍然出现在测试资源管理器中,但不会运行。即使右键单击它并选择运行选定的测试也不会执行测试。没有报告任何构建错误。
我还尝试使用 DateTime.ToString()
而不是 Guid.ToString()
,但这也拒绝运行:
type SimpleRecord = { A: int; B: int }
override x.ToString() = x.A.ToString() + DateTime.Now.ToString()
为什么会在正在测试的类型的 ToString
覆盖中调用 Guid.ToString()
或 DateTime.ToString()
导致测试未运行?
最佳答案
Charlie Poole 提供了根本原因的解释:
When tests are run using the NUnit console or gui runners, they are first loaded (discovered) and then executed. When running under the adapter, the tests are loaded twice, once in the discovery phase and again at the beginning of the execution phase. This is a result of the way the VS Test Window works: discovery and execution are run in separate processes created by VS.
This doesn't cause a problem in most cases. The tests are loaded twice, which means the code for creating any test data is run twice. Usually, the same data is generated both times.
However, when using random data, it's known that different data will be generated in each phase. Tests that are shown in the initial discovery seem to disappear while "unknown" tests are run.
In your case, the guid is generated twice. The first one is used as part of the name of the test, consequently, that test disappears in the execution phase.
下面是一个演示解决方法的示例:
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
关于unit-testing - 当被测类型覆盖 ToString 时,无法运行 TestCaseSource 测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32014436/