iOS界隈の新手のテスティングフレームワークQuickをCocoaPods的なもので導入して満足して死ぬまでの記録

これまでのあらすじ

ひょんなことがきっかけで『iOSアプリ テスト自動化入門』を読みました。今年の3月20日くらいに出版された比較的新しい本なのですが、その直後にSwiftの出現とか冷戦の影響とかのせいでユニットテストを取り巻く状況は急速に変化してしまったようです。

同書の中で、ユニットテストにおけるフレームワークとしてXCTestGHUnitKiwiの3つが紹介されていましたが、そんな最中(さなか)に新手のQuickが颯爽と登場まーた新しいものつくって…


Swift界隈で話題沸騰中のテストフレームワーク Quick とは? - Qiita


[Swift] Quick で始める振る舞いテスト入門 #1 インストール | Developers.IO

序文

ところで話は変わりますが、昨日は朔旦冬至(さくたんとうじ)といって新しいことを始めるのにぴったりの日だったそうです。

なんか1日遅れているような気がしますが、ときには新しいこともしたいですしQuickにちょっと触ってみます。ちょっと触るだけだから

ちなみに上記記事では「QuickはCocoaPodsからインストールできない」と書いてありますが、一応公式に「How to install Quick using beta CocoaPods」という情報がある通り、やってやれないことはないようです。

そんなわけで、今回はQuickをCocoaPods経由でプロジェクトに導入するまでの話を備忘録的に書いていきます。ところどころ躓きました。後半適当になります。

なお使用したXcodeのバージョンは6.1.1です。CocoaPodsのバージョンは0.35.0です。

プロジェクトの作成

まずXcodeを起動して、適当にプロジェクトを作ります。

今回はテスティングフレームワークを動かすことだけが目的で、べつにアプリを作りたいわけではないので、プロジェクトの種類はなんでもよいと思います。ちなみに僕はiOSのSingle View Applicationを選択し、プロジェクトを「Sample1223」と名付けました。

Bundlerの導入

せっかくですが、ここで一旦 Xcodeを終了させます

How to install Quick using beta CocoaPods」にとりあえずBundlerを入れろって書いてあったのでおとなしく入れます。

Bundlerってなんだろう。Rubyerの言うことは分からん


Ruby - ツールを使いたいだけの人のための bundler 入門 (例: vagrant + veewee) - Qiita

ターミナルを起動して、gem installコマンドを打ちます。

bash
$ sudo gem install bundler

あ、sudo*1で実行しないと下記のようなエラーが出てしまうことがあります。

ERROR:  While executing gem ... (Gem::FilePermissionError)
    You don't have write permissions for the /Library/Ruby/Gems/2.0.0 directory.

Gemfileの作成

続いて、.xcodeprojのあるディレクトリまでcdで移動し、Gemfileを作ります*2。以後、特に断りがない限りはこのディレクトリで作業を行うものとします。

bash
$ vi Gemfile

Gemfileの中身は、「How to install Quick using beta CocoaPods」で書けと言われた通りに書いています。

Gemfile
source 'https://rubygems.org'

gem 'cocoapods', :git => 'https://github.com/CocoaPods/CocoaPods.git', :branch => 'swift'
gem 'cocoapods-core', :git => 'https://github.com/CocoaPods/Core.git'
gem 'xcodeproj',  :git => 'https://github.com/CocoaPods/Xcodeproj.git'
gem 'claide', :git => 'https://github.com/CocoaPods/CLAide.git'

gemインストール

bash
$ sudo bundle install

下記のメッセージが表示されたら成功。

Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.

Podfileの作成

続いて、NimbleとQuickを取得するようPodfileに書いてやります。このPodfileも、.xcodeprojのあるディレクトリに作ります。

bash
$ vi Podfile
Podfile
platform :ios, "8.0"

source 'https://github.com/CocoaPods/Specs.git'

pod 'Nimble', :git => "https://github.com/Quick/Nimble"
pod 'Quick', :git => 'https://github.com/Quick/Quick', :tag => 'v0.2.1'

あとはEscからの:wq!で上書き終了して、以下のコマンドを打つだけでOK。

bash
$ bundle exec pod install

実験、そしてまさかのエラー

Finderで.xcodeprojのあるディレクトリに行き、Xcode拡張子が.xcworkspaceの方を開きます。

Xcodeが勝手に作ったテスト用のソースSample1223Tests.swiftを以下のように書き換えてみました。

import Quick

class Sample1223Tests: QuickSpec {
}

すると、1行目のimportでまさかのエラー。「No such module 'Quick'」と怒られてしまいました。

f:id:tercel_s:20141223115025p:plain

どうやら、テストコードからCocoaPodsで追加したライブラリをうまく参照できていないようです。

参照の設定

設定手順は以下の画像を参照してください(手抜き)。

f:id:tercel_s:20141223115224p:plain

これで、「No such module 'Quick'」エラーが消えました! わはー

テストコードを書いてみる

というわけで、Developers.ioのこの記事から丸ごとパクった以下のコードで実験してみます。

import Quick
import Nimble

class Sample1223Tests : QuickSpec {
    override func spec() {
        it("is equal") {
            let value = 2 + 3
            expect(value).to(equal(5))
        }
    }
}

Command+uで無事にテストができました。
f:id:tercel_s:20141223193041p:plain
めでたし。

と見せかけて、まだまだ続くよ

今回導入するQuickとNimbleはテストでしか使わないライブラリなので、Podfileを書き換えてSample1223Tests以外のビルドターゲットからはQuickやNimbleを呼べなくしてやります。targetに「Sample1223Tests」を指定するだけです。

Podfile
platform :ios, "8.0"

target :Sample1223Tests, :exclusive => true do
        source 'https://github.com/CocoaPods/Specs.git'

        pod 'Nimble', :git => "https://github.com/Quick/Nimble"
        pod 'Quick', :git => 'https://github.com/Quick/Quick', :tag => 'v0.2.1'
end
bash
$ bundle exec pod update

ところが、Podfileを修正してCommand+uしたらまたしても謎のエラーが発生しました。

f:id:tercel_s:20141223182220p:plain

なんだこれは。

リンカエラーはさておき、まずはシェルスクリプト起動エラーからなんとかせねば。と思っていたら、GitHubで「diff: /../Podfile.lock: No such file or directory · Issue #2303 · CocoaPods/CocoaPods · GitHub」といういかにも関係ありそうな議論を見つけました。


diff: /../Podfile.lock: No such file or directory · Issue #2303 · CocoaPods/CocoaPods · GitHub

結局これを読んだところでなにひとつ解決しなかったわけですが。

試行錯誤

おそらく、target指定を行わないライブラリが1つ以上ないと、プロジェクトがConfiguration Fileを参照できなくてビルド時にコケるんじゃないか……とあたりをつけました。真偽のほどは分かりません。

f:id:tercel_s:20141223191738p:plain

そこで試しに、Podfileにtarget指定なしでAFNetworking を追加してみます(べつにAFNetworkingでなくてもよいのですが、定番中の定番なのでとりあえず)。

Podfile
platform :ios, "8.0"

pod 'AFNetworking'

target :Sample1223Tests, :exclusive => true do
        source 'https://github.com/CocoaPods/Specs.git'
        pod 'Nimble', :git => "https://github.com/Quick/Nimble"
        pod 'Quick', :git => 'https://github.com/Quick/Quick', :tag => 'v0.2.1'
end

pod updateを実行。

bash
$ bundle exec pod update

そして再度プロジェクトを開き、Configurationの設定を確認。プロジェクトと各ビルドターゲットに対して、Based on Configuration Fileを以下のように設定してCommand+u

f:id:tercel_s:20141223192245p:plain

シェル起動エラーがリンカエラーを道連れにして消えてくれました。
f:id:tercel_s:20141223193440p:plain
今度こそ本当にめでたし。

とはいえば、要りもしないライブラリ(今回はAFNetworking)が導入されてしまうのはあまり気持ちのよいものではありませんな。

実際に何か作るときには、何かしら一つはライブラリを入れるだろうから特に気にすることはないのかもしれませんが…。

まとめ

  • Quickは一応CocoaPodsでインストールできる
  • xUnit ぽくないから慣れるの大変そう
  • CocoaPodsの挙動がいまいちわからない
  • クリスマスが今年もやってくる*3
  • ヒメはヒメなのヒメなのだ*4

*1:root権限。

*2:Gemfileをどこに作ってよいのかわからなかったのでとりあえずプロジェクトのルートっぽいところに作りました。流儀として間違っていたらごめんなさい。

*3:ケンタッキーフライドチキンのCMソング。聞くと鬱になる。

*4:弱虫ペダルの主人公・小野田坂道が好きなアニメの主題歌。劇中では小野田が入学した時点で既に彼のiPodに収録されていたが、季節が変わってインターハイ終了後の秋葉原でもまだ店頭でCDが平積みされているなど異様なまでのロングセラーを誇っている。

Copyright (c) 2012 @tercel_s, @iTercel, @pi_cro_s.