LoginSignup
25
15

More than 5 years have passed since last update.

privateなAPIをテストする方法を考えてみた

Last updated at Posted at 2017-11-11

すこぶる同意。
ということで考えた。

型に、privateだけどtestしたいメンバがあるパターン

Hoge.swift
struct Hoge {
    init(x: Int) { self.x = x }

    /// privateだけどTestしたいメンバ
    fileprivate let x: Int
    fileprivate func doSomething(with string: String) -> String { return "\(string) \(x)" }
}

Targeted Extensionを使うとよさそう。

public protocol PrivatePublicatable {
    associatedtype Publicater
    var `private`: Publicater { get }
}
public final class Private<Base> {
    public let base: Base
    public init(_ base: Base) { self.base = base }
}
public extension PrivatePublicatable {
    var `private`: Private<Self> { return Private(self) }
}

↑こういうのを用意して…
Hoge.swift 内にextensionを書く。

Hoge.swift
extension Hoge: PrivatePublicatable {}
public extension Private where Base == Hoge {
    var x: Int { return base.x }
    func doSomething(with string: String) -> String {
        return base.doSomething(with: string)
    }
}

すると…

HogeTests.swift
let hoge = Hoge(x: 1)
hoge.private.x // 1
hoge.private.doSomething(with: "ほげ") // ほげ 1

外からアクセスできるけどprivateっぽさを明示できる。

そもそも型自身がprivateなパターン

Fuga.swift
private struct Fuga {
    let x: Int
    let y: Int
    func doSomething(with string: String) -> String { return "\(string) \(x) \(y)" }
}

型自体が外部から見えないので、アダプタとなる型を用意しないとどうしようもない。

Fuga.swift
/// Fugaをprivateに保つために作るTest用ラッパー。Fugaと同じファイル内に書く
final class FugaTester {
    private let base: Fuga
    init(args: (x: Int, y: Int)) {
        base = Fuga(x: args.x, y: args.y)
    }
    var x: Int { return base.x }
    var y: Int { return base.y }
    func doSomething(with string: String) -> String {
        return base.doSomething(with: string)
    }
}
FugaTests.swift
let tester = FugaTester(args: (x: 1, y: 2))
tester.x // 1
tester.y // 2
tester.doSomething(with: "ふが") // "ふが 1 2"

辛い…本当にこの道しかないんでしょうか…
ないとしても、ボイラープレートの山なので、Testerは自動生成したさありますね。
(すごい要望があればXcode Source Editor Extensionを作るのもやぶさかではない)

補足

25
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
15