目次

AWS Application Testing v2.0 完全ガイド

公式ドキュメント


1. 本質と位置付け

AWS のアプリケーションテストソリューションは 「実デバイスモバイルテスト(AWS Device Farm)」「混沌エンジニアリング・障害注入テスト(AWS Fault Injection Service)」 の 2 つの主要サービスで構成される。

  • AWS Device Farm:300+ の実 Android/iOS デバイス・ブラウザで自動テスト実行
  • AWS Fault Injection Service(FIS):EC2 / RDS / ECS / EKS / Lambda に意図的な障害を注入して回復力検証

サービス概要

AWS Device Farm

  • 実デバイス数:300+ 台(iPhone / iPad / Android スマートフォン・タブレット)
  • テストフレームワーク:Appium / XCTest / Espresso / Calabash
  • リモートアクセス:ブラウザ上での対話型テスト + Appium リモート実行
  • リージョン:us-west-2(オレゴン)のみ

AWS Fault Injection Service(FIS)

  • 対応リソース:EC2 / ECS / EKS / RDS / Lambda / Network
  • 障害タイプ:インスタンス停止・再起動・CPU ストレス・レイテンシ注入・パケットロス
  • ストップ条件:CloudWatch アラーム(自動安全シャットダウン)
  • リージョン:複数対応

このサービスを選ぶ理由

なぜ AWS Device Farm / FIS を選ぶのか?

  1. 実デバイステスト(Device Farm)のメリット

    • エミュレーター vs 実デバイス
      • エミュレーター:GPS・センサー・NFC・バッテリー挙動の再現困難
      • Device Farm(実デバイス):実際のハードウェア固有バグを検出(バッテリー消費異常・OS バージョン差異等)
    • デバイス多様性:300+ の機種対応(iPhone 12~16 / Android 8~14 等)
    • 並列実行:最大 100 並列でテスト時間を 1/100 に短縮
  2. 混沌エンジニアリング(FIS)の必要性

    • 本番障害シミュレーション:「AZ 障害が起きたら?」を事前に検証する唯一の方法
    • 安全なガードレール:CloudWatch アラームをストップ条件に設定すれば、許容度超過時に自動停止
    • 回復力証明:単なる机上計画でなく、実際の復旧プロセスを自動化して検証
  3. CI/CD パイプラインへの統合

    • CodePipeline から Device Farm テスト・FIS 実験を自動トリガー
    • リリース前に自動品質ゲート実施
  4. AWS エコシステムの完全統合

    • CloudWatch 監視・ログ・メトリクス連携
    • IAM ロール・ポリシーで統一アクセス管理
    • S3 テスト結果・レポート保存

2. AWS Device Farm 詳細

2.1 Device Farm アーキテクチャと実行モデル

┌──────────────────────────────────────────────────────┐
│ アプリケーション開発者                              │
├──────────────────────────────────────────────────────┤
│ APK (Android) / IPA (iOS)                            │
│ + Test Suite (Appium / XCTest / Espresso)           │
└─────────────────┬──────────────────────────────────┘
                  │ S3 / 直接アップロード
                  ↓
┌──────────────────────────────────────────────────────┐
│ AWS Device Farm(us-west-2 オンリー)               │
├──────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────┐  │
│ │ Test Execution Engine                           │  │
│ │ - Appium Server                                 │  │
│ │ - XCTest Runner(iOS)                          │  │
│ │ - Espresso Runner(Android)                    │  │
│ └─────────────────────────────────────────────────┘  │
│           ↓                                          │
│ ┌─────────────────────────────────────────────────┐  │
│ │ Device Pool(デバイスグループ)                │  │
│ │ ┌────────┐ ┌────────┐ ┌────────┐              │  │
│ │ │iPhone14│ │iPhone15│ │iPhone16│ ...         │  │
│ │ │iOS 17  │ │iOS 17  │ │iOS 18  │              │  │
│ │ └────────┘ └────────┘ └────────┘              │  │
│ │ ┌────────┐ ┌────────┐ ┌────────┐              │  │
│ │ │Pixel 5 │ │Pixel 6 │ │Pixel 7 │ ...         │  │
│ │ │Android │ │Android │ │Android │              │  │
│ │ │13      │ │14      │ │15      │              │  │
│ │ └────────┘ └────────┘ └────────┘              │  │
│ └─────────────────────────────────────────────────┘  │
│           ↓                                          │
│ ┌─────────────────────────────────────────────────┐  │
│ │ Metering & Reporting                            │  │
│ │ - ビデオ・スクリーンショット録画                │  │
│ │ - ログ・パフォーマンス測定データ収集            │  │
│ │ - HTML レポート生成                             │  │
│ └─────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────┘
                  ↓
           S3 / CloudWatch

2.2 Device Farm セットアップ

# プロジェクト作成
aws devicefarm create-project \
  --name "mobile-app-tests" \
  --region us-west-2

# 出力:
# {
#   "project": {
#     "arn": "arn:aws:devicefarm:us-west-2:...:project:12345678-...",
#     "name": "mobile-app-tests",
#     "created": "2024-01-15T10:30:00Z"
#   }
# }

# デバイスプール作成(カスタムデバイスセット)
aws devicefarm create-device-pool \
  --project-arn "arn:aws:devicefarm:us-west-2:...:project:..." \
  --name "iPhone-latest-models" \
  --rules '[
    {
      "attribute": "PLATFORM",
      "operator": "EQUALS",
      "value": "IOS"
    },
    {
      "attribute": "OS_VERSION",
      "operator": "GREATER_THAN_OR_EQUALS",
      "value": "17.0"
    },
    {
      "attribute": "MODEL",
      "operator": "IN",
      "value": "iPhone15Pro,iPhone16,iPhone16Plus"
    }
  ]'

# 出力:
# {
#   "devicePool": {
#     "arn": "arn:aws:devicefarm:us-west-2:...:devicepool:...",
#     "name": "iPhone-latest-models",
#     "type": "PRIVATE",
#     "rules": [ ... ]
#   }
# }

2.3 テスト実行(Run)

# テストランの実行
aws devicefarm schedule-run \
  --project-arn "arn:aws:devicefarm:us-west-2:...:project:..." \
  --app-arn "arn:aws:devicefarm:us-west-2:...:app:..." \
  --device-pool-arn "arn:aws:devicefarm:us-west-2:...:devicepool:..." \
  --test '{
    "type": "APPIUM_PYTHON",
    "testPackageArn": "arn:aws:devicefarm:us-west-2:...:upload:...",
    "filter": "TestSuite.*::TestMethod"
  }' \
  --configuration '{
    "auxiliaryApps": [
      "arn:aws:devicefarm:us-west-2:...:app:testhelper"
    ],
    "billingMethod": "METERED",
    "location": {
      "latitude": 35.6762,
      "longitude": 139.6503
    }
  }' \
  --execution-configuration '{
    "jobTimeoutMinutes": 30,
    "accountsCleanup": true,
    "appPackagesCleanup": true,
    "skipAppResign": false,
    "videoCapture": true
  }' \
  --region us-west-2

# 出力:
# {
#   "run": {
#     "arn": "arn:aws:devicefarm:us-west-2:...:run:...",
#     "name": "Appium Python Test Run",
#     "status": "SCHEDULED",
#     "result": "PENDING"
#   }
# }

# テスト実行進捗確認
aws devicefarm get-run \
  --arn "arn:aws:devicefarm:us-west-2:...:run:..." \
  --region us-west-2 \
  --query 'run.{status: status, result: result, created: created}'

# テストレポート取得
aws devicefarm list-jobs \
  --arn "arn:aws:devicefarm:us-west-2:...:run:..." \
  --region us-west-2 \
  --query 'jobs[*].{name: name, status: status, result: result}'

2.4 Appium テスト例

# conftest.py(Appium テスト設定)
import os
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
import pytest

# Device Farm 対応
APPIUM_SERVER = os.environ.get('APPIUM_HOST', 'http://127.0.0.1:4723')

@pytest.fixture(scope='session')
def driver():
    """Device Farm での実行時、APPIUM_HOST が設定される"""
    
    desired_caps = {
        'platformName': 'iOS',
        'platformVersion': '17.0',
        'deviceName': 'iPhone 15 Pro',
        'app': os.environ.get('APPIUM_APP_ID'),  # Device Farm から渡される
        'bundleId': 'com.example.myapp',
        'automationName': 'XCUITest',
        'newCommandTimeout': 600,
        'connectHardwareKeyboard': False,
        'reduceMotion': True
    }
    
    driver = webdriver.Remote(APPIUM_SERVER, desired_caps)
    yield driver
    driver.quit()

# test_login.py(テストケース)
class TestLoginFlow:
    def test_successful_login(self, driver):
        """ログイン成功フロー"""
        
        # ログイン画面待機
        username_field = driver.find_element(
            AppiumBy.ID, 
            'com.example.myapp:id/username_input'
        )
        password_field = driver.find_element(
            AppiumBy.ID,
            'com.example.myapp:id/password_input'
        )
        
        # 認証情報入力
        username_field.send_keys('testuser@example.com')
        password_field.send_keys('TestPassword123')
        
        # ログインボタンクリック
        login_button = driver.find_element(
            AppiumBy.ID,
            'com.example.myapp:id/login_button'
        )
        login_button.click()
        
        # 成功画面確認(最大 30 秒待機)
        driver.implicitly_wait(30)
        home_screen = driver.find_element(
            AppiumBy.ID,
            'com.example.myapp:id/home_title'
        )
        assert home_screen.text == 'Welcome, testuser'
    
    def test_invalid_credentials(self, driver):
        """無効な認証情報"""
        
        username_field = driver.find_element(
            AppiumBy.ID,
            'com.example.myapp:id/username_input'
        )
        password_field = driver.find_element(
            AppiumBy.ID,
            'com.example.myapp:id/password_input'
        )
        
        # 不正な認証情報
        username_field.send_keys('invalid@example.com')
        password_field.send_keys('WrongPassword')
        
        login_button = driver.find_element(
            AppiumBy.ID,
            'com.example.myapp:id/login_button'
        )
        login_button.click()
        
        # エラーメッセージ確認
        driver.implicitly_wait(10)
        error_msg = driver.find_element(
            AppiumBy.ID,
            'com.example.myapp:id/error_message'
        )
        assert 'Invalid credentials' in error_msg.text

2.5 リモートアクセス(Interactive Testing)

# リモートアクセスセッション作成
aws devicefarm create-remote-access-session \
  --project-arn "arn:aws:devicefarm:us-west-2:...:project:..." \
  --device-arn "arn:aws:devicefarm:us-west-2:...:device:..." \
  --instance-arn "arn:aws:devicefarm:us-west-2:...:instance:..." \
  --configuration '{
    "billingMethod": "METERED",
    "videoCapture": true
  }' \
  --region us-west-2

# 出力:
# {
#   "remoteAccessSession": {
#     "arn": "arn:aws:devicefarm:us-west-2:...:session:...",
#     "status": "PENDING",
#     "webUrl": "https://device.devicefarm.aws.com/session/..."
#   }
# }

# セッション URL をブラウザで開く
# → リアルタイムでデバイスを操作・テスト可能
# → ビデオ録画・スクリーンショット自動キャプチャ
# → セッション終了後にログ・動画を S3 に保存

3. AWS Fault Injection Service(FIS)詳細

3.1 FIS アーキテクチャ

┌────────────────────────────────────────────────────────┐
│ アプリケーションアーキテクチャ                         │
├────────────────────────────────────────────────────────┤
│                                                        │
│  ┌─────────────────┐     ┌─────────────────┐         │
│  │   ALB           │     │   Route 53      │         │
│  │ (us-east-1a)    │     │ (Health Check)  │         │
│  └────────┬────────┘     └────────┬────────┘         │
│           │                       │                   │
│  ┌────────▼────────────────────────▼──────┐          │
│  │ ┌─────────────────────────────────────┐ │         │
│  │ │ AZ: us-east-1a                      │ │         │
│  │ │ ┌────────┐ ┌────────┐ ┌──────────┐ │ │         │
│  │ │ │ App-1  │ │ App-2  │ │ Replica │ │ │         │
│  │ │ │ (m5.l) │ │ (m5.l) │ │ (m5.l)  │ │ │         │
│  │ │ └────────┘ └────────┘ └──────────┘ │ │         │
│  │ └─────────────────────────────────────┘ │         │
│  │ ┌─────────────────────────────────────┐ │         │
│  │ │ AZ: us-east-1b(Standby)          │ │         │
│  │ │ ┌────────┐ ┌────────┐              │ │         │
│  │ │ │ App-3  │ │ App-4  │              │ │         │
│  │ │ └────────┘ └────────┘              │ │         │
│  │ └─────────────────────────────────────┘ │         │
│  └──────────────────────────────────────────┘         │
│                                                        │
│  ┌─────────────────────────────────────┐             │
│  │ RDS Multi-AZ                        │             │
│  │ ┌─────────────┐ ┌──────────────┐   │             │
│  │ │ Primary     │ │ Standby      │   │             │
│  │ │ (us-east-1a)│ │(us-east-1b)  │   │             │
│  │ └─────────────┘ └──────────────┘   │             │
│  └─────────────────────────────────────┘             │
│                                                        │
└────────────────────────────────────────────────────────┘

3.2 FIS 実験テンプレート作成

# 実験テンプレート定義(JSON)
cat > az-failure-experiment.json << 'EOF'
{
  "description": "AZ failure simulation with auto-recovery validation",
  "targets": {
    "AZInstances": {
      "resourceType": "aws:ec2:instance",
      "resourceTags": {
        "Environment": "production",
        "Service": "web-api"
      },
      "filters": [
        {
          "path": "Placement.AvailabilityZone",
          "values": ["us-east-1a"]
        }
      ],
      "selectionMode": "ALL"
    }
  },
  "actions": {
    "StopInstances": {
      "actionId": "aws:ec2:stop-instances",
      "parameters": {
        "startInstancesAfterDuration": "PT5M"
      },
      "targets": {
        "Instances": "AZInstances"
      }
    },
    "TriggerASGScaleOut": {
      "actionId": "aws:autoscaling:change-desired-capacity",
      "parameters": {
        "desiredCapacity": "10"
      },
      "targets": {
        "AutoScalingGroups": "WebASG"
      },
      "startAfter": ["StopInstances"]
    }
  },
  "stopConditions": [
    {
      "source": "aws:cloudwatch:alarm",
      "value": "arn:aws:cloudwatch:us-east-1:123456789012:alarm:api-error-rate-high"
    },
    {
      "source": "aws:cloudwatch:alarm",
      "value": "arn:aws:cloudwatch:us-east-1:123456789012:alarm:rds-failover-in-progress"
    }
  ],
  "roleArn": "arn:aws:iam::123456789012:role/FISExperimentRole",
  "tags": {
    "Purpose": "DR-Drill",
    "Schedule": "Weekly",
    "Owner": "Platform-Team"
  }
}
EOF

# テンプレート作成
aws fis create-experiment-template \
  --cli-input-json file://az-failure-experiment.json \
  --region us-east-1

# 出力:
# {
#   "experimentTemplate": {
#     "id": "EXT1234567890ABCDEF",
#     "arn": "arn:aws:fis:us-east-1:...:experiment-template/EXT...",
#     "description": "AZ failure simulation with auto-recovery validation",
#     "creationTime": "2024-01-15T10:30:00Z"
#   }
# }

3.3 FIS 実験実行

# 実験実行
aws fis start-experiment \
  --experiment-template-id EXT1234567890ABCDEF \
  --tags '{
    "GameDay": "2024-01-15",
    "StartedBy": "incident-commander",
    "ExpectedDuration": "15 minutes"
  }' \
  --region us-east-1

# 出力:
# {
#   "experiment": {
#     "id": "EXP1234567890ABCDEF",
#     "arn": "arn:aws:fis:us-east-1:...:experiment/EXP...",
#     "state": "RUNNING",
#     "startTime": "2024-01-15T10:30:00Z"
#   }
# }

# 実験進捗監視
aws fis get-experiment \
  --id EXP1234567890ABCDEF \
  --region us-east-1 \
  --query '{
    State: state,
    Progress: progress,
    StopConditionMet: stopConditionMet,
    Outcome: outcome
  }'

# 実験停止(緊急停止)
aws fis stop-experiment \
  --id EXP1234567890ABCDEF \
  --region us-east-1

# 実験レポート確認
aws fis describe-experiment-template-actions \
  --template-id EXT1234567890ABCDEF \
  --region us-east-1

3.4 CloudWatch ストップ条件の設定

# エラーレート監視アラーム
aws cloudwatch put-metric-alarm \
  --alarm-name api-error-rate-high \
  --alarm-description "FIS stop condition: API error rate exceeds 5%" \
  --metric-name ErrorRate \
  --namespace AWS/ApplicationELB \
  --statistic Average \
  --period 60 \
  --threshold 5 \
  --comparison-operator GreaterThanThreshold \
  --evaluation-periods 1 \
  --treat-missing-data notBreaching \
  --region us-east-1

# 可用性監視アラーム
aws cloudwatch put-metric-alarm \
  --alarm-name availability-degraded \
  --alarm-description "FIS stop condition: Availability drops below 99.5%" \
  --metric-name Availability \
  --namespace Custom/Application \
  --statistic Average \
  --period 60 \
  --threshold 99.5 \
  --comparison-operator LessThanThreshold \
  --evaluation-periods 2 \
  --region us-east-1

4. 比較:AWS Device Farm vs Sauce Labs vs BrowserStack

総合比較表

比較項目 AWS Device Farm Sauce Labs BrowserStack LambdaTest Tricentis Tosca
実デバイス数 300+ 600+ 800+ 500+ 1000+
デバイス種別 iOS / Android iOS / Android / Web iOS / Android / Web iOS / Android / Web / Desktop Web / Mobile / Desktop
テストフレームワーク Appium / XCTest / Espresso Appium / XCTest / Espresso / WebDriver Appium / XCTest / WebDriver Appium / WebDriver / Selenium Tosca Studio(独自)
マネージド度 ✅ フル(AWS) ✅ フル(Cloud) ✅ フル(Cloud) ✅ フル(Cloud) △ Self-managed
ビデオ・ログ ✅ 標準 ✅ 標準 ✅ 標準 ✅ 標準 ✅ 標準
リモートアクセス ✅ ブラウザ ✅ ブラウザ / VNC ✅ ブラウザ ✅ ブラウザ ✅ VNC
並列実行 ✅ 100+ ✅ 300+ ✅ 500+ ✅ 400+ ✅ 無制限
CI/CD 統合 ✅ CodePipeline / GitHub ✅ Jenkins / CircleCI ✅ Jenkins / GitLab ✅ Jenkins / GitHub ✅ Jenkins / Bamboo
AWS 統合 ✅ 最高(IAM / CloudWatch) △ 限定的 △ 限定的 △ 限定的
初期セットアップ 複雑(Appium 要) 簡単 簡単 簡単 複雑(IDE)
価格感 $0.17/分(無料枠 1000分/月) 従量制($0.50~/分) 従量制($0.60~/分) 従量制($0.40~/分) 有償ライセンス(高額)
推奨対象 AWS デプロイ・DevOps 統合 マルチクラウド・拡張性 大規模チーム・高並列 スタートアップ・低コスト 大規模エンタープライズ

詳細比較

AWS Device Farm の強み

  • AWS コンソール・IAM と統合(セキュリティ・監査)
  • CodePipeline デプロイパイプライン内での自動テスト
  • CloudWatch アラーム連携
  • オンプレミス Appium サーバーとのハイブリッド対応

Sauce Labs の強み

  • デバイス・ブラウザ数が豊富(600+ デバイス)
  • Sauce Connect(VPN トンネル)でプライベートネットワークテスト
  • レガシー OS バージョン対応(古い iOS / Android)
  • 企業向けアナリティクス(テストレポート・トレンド分析)

BrowserStack の強み

  • Web アプリ + モバイルの統合テスト
  • Visual Regression テスト機能
  • Network シミュレーション(4G / 3G / 2G)
  • スクリーンレコーディング・テスト実行動画の自動共有

5. 実装チェックリスト

Device Farm テスト導入

  • [ ] Device Farm プロジェクト作成
  • [ ] テストアプリ(APK / IPA)準備
  • [ ] Appium テストスクリプト作成
  • [ ] デバイスプール定義(機種・OS バージョン)
  • [ ] CI/CD パイプライン統合(CodePipeline)
  • [ ] テストレポート自動配信設定(SNS)
  • [ ] 本番環境での定期テスト実行スケジュール

Fault Injection Service(FIS)導入

  • [ ] CloudWatch アラーム作成(ストップ条件)
  • [ ] IAM ロール・ポリシー設定(FIS 実行権限)
  • [ ] 実験テンプレート作成(AZ 障害・EC2 停止・RDS フェイルオーバー)
  • [ ] ステージング環境での実験実行・動作確認
  • [ ] 本番環境実験の実行計画(メンテナンスウィンドウ・通知)
  • [ ] 実験レポート・改善アクション追跡
  • [ ] 定期的な DR 訓練スケジュール化

6. 料金と ROI

Device Farm 料金

課金方法 価格
デバイス単価 $0.17/分(1000 分以上)
月間無料枠 1000 分(新規アカウント)
無制限プラン $250/デバイス/月(定額)

コスト例

月間テスト計画:3000 分(50 デバイス並列実行)

従量課金:
  3000分 × 50 × $0.17 = $25,500/月

定額プラン:
  50 × $250 = $12,500/月

削減効果:50%

FIS 料金

課金項目 価格
アクション実行時間 $0.10/アクション時間
実験テンプレート作成 無料

コスト例

月間 DR 訓練:4回 × 2 時間 = 8 時間

費用:8時間 × $0.10 = $0.80/月
(ほぼ無視できる)

7. まとめ

AWS Application Testing は 「Device Farm(実デバイムテスト) + FIS(障害注入テスト)」 の統合ソリューション。

主な価値

  • Device Farm:実デバイスでのバグ検出(エミュレーター では再現不可)
  • FIS:本番回復力を事前検証(ダウンタイム ゼロ)
  • AWS 統合:CodePipeline / CloudWatch との完全統合
  • 自動化:CI/CD パイプラインでの自動品質ゲート

使うべき場合

  • モバイルアプリ → Device Farm で 300+ デバイステスト
  • クリティカルシステム → FIS で定期的な DR 訓練
  • AWS 完全統合 → IAM / CloudWatch 監視
  • DevOps / CI/CD 重視 → パイプライン内自動テスト

参考資料

AWS Application Testing は 品質保証・回復力検証の完全自動化 を実現し、デジタルサービスの信頼性向上を推進する。