テスト時のみEquatableプロトコルに準拠させる方法(Swift)
はじめに
「製品コードでは構造体を比較しないけど、テスト時は比較したい」ということはありませんか
テストで比較するためだけにEqutableに準拠させるのはありかなぁ🤔
— ウホーイ (@the_uhooi) January 12, 2020
Equatable
プロトコルに準拠することで、構造体同士を ==
で比較できるようになります。
struct FooEntity: Equatable {
let name: String
let age: Int
}
let fooEntity1 = FooEntity(name: "foo", age: 18)
let fooEntity2 = FooEntity(name: "foo", age: 24)
// `Equatable` に準拠しているため、ビルドが通る
XCTAssertEqual(fooEntity1, fooEntity2) // `age` が異なるのでテストは失敗する
このように製品コードで直接 Equatable
プロトコルに準拠させる方法が考えられますが、「 テスト時のみ比較したい 」という意図が読み取れません。
Twitterでテスト時のみ Equatable
プロトコルに準拠させる方法を教えていただいたので、備忘録として残します。
個人的な結論:テスト時のみEquatableプロトコルに準拠させる必要はない
本題に入る前にまず私の結論を言います。
本末転倒ですが、Twitterでいろいろ意見を頂いた結果、私は製品コードで Equatable
プロトコルに準拠させればいいと結論付けました。
理由は以下の通りです。
-
Equatable
プロトコルに準拠しても副作用がほとんどない- コンパイラが自動生成する
==
のコードによるオーバーヘッドくらい
- コンパイラが自動生成する
- テスト時のみ
Equtable
プロトコルに準拠させる方法はどれもデメリットがある
- 詳しくは後述する
- 「構造体が比較できる」ことを当たり前の言語仕様と考えれば、製品に不要なコードが含まれていることにはならない
- StringやIntも
Equatable
プロトコルに準拠しており、比較しなくても普通に使っている
- StringやIntも
方法①:テスト用のマクロを作る
@_ha1f さんから教えていただきました。
#if TEST
— はるふ(冬) (@_ha1f) January 13, 2020
extension Foo: Equatable {}#endif
はどう思いますか
(僕の中ではなしよりのあり)
テスト用のマクロを作り、テスト時のみエクステンションで準拠させます。
struct FooEntity {
let name: String
let age: Int
}
#if TEST
extension FooEntity: Equatable {}
#endif
これは思いつかなかったので目から鱗でした。
「テスト時のみ比較する」という意図が明確にわかります。
ただし、「 マクロが増える 」というデメリットがあります。
方法②:テストターゲットで準拠させる
方法①のエクステンションをテストターゲット側に記述すれば、マクロが不要になります。
@testable import FooTarget
extension FooEntity: Equatable {
public static func == (lhs: FooEntity, rhs: FooEntity) -> Bool {
return lhs.name == rhs.name && lhs.age == rhs.age
}
}
しかし、 ==
のコードを自分で実装し、 public
にする必要があります。
(なぜその必要があるかの言語仕様までは調べていません)
これは「 構造体に新しくプロパティを追加したときに、修正が必要になる 」というデメリットがあります。
修正しなくても警告やエラーが発生しないため、忘れがちになります。
おわりに
方法①も②もデメリットがあることがわかりました。
私はできる限りテスト時のみ使うコードを製品に含めたくないので、デメリットがなければ採用していました。
Twitterで議論が広がると、自分だけでは考えつかなかったことを学べるので、とてもありがたいです。
他にご意見のある方がいらっしゃれば、遠慮なくコメントやTwitterでご連絡ください!
Author And Source
この問題について(テスト時のみEquatableプロトコルに準拠させる方法(Swift)), 我々は、より多くの情報をここで見つけました https://qiita.com/uhooi/items/638a6116278a3e591773著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .