@DariusVのソリューションが好きです。ただし、開発者が Xcode のサイドバーから直接テスト メソッドを実行すると、うまく処理されません。それは私にとって契約違反です。
私がやっていることは、かなり巧妙だと思います。
サブクラスのインスタンス計算プロパティとして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;DR
@Code Differentの回答の適応: 入力と出力の辞書を使用し、for
ループで実行します。