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
をつけてしまうと、外部モジュールであるテストターゲット内で参照不可能になってしまいます。
なんだか手が届かないところがかゆい感じです。