Screenshot Test は、アプリケーション画面のスクリーンショットをキャプチャし、参照画像と比較することによる、ユーザーインターフェースの自動チェックです。ゴールデンテストとは異なり、スクリーンショットテストは実機またはエミュレーターで実行され、ナビゲーション、システム要素、アニメーションを含む完全な画面をキャプチャし、アプリケーションとの対話にUI Automator(Android)またはXCUITest(iOS)を使用します。詳細は Android UI Automator ドキュメント をご覧ください。
重要ポイント
Screenshot Test は、テストがアプリケーション画面を開き、アクション(タップ、テキスト入力、スクロール)を実行し、結果の状態のスクリーンショットを撮るエンドツーエンドのユーザーインターフェーステストです。スクリーンショットはリポジトリに保存されているベースラインと比較されます。スクリーンショットが異なる場合、テストは失敗します。スクリーンショットテストは、ユニットテストでは見つけられない視覚的な回帰(誤ったマージン、要素の重なり、間違った色)を検出します。
ゴールデンテストがあるのに、なぜスクリーンショットテストが必要なのか — ゴールデンテストはコンポーネントを個別にチェックします:1つのボタン、1つのカード、1つのテキスト。スクリーンショットテストは、本番環境に可能な限り近い環境で画面全体をチェックします:実際のナビゲーション、実際のデータ(または最大限に現実的なモック)、実際のシステムフォント、実際のステータスバー。スクリーンショットテストだけが、実機でボタンが他の要素と重なっていることを示します。
ビジネス価値 — Google(2023)によると、ビジュアルバグはモバイルアプリケーションの全バグの15〜25%を占めます。スクリーンショットテストは、以前はQAエンジニアが手動で行っていたビジュアル品質チェックを自動化します。1つのスクリーンショットテストで、1画面の手動テスト5〜10分を置き換えます。50画面のアプリケーションの場合、リグレッション実行ごとに4〜8人時の節約になります。スクリーンショットテストは2〜3リリースサイクルで元が取れます。
ゴールデンテスト はより高速でシンプルです:オフスクリーンバッファでのコンポーネントレンダリングはミリ秒単位で、デバイスを必要とせず、CIで安定しています。スクリーンショットテストはより現実的です:システム要素を含む実際の画面をキャプチャし、アニメーションとナビゲーションをサポートし、実機で動作します。選択は目標に依存します:開発者への迅速なフィードバック(ゴールデン)か、リリース前の最大限の現実性(スクリーンショット)か。
| 特性 | Screenshot Test | Golden Test |
|---|---|---|
| 速度 | 2〜30秒 | 50〜200ミリ秒 |
| 現実性 | 最大(実機) | 制限あり(オフスクリーン) |
| デバイス必要性 | あり(エミュレーター/実機) | なし(JVM、XCTest) |
| アニメーション | サポート | 非サポート |
| ナビゲーション | 複数ステップのシナリオ | 単一コンポーネント |
| 不安定性 | 高(ネットワーク、タイミング) | 中(GPU、フォント) |
| 並列性 | Device Farm(Firebase、AWS) | マルチスレッドJVM/XCTest |
Golden + Screenshot — コンポーネントライブラリ(Design System)の各UIコンポーネントにゴールデンテストを使用します。視覚的回帰の80%はコンポーネントレベルで捕捉されます。スクリーンショットテストは、重要なユーザーパス(オンボーディング、ログイン、支払いフロー、ショッピングカート)に使用します。実際の画面でのコンポーネント統合に関連する20%の回帰は、スクリーンショットテストでのみ捕捉されます。IT Sectrでは80/20の比率を使用しています:400ゴールデン + 100スクリーンショット。
スクリーンショットテストが不要な場合 — 画面がインタラクティブ性のない静的コンテンツで構成されている場合、ゴールデンコンポーネントテストは低コストで同じレベルの検証を提供します。画面が動的に変化する場合(フィード、チャット)、スクリーンショットテストは複雑なデータ設定と待機時間を必要とします。そのような場合は、ベースライン状態(空のリスト、読み込み中)にはスクリーンショットを、リスト内の個別カードにはゴールデンを使用します。
UI Automator は、アプリ間UIテストのためのAndroidフレームワークです。UiDevice.takeScreenshot()を介してスクリーンショットを撮ることができます。Espresso(単一アプリケーション内で動作)とは異なり、UI Automatorはシステムダイアログ(権限、通知)や他のアプリケーションと対話できます。UI Automatorでのスクリーンショットテスト:アプリを開き、読み込みを待ち、スクリーンショットを撮り、ベースラインと比較します。
class LoginScreenScreenshotTest {
@get:Rule
val rule = ComposeTestRule.createAndroidComposeRule<MainActivity>()
@Test
fun login_screen_default() {
val device = UiDevice.getInstance(
InstrumentationRegistry.getInstrumentation()
)
// 画面の読み込みを待つ
IdlingRegistry.getInstance().waitForIdle()
// スクリーンショットを撮る
val screenshot = device.takeScreenshot()
val golden = loadGolden("login_default.png")
// 基準と比較する
val diff = ImageComparator.compare(screenshot, golden)
assertTrue(diff.similarity > 0.98)
}
}
Firebase Test Lab は、数百台の実機で並行してインストゥルメントテストを実行するためのGoogle Cloudサービスです。Firebase Test Labでのスクリーンショットテストは、さまざまなデバイス(Pixel 7、Galaxy S24、Xiaomi 14)でスクリーンショットをキャプチャし、ベースラインと比較します。利点:1つのテストが20台のデバイスで10〜15分でUIをチェックします。欠点:コスト(20台のデバイスでテストあたり1〜5ドル)。Firebase Test Labはgcloud CLIまたはGradleプラグインを介してCIと統合します。
Shot は、Androidでのスクリーンショットテストを簡素化するライブラリです。ShotはEspressoとUI Automatorの上で動作し、ゴールデン管理(作成、更新、削除)、しきい値との比較(ピクセルまたはパーセンテージ)、HTMLレポート生成を追加します。Shotは、独自の画像比較インフラストラクチャを記述せずにスクリーンショットテストを迅速に実装したいプロジェクトに適しています。
XCUITest は、iOS、iPadOS、tvOSアプリケーションのUIテストのためのAppleのフレームワークです。XCUITestでのスクリーンショットテストは、画面キャプチャにXCUIScreen.main.screenshot()、スクリーンショットの保存にXCAttachmentを使用します。XCUITestはユーザーアクション(タップ、スワイプ、typeText)をシミュレートし、各ステップの後にスクリーンショットを撮ります。Xcode 16+では、XCTAttachmentを介したベースラインとのスクリーンショット比較の組み込みサポートが追加されました。
final class LoginScreenScreenshotTests: XCTestCase {
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
app.launch()
}
func test_login_initial_state() {
let loginButton = app.buttons["login_button"]
XCTAssertTrue(loginButton.exists)
// スクリーンショットを撮る
let screenshot = app.screenshot()
let attachment = XCTAttachment(screenshot: screenshot)
attachment.name = "Login-Screen-Initial"
attachment.lifetime = .keepAlways
add(attachment)
// 基準との比較 (XCTAttachment + goldenが必要)
assertScreenshot(
screenshot: screenshot,
goldenName: "login_initial_state"
)
}
}
Xcode Cloud は、iOSアプリケーションをビルドおよびテストするためのAppleのクラウドCIです。Xcode CloudはシミュレーターでのXCUITestテストの実行をサポートしています。スクリーンショットテストは、複数のシミュレーターで並行して実行できます(iPhone 15、iPhone 15 Pro Max、iPad Pro)。結果:添付ファイル付きのXCResult Bundle。Xcode CloudはGitHub/GitLabに組み込まれていません — 統合にはXcode Cloud Webhooksを使用してください。代替案:macos-14とxcodebuildを使用したGitHub Actions。
比較フレームワーク — iOSSnapshotTestCase(Uber)は、シミュレーターで実行する場合、スクリーンショットテストでも機能します。SwiftSnapshotTesting(pointfree)は、コンポーネントのゴールデンテストにより適しています。iOSでのスクリーンショットテストには、組み込みのXCUITestツール + XCTAttachment + カスタムImageComparator(PixelmatorまたはAImage)を使用してください。CIではシミュレーターを使用 — 実機でのスクリーンショットテストはDevice Farm(AWS Device Farm)を介してのみ機能します。
ベースライン管理 — ベースラインスクリーンショットはリポジトリ(Git LFS)またはS3に保存されます。各スクリーンショットはテンプレートに従って命名されます:{testName}_{device}_{orientation}_{locale}.png。例:loginScreenPixel7PortraitRu.png。新しいデバイスまたはロケールを追加するとき、新しいベースラインが作成されます。UIを変更するとき、コードレビュー後に古いベースラインが新しいものに置き換えられます。ベースラインは、テストソースと同様にコードベースの一部です。
CIパイプライン — (1)アプリケーションをビルド。(2)エミュレーター/シミュレーターでスクリーンショットテストを実行。(3)スクリーンショットをベースラインと比較。(4)不一致の場合 — 差分画像を生成。(5)差分アーティファクトをアップロード(actual、expected、diff — 3ファイル)。(6)結果テーブル付きのHTMLレポートを公開。(7)しきい値を超えた場合 — テストは失敗。(8)レビューアが差分アーティファクトを確認し、承認(ベースライン更新)か拒否(コード修正)を決定。
しきい値と許容範囲 — ピクセル単位の絶対比較は厳しすぎます。SSIM(構造類似性指標)またはMSE(平均二乗誤差)を使用します。SSIM 0.98 = 98%の構造的類似性 — 適切なしきい値です。画面によって異なるしきい値が必要になる場合があります:ダークテーマ(黒が多い — 精度が高い)、グラデーション(ノイズが多い — 精度が低い)。パラメーターを介してテストごとにしきい値を設定します:@ScreenshotTest(threshold = 0.99)。
Device Farm vs シミュレーター — 実機でのテスト(Firebase Test Lab、AWS Device Farm)は最大限の現実性を提供しますが、低速で有料です。シミュレーター/エミュレーターでのテストは高速で無料ですが、実機の特性(異なるGPU、ディスプレイの色再現、ピクセル密度)は示しません。戦略:プレマージチェックにはシミュレーター(5分)、ナイトリーテストにはDevice Farm(30分、20デバイス)。IT Sectrでは、トップ10のAndroidデバイスでのナイトリー実行にFirebase Test Labを使用しています。
よくある質問
Golden Test — 各コミットで個別のUIコンポーネントを迅速に検証するため(50〜200ミリ秒)。Screenshot Test — リリース前に実機で画面全体をE2E検証するため(2〜30秒)。両方を使用してください:Design Systemコンポーネントにはゴールデン、重要なユーザーパスにはスクリーンショット。80/20の比率がほとんどのプロジェクトで最適です。
SSIM 0.98 はほとんどの画面で適切な開始しきい値です。ダークテーマの場合は0.99を使用できます(コントラストが高い — より正確な比較)。グラデーションや画像のある画面の場合は0.95〜0.97。ピクセル単位の絶対比較(MSE = 0)は使用しないでください — アンチエイリアシングとGPUの違いにより20〜30%の誤検出が発生します。しきい値はテストごとに個別に設定してください。
意図的なUI変更のたびに — 色、フォント、マージン、アイコンの変更、要素の追加/削除。環境が変わったとき(OSバージョン、CIのフォント)はベースラインを更新しないでください — これは不安定なテストの兆候です。ベースラインはコードレビュー後に開発者がローカルでのみ更新します:古いベースラインを削除し、record=trueでテストを実行し、新しいスクリーンショットを確認し、コミットします。
はい — AndroidではEspresso、iOSではXCUITestを介して可能です。Espressoはアプリケーションプロセス内で動作し、Accessibility Service(UI Automatorのような)を必要としません。XCUITestはAppleの標準的なUIテストフレームワークです。スクリーンショットテストの場合、違いは最小限です:XCUITestはやや安定しており(ネイティブApple API)、UI Automatorはやや柔軟性があります(プロセス間相互作用)。
正しく設定されていれば — いいえ。プレマージ:変更された画面のみでスクリーンショットテストを実行します(30〜60秒)。ナイトリー:Device Farmで完全実行(30分、20デバイス)。エミュレーターでのスクリーンショットテスト実行時間:画面あたり2〜10秒。20画面 = 40〜200秒。これは1画面の手動テスト時間(5〜10分)よりも短いです。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。