我更喜欢@DariusV的解决方案。但是,当我开发人员直接从 Xcode 的侧边栏执行测试方法时,它并不能很好地处理。这对我来说是一个交易破坏者。
我最终做的事情我认为是相当光滑的。
我将 a Dictionary
of testValues
(probs 需要一个更好的名称) 声明为我的XCTestCase
子类的实例计算属性。然后,我定义了Dictionary
键入预期输出的输入文字。我的示例测试了一个作用于 的函数Int
,所以我这样定义testValues
:
static var testRange: ClosedRange<Int> { 0...100 }
var testValues: [Int: Int] {
let range = Self.testRange
return [
// Lower extreme
Int.min: range.lowerBound,
// Lower bound
range.lowerBound - 1: range.lowerBound,
range.lowerBound : range.lowerBound,
range.lowerBound + 1: range.lowerBound + 1,
// Middle
25: 25,
50: 50,
75: 75,
// Upper bound
range.upperBound - 1: range.upperBound - 1,
range.upperBound : range.upperBound,
range.upperBound + 1: range.upperBound,
// Upper extreme
Int.max: range.upperBound
]
}
在这里,我很容易声明我的边缘和边界情况。一种更符合语义的方法可能是使用元组数组,但 Swift 的字典文字语法足够薄,我知道这是做什么的。
现在,在我的测试方法中,我有一个简单的for
循环。
/// The property wrapper I'm testing. This could be anything, but this works for example.
@Clamped(testRange) var number = 50
func testClamping() {
let initial = number
for (input, expected) in testValues {
// Call the code I'm testing. (Computed properties act on assignment)
number = input
XCTAssertEqual(number, expected, "{number = \(input)}: `number` should be \(expected)")
// Reset after each iteration.
number = initial
}
}
现在要为每个参数运行,我只需以 Xcode 的任何正常方式或任何其他适用于 Linux 的方式(我假设)调用 XCTests。无需运行每个测试类来获得这个参数化。
那不是很漂亮吗?我只用几行DRY代码就涵盖了每个边界值和等价类!
至于识别失败案例,每次调用都通过一个XCTAssert
函数运行,根据 Xcode 的约定,只有在您需要考虑错误时才会向您抛出消息。这些显示在侧边栏中,但类似的消息往往会融合在一起。我的消息字符串在这里标识了失败的输入及其产生的输出,修复了混合在一起,并使我的测试流程成为一个理智的樱桃苹果派。(你可以用任何你喜欢的方式来格式化你的,土包子!任何能祝福你理智的东西。)
可口的。
TL;博士
@Code Different答案的改编:使用输入和输出字典,并for
循环运行。