iOSエンジニアならもはや必須になるつつあるfastlaneで自動テストしてみよう

# 概要

こちらの記事はXcodeの自動テストツールであるfastlaneの導入手順に関する手引書になっています。  
元記事はこちらの記事になります。

[fastlane Tutorial: Getting Started](https://www.raywenderlich.com/233168-fastlane-tutorial-getting-started)

こう見るとやはり最初の導入時点での作業はかなりあります。ですが、これだけの作業量でもチーム開発でしている場合にはメリットがかなりあります。そのため大体のアプリの現場ではfastlaneを導入してテストの自動化、アプリのアップロードの自動化を図っています。

なのでもうfastlaneの実装方法は分かりませんでは話しにならないケースが増えてきているためこれを機械にfastlaneを再度見直すためにこちらでまとめて(翻訳)みました。翻訳の許可を頂いてます。

# はじめに

このfastlaneのチュートリアルでは、fastlaneを使用してAppをApp Storeにプロビジョニングや、スクリーンショット作成・構築・アップロードする方法を学びます。

素晴らしい瞬間ですね。数日、数週間、場合によっては数か月もの時間をかけてアプリを作成し、世界にシェアする準備が整いました。あと最後にしなければならないのはApp Storeに開発したアプリを提出することだけです。それはどれほど難しいでしょう？

厄介な仕事の山を手がかりにしましょう：たくさんのスクリーンショットをキャプチャし、あなたのアプリケーションをApple DeveloperとApp Store Connectのサイトに追加し、バイナリとメタデータをアップロードし、そして他の無意味な仕事をします！ あー面倒ですね！

もっと良い方法はありませんか。サポートされているすべての言語で、サポートされているすべてのデバイスですべてのスクリーンショットを自動的に取得する単一のコマンドを実行できさえすればどんなに楽なことか。これらのスクリーンショットをアップロードするためのコマンドが1つしかないなら、アプリをAppleのデベロッパーサイトに追加してすべて送信します。あなたが保存したいと思うすべての時間を考えてください！

さて、幸運なことがあります。作成者の[Felix Krause](https://twitter.com/KrauseFx)とlead maintainerの[Josh Holtz](https://twitter.com/joshdholtz)のおかげで、これ以上のことを行うことができるツールがあります。 これは[fastlaned](https://fastlane.tools/)と呼ばれます。 このチュートリアルでは、fastlaneを使ってApp Storeにアプリをデプロイする方法を学びます。 きっとあなたの新しい親友になるでしょう。 Googleも[2017年に買収して](https://www.adweek.com/digital/google-acquires-twitter-assets-fabric-crashlytics-answers-digits-fastlane/)fastlaneと提携しました。

![default_icon_record.jpg](https://qiita-image-store.s3.amazonaws.com/0/44392/14ea9d59-1f7c-0cca-56eb-870b42f31a33.jpeg)

> このチュートリアルでは、あなたが有料のApple Developerアカウントを持っていること、およびcommand line、Xcode、そしてアプリ送信プロセスについての基本的な知識があることを前提としています。 アカウントを持っていない場合は、[この](https://www.raywenderlich.com/184709/submit-app-apple-no-account-app-store-part-1)チュートリアルが役立ちます。

## Getting Started

まず、このページの上部または下部にある[**Download Materials**](https://koenig-media.raywenderlich.com/uploads/2019/02/mZone_Sample_Project.zip)ボタンを使用してこのチュートリアルの材料をダウンロードしてから、適切な場所に保存します。

このチュートリアルのサンプルアプリ、**mZone Poker**は、ノーリミットテキサスホールデムのトーナメント用のポーカー計算機です。 それはあなたのチップ数と現在のビッグブラインドレベルに基づいて推奨される行動を表示します。

Xcodeで**mZone**プロジェクトを開き、ビルドして実行し、チェックアウトします。

![mzonestarter-278x500.gif](https://qiita-image-store.s3.amazonaws.com/0/44392/8b37700b-077c-566c-513a-b073d3697164.gif)

## Setting Up fastlane

ツールであるfastlaneはRubyスクリプトの集まりなので、正しいバージョンのRubyがインストールされている必要があります。 お使いのOSにはデフォルトでRuby 2.0が付属している可能性がありますが、ターミナルを開いて次のように入力すると、そうであるかどうかを確認できます。

```sh
ruby -v
```

インストールされていない場合、最も簡単な方法は、HomeOSのmacOS用パッケージマネージャの[**Homebrew**](http://brew.sh/)を使うことです。

次のターミナルコマンドを入力して自作をインストールします。

```sh
/usr/bin/ruby -e \
  "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

それから、Rubyをインストールします。

```sh
brew update && brew install ruby
```

`brew link --overwrite ruby`を実行するか、Homebrewから指示された場合は新しいターミナルセッションを開きます。

Xcode Command Line Tools（CLT）も必要です。 確実にインストールするため、「ターミナル」を使います。

```sh
xcode-select --install
```

Xcode CLTがすでにインストールされている場合は、このエラーが発生します。`xcode-select: error: command line tools are already installed, use "Software Update" to install updates`そうでない場合は、プロンプトが表示されたらインストールを続行します。

これでfastlaneをインストールする準備が整いました！ 次のコマンドを入力してください。

```sh
sudo gem install -n /usr/local/bin fastlane --verbose
```

Homebrewを使用したい場合は、次のコマンドを入力してください。

```sh
brew cask install fastlane
```

> El Capitanとともに、OS Xは**Rootless**とも呼ばれる[**System Integrity Protection**](https://support.apple.com/en-us/HT204899)を導入しました。 /usr/local/binはまだ書き込み可能なので、そこにfastlaneをインストールします。

システムパスワードを入力すると、ターミナルにインストールが進行中であることを示す一連のアクティビティが表示されます。 これには数分かかることがあるので、コーヒーを飲んだり、犬の散歩をしたり、ゾンビと戦う戦術を磨いたりして暇を潰してください(笑)。

インストールが完了したら、プロジェクトにfastlaneを設定する準備が整いました。ですが、あなたがそうする前にここにfastlaneツールのハイレベルな外観があります。

## The fastlane Toolchain

その魔法が機能するために、fastlaneは以下のツールのセットをすべて一つのroof下に持ってきます：

- [**produce**](https://github.com/fastlane/fastlane/tree/master/produce)は、App Store ConnectとApple Developer Portalの両方に新しいiOSアプリケーションを作成します。
- [**cert**](https://github.com/fastlane/fastlane/tree/master/cert)はiOSコード署名証明書を自動的に作成して管理します。
- [**sigh**](https://github.com/fastlane/fastlane/tree/master/sigh)は、プロビジョニングプロファイルを作成、更新、ダウンロード、および修復します。
- [**snapshot**](https://github.com/fastlane/fastlane/tree/master/snapshot)はあなたのiOSアプリのローカライズされたスクリーンショットをすべての機器で自動化します。
- [**frameit**](https://github.com/fastlane/fastlane/tree/master/frameit)はあなたのスクリーンショットを正しいデバイスのframeに入れます。
- [**gym**](https://github.com/fastlane/fastlane/tree/master/gym)はあなたのiOSアプリをビルドしてパッケージ化します。
- [**deliver**](https://github.com/fastlane/fastlane/tree/master/deliver)はスクリーンショット、メタデータ、そしてあなたのアプリをApp Storeにアップロードします。
- [**pem**](https://github.com/fastlane/fastlane/tree/master/pem)はあなたのプッシュ通知プロファイルを自動的に生成して更新します。
- [**spaceship**](https://github.com/fastlane/fastlane/tree/master/spaceship)は、AppleデベロッパーセンターとApp Store Connect APIにアクセスできるRubyライブラリです。
- [**pilot**](https://github.com/fastlane/fastlane/tree/master/pilot)はTestFlightの展開を自動化し、ベータテスターを管理します。
- [**boarding**](https://github.com/fastlane/boarding)はベータテスターを招きます。
- [**match**](https://github.com/fastlane/fastlane/tree/master/match)はGitを使ってあなたのチーム全体で証明書とプロビジョニングプロファイルを同期させます。
- [**scan**](https://github.com/fastlane/fastlane/tree/master/scan)はアプリのテストを実行します。

今日はこれらのツールをいくつか使用します。今のところ理論としては十分です。このチュートリアルを実行して、早い段階で作業を開始しましょう。

## Adding fastlane to Your Project

ターミナルを開き、`cd`コマンドでmZone starter projectに移動します。たとえば、デスクトップに**mZone_Sample_Project**フォルダを追加した場合は、次のように入力します。

```sh
cd ~/Desktop/mZone_Sample_Project/mZone
```
mZone starter projectを作業ディレクトリとして設定します。

そして、次のように入力しましょう。

```sh
fastlane init
```

fastlaneを初期化します。

> 「permission denied」というエラーが出た場合は、このコマンドの前に `sudo`を付けてください。

出力後、ファストレーンは「What would you like to use fastlane for?」と尋ねます。

<img width="400" alt="fastlane_init_output.png" src="https://qiita-image-store.s3.amazonaws.com/0/44392/b0687f37-dad5-5658-9aa4-7d98b3c83695.png">

fastlaneでは「recommend[s] automating one task first,」が、この1つのチュートリアルで複数の自動化されたアクションを実装するので手動設定を開始するには**4**を入力します。outputを読み、プロンプトが出されたら**Enter**を押します。

**mZone**フォルダーに戻ると、いくつかの新しいことがわかります。**Gemfile**には、プロジェクト依存関係としてのfastlane gemと、次のものを含むfastlaneフォルダーが含まれています。

- **Appfile** : アプリの識別子、Apple ID、およびfastlaneがアプリを設定するために必要なその他の識別情報を格納します。
- **Fastfile**: fastlaneアクションを呼び出すために作成する**lanes**を管理します。

![fastlane_init_files.jpg](https://qiita-image-store.s3.amazonaws.com/0/44392/e1b9ba26-f956-2605-f48d-259e6854bf4e.jpeg)

選択したテキストエディタで**Fastfile**を開き、テキストエディタでsmart quotesがサポートされている場合はsmart quotesを無効にしてから、ファイルの内容を次のように置き換えます。

Fastfile

```rb
default_platform(:ios)

platform :ios do
# 1
  desc "Create app on Apple Developer and App Store Connect sites"
# 2
  lane :create_app do
# 3
​    produce
  end
end
```

あなたがRubyをこれまで見たことがないなら、これはあなたにとってちんぷんかんぼうに見えるかもしれません。 このコードの動作は次のとおりです。

1. **lane**の説明を入力します。 （laneは連続したタスクのワークフローです）。
2. このレーンに `create_app`という名前を付けます。
3. 開発者ポータルとApp Store Connectの両方にアプリを追加するために**produce**を使用します。

これで、一番最初の**lane**を作成しました。

<img width="500" alt="creature_panda-beachball.png" src="https://qiita-image-store.s3.amazonaws.com/0/44392/6ce0ba65-9b2c-9cd9-0218-d9ae97d4ff91.png">

**Fastfile**を保存してから**Appfile**を開きます。 ポンド記号（＃）を削除して**apple_id**で始まる行のコメントを外し、**[[APPLE_ID]]**を実際のApple IDのユーザー名に置き換えます。 この情報を今すぐ設定することで、fastlaneは後でそれを繰り返し要求する必要がなくなります。

> App Store ConnectとApple Developer Portalのユーザー名が異なる場合は、**apple_id**の行を次のように置き換えます。

> ```rb
apple_dev_portal_id("[[APPLE_DEVELOPER_ACCOUNT_USERNAME]]")
itunes_connect_id("[[APP_STORE_CONNECT_ACCOUNT_USERNAME]]")
```

> 次に、各username placeholderをそれぞれのusernameに置き換えます。

閉じる前に**Appfile**を保存してください。

## Creating Your App

プロジェクトフォルダ内で「Terminal」を開き、次のように入力します。

```sh
fastlane create_app
```

これは作成したばかりの`create_app`laneを走らせます。

このようなものが見えるはずです。

<img width="709" alt="fastlane_create_app.png" src="https://qiita-image-store.s3.amazonaws.com/0/44392/069e820c-dfe0-c41c-98b0-29760497ec11.png">

その出力の先頭で、fastlaneはgemバンドルのコンテキストでfastlaneをより速く起動するために、fastlaneコマンドの前に「bundle exec」を付けることを提案してきます。今後はそうすることができます。

プロンプトが表示されたら、App Store Connectのパスワードを入力します。 デベロッパーポータルに複数のチームがある場合は、**mZone Poker**アプリに使用するチームに対応する番号を入力してください。

最終的には、商品はあなたのアプリのbundle IDを入力するように頼みます。作成する時が来ました。

bundle IDは、App Store Connectでこれまでに使用されたことのある他のすべてのバンドルIDとは異なるものにする必要があります。次の形式を使用して、ユニークなバンドルidentifierを入力してください。

```
com.mZone-Poker.[Insert your email address minus “@” and “.”]
```
(Insert your email address minus “@” and “.” = メールアドレスの逆ドメイン)

<img width="400" alt="create_bundle_id-1.png" src="https://qiita-image-store.s3.amazonaws.com/0/44392/a45c03e7-a3ce-6c34-6af8-b96e7be5f8d0.png">

バンドルIDがすでに取得されている場合は、それを編集してユニークなIDになるまで送信をやり直してください。

次にアプリ名を送信するように求められたら、それもユニークにする必要があります。次の形式を試してください。

```
mZone Poker [Insert your email address minus “@” and “.”]
```

アプリ名は30文字を超えることはできません。必要に応じて切り捨ててください。

App Store Connectアカウントに複数のチームがある場合は使用するチームに対応する番号を入力してください。

Apple Developerアカウントに問題があることを示すエラーが表示された場合（たとえば、新しいプログラム契約に同意する必要がある場合など）、問題を解決してから`produce`をもう一度実行してください。

アプリ名が利用できない場合、プロセスはそこでエラーで終了します。もう一度`produce`を実行し、Apple IDと作成したばかりのBundle IDを再入力してから、クリエイティブマッスルを曲げてユニークなIDを作成するか、この段落の先頭に戻って繰り返します。イライラすることはわかっていますが無限ループを解消できると確信しています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/44392/6ce95f88-fb31-7243-575c-b6a864924db6.png)

Apple Developer CenterとApp Store Connectにログインします。するとあなたのアプリはすでに両方に追加されています。なんてクールなんでしょう。

![apple_dev_and_connect-575x500.png](https://qiita-image-store.s3.amazonaws.com/0/44392/607b7fb7-7933-f54e-06de-2853ff86f187.png)

**Appfile**を再度開き、**app_identifier**で始まる行のコメントを外し、**[[APP_IDENTIFIER]]**を作成したばかりのバンドルIDに置き換えます。

早くチームを選ばなければならなかった場合、lanesを走らせるときに再び入力する必要がないようにチームの名前を追加します。 Developer Portal/App Store Connect team nameを指定するには、以下を追加します。

```rb
team_name ("[[TEAM_NAME]]")
```

[[TEAM_NAME]]をあなたのチームの名前に置き換えます。

## Generating the Deliverfile

ターミナルに戻って、入力しましょう

```sh
bundle exec fastlane deliver
```
fastlaneから「**Do you want to setup deliver?**」と質問された時にはyと入力して答えましょう。
次は「**Would you like to use Swift instead of Ruby?**」と質問されます。このチュートリアルの執筆時点では、iOS開発者としてはおそらくSwiftの方が快適ですが、[**fastlane.swift**](https://docs.fastlane.tools/getting-started/ios/fastlane-swift/)はまだベータ版です。 fastlaneファイルでRubyを使用するには、nを入力します。

<img width="400" alt="fastlane_deliver.png" src="https://qiita-image-store.s3.amazonaws.com/0/44392/7099950f-c0a2-1adc-e972-2cb17ede7449.png">

配信が正常に完了したら、Finderで**mZone/fastlane**に戻ると、新しいことがいくつかわかります。

- **metadata**ディレクトリ。アプリのメタデータの大部分を保持します。
- **Deliverfile**、残りのいくつかのメタデータを保持します。
- **screenshots**ディレクトリ。アプリのスクリーンショットが含まれる。

![metadata_directory-650x183.png](https://qiita-image-store.s3.amazonaws.com/0/44392/2846d726-a7f0-938f-72c1-e2d069646f3f.png)

**metadata**ディレクトリには、説明、キーワード、カテゴリなどの一般的なApp Storeアイテムにちなんで名前が付けられたテキストファイルがたくさんあります。Fastlaneは、これらのファイルを使ってApp Store Connectにアプリのメタデータ情報を送信します。

**en-US/description.txt**を開き、以下を追加します。

```
mZone is a simple poker calculator for No Limit Texas Hold 'Em tournaments that displays a recommended course of action based on your chip count and the current big blind level.
```

**keywords.txt**に追加：

```
Poker, Cards, Gambling
```

**name.txt**にすでにアプリの名前が含まれていることを確認してから、**privacy_url.txt**と**support_url.txt**の両方に`https://www.raywenderlich.com`を追加します。

このアプリはフランス語と英語の両方をサポートしていますが、**en-US**フォルダのみが存在します。これを修正するには、同じディレクトリに**en-US**フォルダのコピーを作成し、**fr-FR**という名前を付けます。 このfastlaneチュートリアルを短くするために、メタデータをフランス語に翻訳する必要はありません…今回はですが。

次に、メタデータフォルダーに：

- **copyright.txt**に `Copyright（c）2019 Razeware LLC`を追加してください。
- **primary_category.txt**に`Game`を追加します。
- **primary_first_sub_category.txt**に`Card`を追加します。
- **primary_second_sub_category.txt**に`Casino`を追加します。

次に、同じフォルダー内で好みのtext/codeエディターを使用して、**app_store_rating_config.json**という名前のJSONファイルを作成します。

```app_store_rating_config.json
{
  "CARTOON_FANTASY_VIOLENCE": 0,
  "REALISTIC_VIOLENCE": 0,
  "PROLONGED_GRAPHIC_SADISTIC_REALISTIC_VIOLENCE": 0,
  "PROFANITY_CRUDE_HUMOR": 0,
  "MATURE_SUGGESTIVE": 0,
  "HORROR": 0,
  "MEDICAL_TREATMENT_INFO": 0,
  "ALCOHOL_TOBACCO_DRUGS": 0,
  "GAMBLING": 2,
  "SEXUAL_CONTENT_NUDITY": 0,
  "GRAPHIC_SEXUAL_CONTENT_NUDITY": 0,
  "UNRESTRICTED_WEB_ACCESS": 0,
  "GAMBLING_CONTESTS": 0
}
```

この評価設定はアプリが「frequent/intense」擬似ギャンブル（つまり、値= 2）を持ち、他のリストされたコンテンツのどれも持っていないことを示します。 このファイルは適切な年齢評価を割り当てるために必要な情報をアップルに提供します。

そして最後に、**review_information**フォルダで、メールアドレスを**email_address.txt**に、名前を**first_name.txt**に、姓を**last_name.txt**に、電話番号を**phone_number.txt**にそれぞれ追加します。電話番号の前に「+」と国コードを続けます。たとえば+44 844 209 0611と言ったように。

おめでとうございます。 送信に必要なすべてのメタデータを追加しました。

> [ここ](https://docs.fastlane.tools/actions/deliver/#more-options)にメタデータオプションとDeliverfile設定の完全なリストがあります。

## Automating Screenshots

スクリーンショットを撮るのは面倒です。アプリがサポートするデバイスと言語が多ければ多いほど、書き込み時間は長くなります。辛いですね！

**mZone Poker**は2つの言語と2つのiPhoneのアスペクト比をサポートしています。 あなたがそれぞれの言語とスクリーンのアスペクト比のためにデバイスごとに5つのスクリーンショットを撮らなければならなかったならば、それは20枚のスクリーンショットになるでしょう！ただし、fastlaneを使用すると、単一のコマンドを実行することでこれをすべて実行できます。

「Terminal」に入力して、スナップショット用にプロジェクトを設定します。

```terminal
fastlane snapshot init
```

**Snapfile**ファイルが**fastlane**フォルダに表示されます。それを開きファイルの内容を次のファイルで置き換えます。

```rb:Snapfile.txt
# 1 - A list of devices you want to take the screenshots from
devices([
  "iPhone 8 Plus",
  "iPhone SE"
])

# 2 - A list of supported languages

languages([
  'en-US',
  'fr-FR'
])

# 3 - The name of the scheme which contains the UI Tests

scheme("mZone Poker UITests")

# 4 - Where should the resulting screenshots be stored?

output_directory "./fastlane/screenshots"

# 5 - Clears previous screenshots

clear_previous_screenshots(true)
```

ここでは次のように指定します。

1. fastlaneにスクリーンショットを取り込ませたいデバイス。
2. あなたがキャプチャーしたローカライズ言語。
3. スクリーンショットの自動化を実行するためにすぐに作成するXcodeスキームの名前。
4. スクリーンショットの出力ディレクトリ。
5. そのfastlaneは新しいものをキャプチャする前に出力ディレクトリ内のすべてのスクリーンショットを消去する必要があります。

閉じる前にファイルを保存してください。

ターミナルに戻って`fastlane snapshot init`を実行した後に現れた指示に注意してください：

<img width="571" alt="fastlane_snapshot_init.png" src="https://qiita-image-store.s3.amazonaws.com/0/44392/7eebf951-d64e-e5a2-ab0d-3857241be43e.png">

それがあなたが次にすることです。

## Creating a Test Target

Xcodeで**mZone Poker.xcodeproj**を開き、次に**File▸New▸Target**に移動します。**iOS**タブの**Test**セクションで、**iOS UI Testing Bundle**を選択してから**Next**をクリックします。

<img width="400" alt="create_uitest_target.png" src="https://qiita-image-store.s3.amazonaws.com/0/44392/033343d3-e24a-59cc-3978-a402555654c7.png">

**Product Name**フィールドに**mZone Poker UITests**と入力し、**Finish**をクリックします。

<img width="400" alt="create_uitest_target_2.png" src="https://qiita-image-store.s3.amazonaws.com/0/44392/3cc2018c-ec8c-68b8-6c93-58de568ce44a.png">

**mZone Poker UITests**フォルダーがXcodeの左側のナビゲーターメニューに表示されます。

targetの全般ページに移動します。**mZone Poker** targetの下には、mZone Poker UIテストは表示されません。**mZone Poker UITests**を選択し、**Signing for “mZone Poker UITests” requires a development team**というエラーが表示された場合は、チームを選択してください。

![test_target_general-1-650x255.png](https://qiita-image-store.s3.amazonaws.com/0/44392/64e2600b-9b73-29f7-2d03-3c4f8de634a2.png)

**fastlane**のディレクトリに戻り、**SnapshotHelper.swift**をXcodeのプロジェクトナビゲータの**mZone Poker UITests**フォルダの下にドラッグします。**Choose options for adding these files**ウィンドウが表示されたら、次のように選択します。

- **Copy items if needed.**
- **Create groups.**
- **mZone Poker UITests.**

**Finish**をクリックする前に、**mZone Poker** targetの選択を解除してください。

<img width="400" alt="add_snapshot_helper.png" src="https://qiita-image-store.s3.amazonaws.com/0/44392/86889609-88f3-416d-8faf-b1c3d8966c1a.png">

次に、**mZone Poker UITests**で**mZone_Poker_UITests.swift**を開きます。`setUp（）`と`tearDown（）`の両方を削除してから、`testExample（）`の内容を次のように置き換えます。

```mZone_Poker_UITests.swift
// 1
let app = XCUIApplication()
setupSnapshot(app)
app.launch()
// 2
let chipCountTextField = app.textFields["chip count"]
chipCountTextField.tap()
chipCountTextField.typeText("10")
// 3
let bigBlindTextField = app.textFields["big blind"]
bigBlindTextField.tap()
bigBlindTextField.typeText("100")
// 4
snapshot("01UserEntries")    
// 5
app.buttons["what should i do"].tap()
snapshot("02Suggestion")   
```

このコードの動作は次のとおりです。

1. スナップショットを撮るための設定をして、アプリを起動します。
2. **chip Count**テキストフィールド（ストーリーボードでaccessibility identifierが「chip count」に事前設定されていることを確認する事）をタップし、そのフィールドに10を入力します。
3. **Big Blind**テキストフィールドをタップして100を入力します。
4. スナップショットを作成してアプリがuser entriesをどのように表示するかを示します。
5. **What Should I Do?**をタップします。ボタンを押すと、別のスクリーンショットが表示され、警告が表示されます。

> テキサスホールデムにはプレイヤーの位置によってボタン・ザガン・SB・BBと言ったポジションがあります。Big Blind(ビッグブラインド)というのはそのポジションをさしています。

次に、**mZone Poker UITests**スキームを作成するには、実行ボタンと停止ボタンのすぐ右にあるボタンをクリックして、**Manage Schemes**…を選択します。fastlaneのアクセスを許可するには、**mZone Poker UITests**の横にある**Show**と両方のターゲットの横にある[Shared]を選択します。 次に、**mZone Poker UITests**の行と**Edit**をクリックします。

> スキームが表示されない場合は、" + "をクリックして**Target**ドロップダウンから**mZone Poker UITests**を選択します。

<img width="400" alt="manage_schemes.png" src="https://qiita-image-store.s3.amazonaws.com/0/44392/88574cef-4e49-2b56-cf38-730ea853def4.png">

スキームエディタの左側のメニューで**Build**をクリックします。 次に、**mZone Poker UITests**ターゲットの横にある**Test**と**Run**オプションを選択してから**Close**をクリックして変更を保存します。

<img width="400" alt="edit_test_scheme_2.png" src="https://qiita-image-store.s3.amazonaws.com/0/44392/53a88c0e-b9c5-d726-cc76-349cd28099c0.png">

Xcodeのままにして**Fastfile**を開き、`create_app`laneの下に次の行を追加します。

```rb:Fastfile.txt
  desc "Take screenshots"
  lane :screenshot do
    snapshot
  end
```

この`screenshot`laneは、**Snapfile**の設定に従ってスクリーンショットを撮るためにスナップショットを使用します。

**Fastfile**を保存し、ターミナルに戻って次のように入力します。

```sh
bundle exec fastlane screenshot
```

今、みてください…スクリーンショットは、あなたが特に何もせずともキャプチャされています！不気味な仕事をスキップする喜びに浸ってください。

スナップショットが完了すると、スクリーンショットのHTMLプレビューが自動的に開きます。

![screenshot_html-1-483x500.png](https://qiita-image-store.s3.amazonaws.com/0/44392/a889a828-7311-2973-0336-b014c7c47d82.png)

> **snapshot**は**Snapfile**にリストされているシミュレータにアクセスする必要があります。そのリストから1つもデバイスが見つからない場合は、**Window**▸**Devices**の順に選択して、それらをXcodeに追加してください。 次に、+ をクリックして新しいシミュレータを追加します。

> あいまいなシミュレータ名に関する警告が表示された場合は、重複するシミュレータを削除するか、**Snapfile**内の名前と一致するようにシミュレータ名を変更する必要があります。

たった1つのコマンドで、すべてのデバイスのスクリーンショットを英語とフランス語の両方で作成できます - 因みにそれ以上うまくいきません。

## Creating the IPA File

アプリを構築してアップロードすることも時間のかかるプロセスです。 fastlaneが**gym**のツールを使ってこれを実現できるのです。

> Xcodeの**mZone Poker**ターゲットにbundle identifierとsigning identityを設定していることを確認してください。

ターミナルで以下を実行します。

```sh
fastlane gym init
```

**するとGymfile**が作成されます。

**Gymfile**を開き、その内容を次のファイルで置き換えます。

```rb:Gymfile.txt
# 1
scheme("mZone Poker")
# 2
output_directory("./fastlane/builds")
# 3
include_bitcode(false)
# 4
include_symbols(false)
#5
export_xcargs("-allowProvisioningUpdates")
```

このコードは以下のことをしています。

1. mZone Pokerのschemeを指定します。
2. fastlaneが.ipaアプリのバイナリファイルを保存する場所を指定します。
3. ビルドからBitcodeを除外します。Bitcodeを使用すると、Appleはあなたのアプリを最適化することができますが、今はビルドをスピードアップするためにそれを除外します。
4. ビルドからsymbolsを除外します。symbolsを含めると、Appleはアプリのデバッグ情報にアクセスできるようになりますが、今はビルドをスピードアップするために除外します。
5. Xcodeが自動プロビジョニングを使用できるようにします。

**Fastfile**を開き、screenshotのlaneの下に以下を追加します。

```rb:Fastfile.txt
  desc "Create ipa"
  lane :build do
    # 1
    enable_automatic_code_signing
    # 2
    increment_build_number
    # 3
    gym
  end
```

これは**build**laneです：

1. Xcodeで自動プロビジョニングを有効にします。
2. ビルド番号を1つ増やします（各ビルド番号はApp Store Connectのアップロード要件ごとにユニークです）。
3. 署名付き**.ipa**ファイルを作成します。

**Fastfile**を保存してから、ターミナルでビルドを実行します。

```sh
bundle exec fastlane build
```

fastlaneからcertificatesにアクセスするためにkeychainのパスワードを入力するように求められた場合は、入力してください。同じ許可を繰り返し付与したくない場合は、**Allow Always**を選択します。 ビルドが正常に完了すると、署名された**.ipa**が**fastlane/build**に表示されます。

<img width="611" alt="ipa_directory.png" src="https://qiita-image-store.s3.amazonaws.com/0/44392/9f057742-5d9b-adc4-af74-abc49acfa6a3.png">


## Uploading to App Store Connect

スクリーンショット、メタデータ、および.ipaファイルをApp Store Connectにアップロードするには、**deliver**を使用します。

まず、**Deliverfile**の内容を次のように置き換えます。

```rb:Deliverfile.txt
# 1
price_tier(0)
# 2
submission_information({
    export_compliance_encryption_updated: false,
    export_compliance_uses_encryption: false,
    content_rights_contains_third_party_content: false,
    add_id_info_uses_idfa: false
})
# 3
app_rating_config_path("./fastlane/metadata/app_store_rating_config.json")
# 4
ipa("./fastlane/builds/mZone Poker.ipa”)
# 5
submit_for_review(true)
# 6
automatic_release(false)
```

ここでは、

1. 価格帯を0に設定します。これは無料アプリです。
2. レビューのために手動で送信する際にAppleがあなたに提示する質問に答えてください。
3. アプリ評価設定の場所を指定します。
4. .ipaファイルの場所を指定します。
5. 審査のためにアプリを自動的に送信するには、`submit_for_review`を`true`に設定します。
6. `automatic_release`を`false`に設定すると、アプリの審査で承認された後にアプリを手動でリリースする必要があります。

**Fastfile**を開きます。`build`laneの後に、次を追加してください。

```rb:Fastfile.txt
  desc "Upload to App Store"
  lane :upload do
    deliver
  end
```

次に、fastlaneでメタデータのプレビューを作成するには、Terminalを開いて次のコマンドを実行します。

```sh
bundle exec fastlane upload
```
すべて問題なければ、Terminalにyと入力して承認します。

laneが完成したら、App Store Connectにログインします。スクリーンショット、メタデータ、およびビルドがあるはずです。レビューを待ってください。

<img width="400" alt="waiting_for_review.png" src="https://qiita-image-store.s3.amazonaws.com/0/44392/16d56c28-3eea-a462-92b7-6e11c3901c50.png">

## Putting It All Together

アプリの作成、スクリーンショットの作成・構築・アップロードのためのlaneが別々に用意されました。それらを1つずつ呼び出すことはできますがあまりしたくないですね。

本当は、、、あなたはすべてを1つのコマンドでしたいはずです。

**Fastfile**を開きます。`upload`laneの後に、以下を追加します。

```rb
  desc "Create app, take screenshots, build and upload to App Store"
  lane :do_everything do
    create_app
    screenshot
    build
    upload
  end
```

すると`do_everything`がすべての面倒をみてくれます。

さらに、laneを完全にハンズフリーにするには、**Deliverfile**を開き最後に以下を追加します。

```rb:Deliverfile.txt
force(true)
```

これによりfastlaneはスクリーンショットとメタデータの承認をスキップします。

そしてfastlaneにすべての重い作業をやらせるには次のコマンドを実行します。

```sh
bundle exec fastlane do_everything
```


## Supporting Multiple Targets

**mZone_Sample_Project**の**Multiple_Targets**フォルダーを参照してください。Xcodeで**Multiple_Targets/mZone-2/mZone Poker.xcodeproj**を開きます。 **mZone Poker Pro と mZone Poker Pro UITest**という2つの新しいtargetを除いて、このプロジェクトは最初のプロジェクトとよく似ているはずです。

実行中のmZone PokerとmZone Poker Proを切り替えるには、RunボタンとStopボタンのすぐ右側にあるボタンをクリックしてから、実行するアプリのスキームを選択します。

<img width="339" alt="switch_schemes.png" src="https://qiita-image-store.s3.amazonaws.com/0/44392/e7a07b66-05c2-dd60-7c50-36bdf65d6a53.png">

mZone Poker Proをビルドして実行します。 これはmZone Pokerとほぼ同じですが、より詳細な提案を返します。

![mZone_and_mZone_Pro.gif](https://qiita-image-store.s3.amazonaws.com/0/44392/baad2c83-d5e8-b52f-ac8b-3c86292b365b.gif)

Generalページで、mZone PokerのバンドルIDを以前に作成したものに設定します。

それから、mZone Poker Proの仮の新しいバンドルIDを設定します。 例えば：

```
com.mZone-Poker-Pro.[Insert your email address minus “@”  and “.”]
```

それでは、Finderに戻ってください。**Gemfile**と**fastlane**ディレクトリを**mZone**から**mZone-2**にコピーして貼り付けます。次に**mZone-2/fastlane/SnapshotHelper.swift**を新しいプロジェクトにドラッグします。**Choose options for adding these files**のウィンドウが表示されたら、以下を選択します。

- **Copy items if needed.**
- **Create groups.**
- **mZone Poker UITests.**
- **mZone Poker Pro UITests.**

それから、**Finish**をクリックします。

<img width="300" alt="add_snapshot_helper-multiple_targets (1).png" src="https://qiita-image-store.s3.amazonaws.com/0/44392/96fc1407-55a6-fbb7-e96d-2d96a433fd4f.png">




## Setting Up Multiple Environments

環境（**.env**）ファイルには、実行中にアプリがさまざまにアクセスできる構成設定が含まれています。このプロジェクトでは、2つの環境を作成します。各アプリケーションターゲットに対して1つずつです。

お気に入りのテキストエディタを開き、smart quotesを無効にして次のように入力します。

```.env
SCHEME = "mZone Poker"
TEST_SCHEME = "mZone Poker UITests"
BUNDLE_IDENTIFIER = "[[YOUR UNIQUE BUNDLE IDENTIFIER]]"
APP_NAME = "[[YOUR UNIQUE APP NAME]]"
```

この環境は、mZone Pokerの環境スキーム、テストスキーム、バンドルID、およびアプリ名を保持しています。 [[YOUR UNIQUE BUNDLE IDENTIFIER]]をmZone PokerのバンドルIDに置き換え、[[YOUR UNIQUE APP NAME]]をアプリケーションのユニークな名前に置き換えます。

ファイルを**.env.mZone_Poker**として**mZone-2/fastlane**に保存します（ファイル拡張子は付けません）。デフォルトでは.env変数が隠しファイルになっているので、Finderで.env.mZone_Pokerが表示されない場合は、**Shiftキー+Commandキー**を押しながらFinderで隠しファイルを表示します。

同様に、次のものを含む2番目のファイルを作成します。

```ini:.env
SCHEME = "mZone Poker Pro"
TEST_SCHEME = "mZone Poker Pro UITests"
BUNDLE_IDENTIFIER = "[[YOUR UNIQUE BUNDLE IDENTIFIER]]"
APP_NAME = "[[YOUR UNIQUE APP NAME]]"
```

[[YOUR UNIQUE BUNDLE IDENTIFIER]]に**mZone Poker Pro**の現在のバンドルIDを置き換えてください。 次に、仮のユニークのアプリ名を作成します。

```text
mZone Poker Pro [Insert your email address minus “@”  and “.”]
```

アプリ名は30文字を超えることはできないため、必要に応じて切り捨ててください。

同じディレクトリに**.env.mZone_Poker_Pro**としてファイルを保存します。

これで、スキームを切り替えるときに変数を使用して現在の設定にアクセスできるようになります。

まず第一に、**Appfile**を開き、app_identifier行のコメントを外して、次のように置き換えます。

```rb:Appfile.txt
app_identifier("[[APP_IDENTIFIER]]")
```
を

```rb:Appfile.txt
app_identifier(ENV['BUNDLE_IDENTIFIER'])
```
に。

“ENV['BUNDLE_IDENTIFIER']”は、あなたが現在の環境に設定した方からバンドルIDを取得するようにfastlaneに指示します。

**Deliverfile**で.ipa行を次のように置き換えます。

```rb:Deliverfile.txt
ipa("./fastlane/builds/#{ENV['APP_NAME']}.ipa")
```

**Gymfile**で、scheme行を次のように置き換えます。

```rb:Gymfile.txt
scheme(ENV['SCHEME'])
```

**Snapfile**で、schemeとoutput_directoryの行を次のように置き換えます。

```rb:Snapfile.txt
scheme(ENV['TEST_SCHEME'])
```
の部分と

```rb:Snapfile.txt
output_directory "./fastlane/screenshots/#{ENV['SCHEME']}"
```

ですね。

それぞれ。

最後に、新しい**metadata**ディレクトリに戻ります。すべてのコンテンツを選択して、それらを**mZone Poker**という名前の新しいフォルダーに配置します。

<img width="400" alt="duplicate_metadata_1.png" src="https://qiita-image-store.s3.amazonaws.com/0/44392/3d52e479-a806-5578-7496-ca79a86b9191.png">

それからそのフォルダを複製しその複製に**mZone Poker Pro**と名付けます。


<img width="400" alt="duplicate_metadata_2.png" src="https://qiita-image-store.s3.amazonaws.com/0/44392/e6dc28d1-8689-3819-c286-b62c83ffdb98.png">


**mZone Poker Pro/ja-jp/name.txt** と **mZone Poker Pro/fr-FR/name.txt**の内容を新しいアプリの名前に変更します。簡単にするために、他のすべてのメタデータは今のところ同じにしておきます。

2番目のtargetに対してすべてのコマンドを実行するには次のように入力します。

```sh
bundle exec fastlane do_everything --env mZone_Poker_Pro
```

これは、**.env.mZone_Poker_Pro**の変数を使用して`do_everything`を実行します。

しかし、すべてのtargetに対してすべてのコマンドを一度に実行したい場合はどうなりますか？

**Fastfile**を開きます。 `do_everything`の下に、以下を追加します。

```rb:Fastfile.txt
  def execute_for_all_envs
    # 1
    schemeList = Dir.glob(".env.*”)
    # 2
    schemeList.each do |file|
      # 3
      Dotenv.overload(file)
      # 4
      yield
    end
  end
```

このメソッドは、

1. 現在のディレクトリの **.env.ファイルを配列に入れます**。
2. 各.envファイルをループします。
3. 現在の.envファイルで`ENV`をoverloadします。
4. `execute_for_all_envs`の呼び出しに続いてブロックを実行します。

次に、`do_everything`から`execute_for_all_envs`を呼び出すには、`do_everything`の内容を次のように置き換えます。

```rb:Fastfile.txt
    if ENV['SCHEME'] != nil
      create_app
      screenshot
      build
      upload
    else
      execute_for_all_envs{ do_everything }
    end
```

ここでコマンドラインで環境を指定しないと、ENV ['SCHEME'] == nilが実行され、`execute_for_all_envs`が実行されます。`execute_for_all_envs`はENVを最初の環境に設定し、呼び出し側ブロックに戻ります。その後、呼び出し側ブロックは`do_everything`を再実行します。

`do_everything`がその環境のすべてを実行した後、`execute_for_all_envs`内のループが続行され、次の環境に戻ります。

以上です。

これで実行できます。

```sh
bundle exec fastlane do_everything
```

あなたが座ってリラックスしている間にfastlaneが両方のtargetにすべての重い処理をします。

注意：fastlane実装前と比較して、あなたに長い時間を費やしてしまうことは奇妙に感じるかもしれませんが、私たちを信頼してください。