我更喜欢@DariusV 的solution。但是,当我开发人员直接从 Xcode 的侧边栏执行测试方法时,它并不能很好地处理。这对我来说是个大问题。
我认为我最终做的事情相当巧妙。
我声明testValues 的Dictionary(可能需要一个更好的名称)作为我的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;DR
改编自@Code Different 的answer:使用输入和输出字典,并使用for 循环运行。 ?