9
2

More than 1 year has passed since last update.

Sourceryを使って自動でEquatableに準拠させる

Last updated at Posted at 2022-12-20

この記事はand factory.inc Advent Calendar 2022 21日目の記事です。
昨日は @k_shinn さんの 【Jetpack Compose】WearOSで簡単なアプリを作ってみる でした。

はじめに

テストを書くときによく構造体の比較をしたいときがあるのですが、毎回Equatableに準拠させるために==の実装をするのが面倒だと感じてました。
そこで今回は、Sourceryというツールを使ってEquatableの実装を自動化してみました。

Sourceryとは

Sourceryとはボイラーテンプレートを自動生成してくれるSwift製のツールです。

環境

  • MacBook Pro Apple M1 Max
  • Xcode14.1(14B47b)
  • Swift:5.7.1
  • Mint:0.17.4

セットアップ

今回はMintを使ってインストールします。

Mintfile
krzysztofzablocki/Sourcery@1.9.2
$ mint bootstrap

.sourcery.ymlを作成する

コマンドラインから実行するときに指定するオプションをあらかじめ設定ファイルに記述しておきます。

.sourcery.yml
sources:
  # ソースとなるファイルやディレクトリのパス
  - Sample-Sourcery
templates:
  # テンプレートが格納されているパス
  - Sample-Sourcery/Templates
output: 
  # 自動生成したファイルを格納するパス
  Sample-Sourcery/Generated

Templateを配置する

自動生成するときに元となるテンプレートを配置します。

AutoEquatable.stencil
// AutoEquatable

{% for type in types.implementing.AutoEquatable|struct %}
extension {{type.name}}: Equatable {
  static func == (lhs: {{type.name}}, rhs: {{type.name}}) -> Bool {
    {% for variable in type.storedVariables|!annotated:"skipEquality" %}guard lhs.{{variable.name}} == rhs.{{variable.name}} else { return false }
    {% endfor %}
    return true
  }
}
{% endfor %}

プロトコルの実装

Equatableの実装を自動生成したい構造体は、AutoEquatableに準拠させる必要があるので、AutoEquatableプロトコルを定義しておきます。

SourceryProtocols.swift
protocol AutoEquatable {}

AutoEquatableに準拠させる

Equatableの実装を自動生成したい構造体にAutoEquatableを準拠させます。

User.swift
import Foundation

struct User: AutoEquatable {
    let id: Int
    let name: String
    let iconUrlStr: String
}

Sourceryを実行

ここまで準備ができたら、コマンドラインからSourceryを実行してEquatableの実装を自動生成します。

$ mint run krzysztofzablocki/Sourcery

自動生成されたファイル

実行が成功すると、.sourcery.ymloutput:に定義したパスに自動生成されたコードが出力されます。

AutoEquatable.generated.swift
// Generated using Sourcery 1.9.2 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
// AutoEquatable

extension User: Equatable {
  static func == (lhs: User, rhs: User) -> Bool {
    guard lhs.id == rhs.id else { return false }
    guard lhs.name == rhs.name else { return false }
    guard lhs.iconUrlStr == rhs.iconUrlStr else { return false }
    return true
  }
}

おわりに

Sourceryを使うことでEquatableの実装を簡単に行うことができるようになりました。
Sourceryは他にもMockなども自動生成できるので、それらも活用してテストの実装コストを下げていければと思います。

明日のAdvent Calendarの記事もお楽しみに:santa:

参考リンク

https://github.com/krzysztofzablocki/Sourcery
https://github.com/krzysztofzablocki/SourceryWorkshops/tree/steps
https://enmtknt.hateblo.jp/entry/2018/03/13/153344

9
2
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
9
2