Xcode Source Editor Extensionを使って、実装ファイルとテストファイルをトグルジャンプする

まえがき

以前、iOS Test Night #4という勉強会にて、テストを書かない言い訳をした結果wwwwwww // Speaker Deckという発表①をしました。
この発表①はもっと過去のiOS Test Nightで行った発表⓪を枕にした発表です。ややこしいな。
発表⓪にて、テストファイルと実装ファイルって
distance.png
みたいに距離があると気軽に行き来するには辛すぎるよねと話したんですが、そしたら

テストを書かない言い訳をさせてくれ // Speaker Deck

Java+Eclipse時代はプロダクトコードとテストコードをトグル的に行き来できるプラグイン入れてたけどXcode+Swiftはそういうのないの???

2017/03/17 10:15

と言われたので、それができるように
https://github.com/takasek/XCJumpToTests/blob/master/xcode_toggleImplAndTests.scpt
というAppleScriptスクリプトを作りました、というのが発表①の内容でした。

o.gif

xcode_toggleImplAndTests.scpt の使い方

Xcodeには Custom Behavior という機能があり、任意のスクリプトをワンタップで実行できます。
適当な場所にスクリプトを置いて、設定からTrigger Hot Keyを設定します。
behavior.png

Hoge.swift で実行したら HogeTests.swift あるいは HogeSpec.swift に、
HogeTests.swift あるいは HogeSpec.swift で実行したら Hoge.swift にジャンプします。

ありがたいことに、今も活用していただけてると報告を受けることがあります。
けど問題もありまして、

xcode_toggleImplAndTests.scpt の問題点

AppleScript読みづらいし書きづらい。
本当ならメンテしやすいように、SwiftかObj-Cで書きたいものです。
というかXcode Source Editor Extensionで実現できれば最高なんだけどなー…
と思ってたところで、それを可能にするワークアラウンドを思いつきました。
その詳細については数日前の別記事 続・Xcode Source Editor Extensionの世界 〜XPCとScripting Bridge〜 - Qiita で解説しました。

xcode_toggleImplAndTests.scpt をXcode Source Editor Extension化してみた

これが成果物です。
https://github.com/takasek/XCJumpToTests

使い方

  1. プロジェクトをcloneして、Xcodeで開きます
  2. プロビジョニングプロファイルを書き替えてArchiveします
  3. 出来上がった .app を実行すると、コンピュータにXcode Source Editor Extensionがインストールされます
  4. 設定画面からホットキーを設定します

image.png

スクリプトバージョンに比べて、ビルドする手間が増えましたが、スクリプトの置き場所に悩む必要はなくなり、Xcodeと統合された安心感と格段のメンテナンス性が手に入りました。

制限

プロジェクトをArchiveする必要があるということは、有料のApple Developer Program登録をしている必要があるということです。
有料登録していない開発者であれば、AppleScript版が役に立つことでしょう。

XcodeとのScripting Bridge によるテストの可能性

「テスト自動化」の話かって言われると少し苦しい記事内容になってしまった気がするので、ついでに、最後にそれっぽい話でお茶を濁しましょう。

Xcode Scripting Bridgeには次のようなインタフェースがあります。

- (XcodeSchemeActionResult *) testWithCommandLineArguments:(id)withCommandLineArguments withEnvironmentVariables:(id)withEnvironmentVariables;

ちなみに XcodeSchemeActionResult ってのはこんな奴。

// An object describing the result of performing a scheme action command.
@interface XcodeSchemeActionResult : SBObject <XcodeGenericMethods>

- (SBElementArray<XcodeBuildError *> *) buildErrors;
- (SBElementArray<XcodeBuildWarning *> *) buildWarnings;
- (SBElementArray<XcodeAnalyzerIssue *> *) analyzerIssues;
- (SBElementArray<XcodeTestFailure *> *) testFailures;

- (NSString *) id;  // The unique identifier for the scheme.
@property (readonly) BOOL completed;  // Whether this scheme action has completed (sucessfully or otherwise) or not.
@property XcodeSchemeActionResultStatus status;  // Indicates the status of the scheme action.
@property (copy) NSString *errorMessage;  // If the result's status is "error occurred", this will be the error message; otherwise, this will be "missing value".
@property (copy) NSString *buildLog;  // If this scheme action performed a build, this will be the text of the build log.


@end

これを使えば、Apple ScriptやXcode Source Editor Extensionからテストを実行し、終了を監視することも可能かもしれません。
……そこ、誰得とか言わない。

完全に余談ですが

今回のプロジェクトを準備していたところ、Twitterにてこんな反応をいただきました。

確かに、ジャンプ元・ジャンプ先を求めるロジックだけ切り出してエディットできるようにすれば、もっと柔軟で使い道が広がるなーと思いつつ、今回そこまでやると完全にアドベントカレンダーの趣旨から抜けてしまうのでやりませんでした。
近いうちに、そこまで実現したXcode Source Editor Extensionをリリースしたいなと思いました。