例えばこのような関数があるとします。
class A {
func test (num : Int) {
if num < 10 {
printTest()
}
}
func printTest () {
print("test")
}
}
このような関数があった場合に、test(num : Int)をどうテストしようかな、と考えます。
検証したいケースは以下の2つ。
- num < 10の時に、printTestが実行されていること。
- num >= 10の時に、printTestが実行されていないこと。
悩んだこと
- printTestが実行されたことってどうやって検証するんや・・
- 実際にprintTestの中身で行われていることを検証すればいいが、それは関数testとは別のところでやってるから検証しなくてもいい(中でやってることは関係ない! コールしていることさえわかればいい!)
- テストのために返り値Boolつけるとか絶対やりたくねぇ・・
- (似てるが)テストのために関数の中身ごちゃごちゃ変えるとかそんなにしたくねぇ・・
- Cuckooの導入でつまづいた
解決方法
class A {
func test (num : Int) {
if num < 10 {
printTest()
}
}
func printTest () {
print("test")
}
}
class FakeA : A {
var printTestCount = 0
override func printTest () {
printTestCount += 1
super.printTest() // 親クラスの関数を実行をする
}
}
--XCTest--
func test_A_numが10未満_printTestが実行されていること() throws {
// 準備
let A = FakeA()
// 実行
A.test(num: 9)
// 検証
XCTAssertEqual(A.printTestCount, 1)
}
func test_A_numが10以上_printTestが実行されていないこと() throws {
// 準備
let A = FakeA()
// 実行
A.test(num: 11)
// 検証
XCTAssertEqual(A.printTestCount, 0)
}
懸念点
- 実際にprintTest(内部の関数)を実行することによって、test(テスト対象の関数)にて検証したい数値に影響が出る可能性がある。
- そうならない設計がベストではある。
- 関数実行のみを検証するのであれば、printTestの中身にてsuper.printTest()を実行しなければいいだけではある。
- だが、それではテストごとにFakeクラスを作成する必要があり非常に面倒
- いちいちFakeクラスを作るのがめんどくさい。
- privateメソッドの時とかのことはあんまり考えていない。(finalとかしちゃうとこれ使えないか)
ベストソリューションとは思っていないので、懸念漏れ/他のやり方等あればご指摘いただけるととっても嬉しいです。