朝専用SNS「朝の実」では、TestFlight でテスト配布を始めるタイミングで、AsanomiTests を実行する最小限の CI も入れました。
この記事では、TestFlight と CI をそれぞれ簡単に整理したうえで、朝の実で実際に入れた内容をまとめます。
1. TestFlightとは
TestFlight は、公開前のアプリを実機へ配布し、テスターからのフィードバックを集めるための Apple の仕組みです。
App Store に公開する前に、配布、インストール、フィードバック収集までを Apple の導線の中で完結できます。
TestFlight には内部テストと外部テストがあり、配布方法が少し違います。
内部テストでは、テスターはApp Store Connect の登録が必要です。
一方、外部テストでは、テスターは「TestFlight アプリ」がダウンロードしてあればOKです。
ただし、外部テスターに配る場合は、ビルドを AppleのReview に通さなければなりません。
内部テスターは最大 100人、外部テスターは最大 10,000人 まで追加でき、ビルド後は 90日間 テストできます。
現在、朝の実では内部テストのみで自分が実機テストを行なっています。以下、TestFlight のメリットをまとめます。
- 実機で公開前ビルドを配れる
- App Store Connect 上でテスター管理ができる
- フィードバックやスクリーンショットをApple の導線で回収できる(テスター負荷 小)
2. TestFlightの導入方法
ここでは、TestFlight の詳しい導入手順を1つずつ説明するのではなく、全体の流れだけに絞ります。
TestFlight の導入は、大きく 3ステップ です。
App Store Connect > TestFlightでテスト情報を入力する
テスターに見せる基本情報を入れます。- Xcode からビルドをアップロードする
ビルドが App Store Connect 側で処理されると、TestFlight で選べるようになります。 - テスターグループを作り、ビルドを割り当てる
内部テスターや外部テスターを追加し、そのグループへビルドを配布します。
3. TestFlightのフィードバック機能
TestFlight の良いところは、配るだけで終わらず、フィードバックの回収までつながっていることです。
テスターは TestFlight アプリからコメントやスクリーンショットを送れます。
特に便利なのが スクリーンショットフィードバック です。
テスターはアプリを使っている最中に、いつも通りスクリーンショットを撮るだけで、その画面に対するフィードバックを送れます。専用の報告フォームを探したり、あとから状況を文章で説明し直したりしなくてよいのが便利です。
開発側では、App Store Connect の スクリーンショットフィードバック 画面から、どの画面で何が起きたのかを画像つきで見返せます。
「なんとなく使いにくい」ではなく、「この画面でここが気になる」という粒度で整理しやすいのが良いところです。
朝の実でも、投稿画面やホーム画面に対するフィードバックをこの画面で確認しています。
実機で使ったときの違和感や文言の分かりづらさは、こうした画面付きフィードバックが追いやすいです。
4. CIとは
CI は Continuous Integration(継続的な統合) の略で、ざっくり言えば「コード変更のたびに、ビルドやテストを自動で回す仕組み」です。
以下、CIで行う処理の例です。(これ以外にもやれることはたくさんあります)
- ビルド
- Lint
- Format チェック
- Unit Test
- UI Test
CI では、繰り返し確認する機械的なチェックを自動化します。
たとえば「ビルドが通るか」「テストが落ちていないか」「コードの書き方が一定のルールに沿っているか」を、PR作成時やブランチへのpush時に毎回同じ条件で確認できます。
これにより、人が確認する範囲を減らして、一定の品質を安定して確保できます。
5. CIの導入方法
朝の実では、GitHub Actions で CI を入れています。
最初にやったのは次の3つです。
- CI で使う scheme を決める
.github/workflows/ci.ymlを作る- push や PR で
xcodebuild testが動くことを確認する
ここから、それぞれを少し詳しく見ていきます。
1. CIで使うschemeを Shared にする
ここでいう scheme は、Xcode のビルドやテストの実行設定です。
Xcode では、どのアプリをビルドするか、どのテストを実行するかを scheme にまとめて管理します。
CI 用の scheme は Xcode 上で Shared にします。
Shared にした scheme は GitHub で管理されるため、GitHub Actions から参照できるようになります。
(以下の設定画面は、Xcode画面中央上部のアプリ名(scheme名)の部分を押下すると出てきます)

2. .github/workflows/ci.ymlを作る
.github/workflows/ci.yml は、GitHub Actions に「いつ」「どの環境で」「どのコマンドを実行するか」を伝える設定ファイルです。
リポジトリ内の決まった場所にこのファイルを置くと、GitHub が workflow として読み取ってくれます。
GitHub Actions の workflow は YAML で書きます。
今の朝の実では、develop, main への PR と、develop, main への push で走る設定にしています。
※ ci.yml の実際の内容は 「6. 朝の実で使用しているCIの内容」で公開してます。
3. pushやPRでxcodebuild testが動くことを確認する
設定を書いたら、実際に対象ブランチへ push するか、PR を作成して GitHub Actions が起動することを確認します。
朝の実では、GitHub Actions 上で xcodebuild test が実行され、その結果を GitHub の Actions 画面で確認できる状態にしました。

この CI はローカルの simulator を使うのではなく、GitHub Actions の macOS runner 上で動きます。
つまり、ネット上の macOS 環境でビルドし、その runner 上の iOS Simulator でテストしている形です。
6. 朝の実で使用しているCIの内容
朝の実で今使っている CI は、かなり最小限です。
対象は AsanomiTests の実行で、UI Test、lint、Format チェック、TestFlight 配布の自動化まではまだ入れていません。
name: CI
on:
# main/develop 向けの PR で実行
pull_request:
branches: [main, develop]
# main/develop ブランチへの push で実行
push:
branches: [main, develop]
jobs:
build-test:
# Xcode が使える macOS runner
runs-on: macos-15
# 何かが固まったときに CI が待ち続けないよう、最大実行時間を決めておく
timeout-minutes: 30
env:
# ビルド対象の Xcode プロジェクト
XCODE_PROJECT: Asanomi.xcodeproj
# CI で使う scheme
XCODE_SCHEME: Asanomi-CI
# CI では simulator 向けに deployment target を明示する
CI_IOS_DEPLOYMENT_TARGET: "18.5"
steps:
# GitHub Actions の runner に、このリポジトリのコードを取得する
- uses: actions/checkout@v6
# Unit Test を実行する
# xcodebuild test は、テスト前に必要なビルドもまとめて実行してくれる
- name: Unit Tests
run: |
# 指定した project / scheme を、指定 simulator 上でテストする
# -only-testing で AsanomiTests だけに絞っている
xcodebuild \
-project "$XCODE_PROJECT" \
-scheme "$XCODE_SCHEME" \
-destination 'platform=iOS Simulator,name=iPhone 16,OS=18.5' \
IPHONEOS_DEPLOYMENT_TARGET="$CI_IOS_DEPLOYMENT_TARGET" \
-only-testing:AsanomiTests \
test構文として見ると、ポイントは次の7つです。
on
workflow を起動するタイミングを指定します。ここではpull_requestとpushを指定し、それぞれ対象ブランチをbranchesで絞っています。jobs
実行する処理のまとまりを定義します。ここではbuild-testという1つの job を作っています。runs-on
job を実行する環境を指定します。iOS アプリのビルドやテストには Xcode が必要なので、ここでは macOS runner を使っています。env
job 内で使う環境変数を定義します。プロジェクト名や scheme 名、deployment target のように何度も使う値をここにまとめています。steps
job の中で実行する手順を上から順に並べます。usesは既に用意されている Action を使う指定で、ここではactions/checkout@v6を使ってリポジトリのコードを runner に取得しています。run
runner 上で実行するシェルコマンドを書きます。複数行のコマンドを書くときは|を使い、その下にコマンドを並べます。xcodebuild test
Xcode のテストをコマンドラインから実行します。-project、-scheme、-destinationで対象を指定し、-only-testingで実行するテストを絞っています。
7. まとめ
TestFlight は、公開前のアプリを実機で配布し、フィードバックを集めるための仕組みです。
一方で CI は、ビルドやテストのような機械的に確認できる処理を、同じ条件で自動実行するための仕組みです。
朝の実では、TestFlight で実機確認を始めるタイミングで、GitHub Actions による最小限の CI も入れました。
今の CI では xcodebuild test で AsanomiTests を実行し、処理側のテストを GitHub Actions 上で確認できるようにしています。
まだ UI Test や lint、TestFlight 配布の自動化までは入れていません。
まずは TestFlight で人が見る部分と、CI で毎回同じ条件で見る部分を分けるところから始めました。
