Swift2.0でUnit Testを書く際に@testableというattributeが追加されました。
この@testableを使用する際の注意事項です。
まずはアクセス制御について確認しましょう。以前書いたものから引っ張ってきました。
アクセス制御
Swiftは モジュール と ソースファイル をアクセス制御の単位としています。
| アクセスレベル | 用途 | |
|---|---|---|
| public | どこからでもアクセス可能 | どこからでもアクセス可能なのでframeworkのAPIを定義する場合はこれを使う |
| internal | デフォルトのアクセスレベル | 自身のモジュールと同じモジュールのソースファイル内であればアクセス可能。何も指定しない場合はこれが指定される。 |
| private | 最も厳しいアクセスレベル | モジュール内の同じソースファイルでなければアクセスできない。外部に隠蔽しておきたいものはこれを指定。 |
@testableの書き方
@testableはimportと一緒に記載します。以下はProductKitというEmbedded Frameworkを作成し、そのUTを記述した際のものです。
import XCTest
@testable import ProductKit
class ProductKitTests: XCTestCase {
override func setUp() {
super.setUp()
}
override func tearDown() {
super.tearDown()
}
func testExample() {
let something = Something(publicName: "public", internalName: "internal")
something.publicHello(something.publicName)
something.internalHello(something.internalName)
}
}
2行目のimportの前に@testableを記述しています。internalなメソッドやプロパティに対してはこれでアクセス可能になります。
注意点
注意点としては、@testableをつけてもアクセス可能なのは**internalまでで、privateな関数、メソッド、プロパティにはアクセスできません。**
よく考えれば、外部モジュールにさえしておけばinternalで十分隠蔽されている状態になります。モジュールが分かれていればinternalなプロパティやメソッドにはアクセスできないので。
いままで外部モジュールで作成したクラス内の、内部でしか使用しないメソッドなどはprivateにしていましたが、モジュールが分かれていれば参照不可能になるのでinternalで十分なのかもしれません。というか、そうしないとテスト不可能になります。
ただし同一モジュール内ではinternalなプロパティやメソッドにはアクセスできてしまうわけで、隠蔽したいからとprivateをつけてしまうと、外部モジュールであるテストターゲット内で参照不可能になってしまいます。
なんだか手が届かないところがかゆい感じです。