モバイルテストブラウザ開発事例
プロジェクト概要
PC環境でスマートフォンやタブレットの表示を効率的にテストするための専用ツールを開発しました。開発中のWebシステム(localhost環境)のレスポンシブデザインを素早く検証できる自動化ツールです。
技術スタック
言語・フレームワーク
- Python 3.7+
- Selenium WebDriver
主要ライブラリ
- selenium: ブラウザ自動化
- Chrome DevTools: モバイルエミュレーション
開発環境
- Google Chrome + ChromeDriver
- Git(バージョン管理)
開発背景・課題
解決したい課題
- 開発効率の向上: レスポンシブデザインの確認作業の自動化
- テスト環境の統一: 複数のモバイルデバイスでの表示確認
- localhost環境での検証: 開発中システムの動的テスト
従来の問題点
- 手動でのブラウザサイズ変更による非効率なテスト
- デバイス固有の表示問題の見落とし
- 複数ポートでの開発時の設定変更の煩雑さ
実装した主要機能
1. モバイルデバイスエミュレーション
mobile_devices = {
"iPhone_12": {
"width": 390,
"height": 844,
"pixel_ratio": 3.0,
"user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0..."
},
"Galaxy_S21": {
"width": 360,
"height": 800,
"pixel_ratio": 3.0,
"user_agent": "Mozilla/5.0 (Linux; Android 11..."
}
}
対応デバイス
- iPhone 12 (390×844)
- iPhone SE (375×667)
- Galaxy S21 (360×800)
- iPad (768×1024)
2. 動的ポート設定機能
def get_port_input():
while True:
try:
port_input = input("ポート番号を入力してください (デフォルト: 10024): ").strip()
if not port_input:
port = 10024
else:
port = int(port_input)
if port < 1 or port > 65535:
print("❌ ポート番号は1-65535の範囲で入力してください")
continue
app_url = f"http://localhost:{port}"
return app_url
except ValueError:
print("❌ 有効な数値を入力してください")
特徴
- 起動時にポート番号を動的に指定可能
- 入力値の妥当性チェック(1-65535の範囲)
- デフォルト値の自動設定
3. 自動テスト機能
def check_responsive_elements(self):
elements_to_check = [
("body", "ページ全体"),
("main", "メインコンテンツ"),
(".container", "コンテナ"),
("header", "ヘッダー"),
("nav", "ナビゲーション"),
("button", "ボタン"),
("input", "入力フィールド")
]
for selector, description in elements_to_check:
elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
if elements:
element = elements[0]
size = element.size
location = element.location
print(f"✅ {description}: サイズ {size['width']}x{size['height']}")
自動実行項目
- スクリーンショット自動撮影
- レスポンシブ要素の表示状態チェック
- ビューポート情報の取得
- 要素サイズ・位置の検証
4. インタラクティブテスト環境
def wait_and_interact(self, timeout=None):
if timeout is None:
print("⏰ ブラウザが起動しました。手動でテストを行ってください")
print("📝 可能な操作:")
print(" - 要素のクリック")
print(" - スクロール")
print(" - フォーム入力")
print(" - レイアウト確認")
while True:
try:
self.driver.current_url
time.sleep(1)
except:
break
手動テスト支援
- ブラウザ操作の自由度確保
- 開発者ツール自動起動
- リアルタイムでの確認作業
改修・拡張開発
クライアント要求による機能追加
要求内容: 固定されたポート番号ではなく、起動時に動的に設定したい
実装アプローチ
1. 既存コードの分析: ハードコードされたURL設定の特定
2. ユーザーインターフェースの追加: 対話式ポート入力機能
3. エラーハンドリングの強化: 入力値検証とユーザビリティ向上
4. ドキュメント整備: README.md、.gitignore、requirements.txt作成
技術的実装ポイント
# Before: 固定URL
def __init__(self, chromedriver_path=None, app_url="http://localhost:10024"):
self.app_url = app_url
# After: 動的URL設定
def __init__(self, chromedriver_path=None, app_url=None):
self.app_url = app_url
# 新機能: ポート入力処理
def get_port_input():
# バリデーション付きポート入力処理
# デフォルト値設定
# エラーハンドリング
プロジェクト管理・品質管理
ドキュメント整備
README.md: 包括的な技術ドキュメント
- セットアップ手順
- 使用方法
- API仕様
- トラブルシューティング
- 拡張方法
.gitignore: 適切な除外設定
- Python関連ファイル(pycache、*.pyc)
- 仮想環境(/venv/)
- テスト出力ファイル(スクリーンショット)
- IDE設定ファイル
requirements.txt: 依存関係管理
selenium>=4.0.0
アーキテクチャ設計
MobileTestBrowser (Class)
├── 初期化・設定管理
├── ブラウザオプション設定
├── デバイスエミュレーション
├── 自動テスト実行
├── スクリーンショット管理
├── インタラクティブモード
└── リソース管理
設計思想
- 単一責任原則: 機能ごとのメソッド分離
- 拡張性: 新デバイス・機能の追加容易性
- エラーハンドリング: 堅牢性の確保
- ユーザビリティ: 直感的なインターフェース
成果・効果
開発効率の向上
- テスト時間短縮: 手動操作から自動化への移行
- 設定変更の簡素化: ポート番号の動的設定
- 再現性の確保: 一貫したテスト環境
品質向上
- 見落とし防止: 自動的な要素チェック
- ドキュメント化: 後続開発者への引き継ぎ支援
- 標準化: 統一されたテスト手順
運用面での改善
- 柔軟性: 様々な開発環境への対応
- 保守性: 明確なコード構造とドキュメント
- 拡張性: 新機能追加の容易性
技術的学び・工夫点
Selenium活用
- モバイルエミュレーション: Chrome DevToolsとの連携
- 要素検証: 動的な画面要素の状態確認
- スクリーンショット: 自動的な証跡取得
ユーザーエクスペリエンス
- 対話式インターフェース: 直感的な操作性
- エラーメッセージ: 分かりやすいフィードバック
- デフォルト値: 使いやすさの配慮
コード品質
- 例外処理: 堅牢なエラーハンドリング
- 設定の外部化: ハードコードの排除
- ドキュメント: 包括的な仕様書作成
今後の拡張可能性
機能拡張案
- 複数ブラウザ対応: Firefox、Safari対応
- テストシナリオ: 自動操作スクリプト機能
- レポート機能: テスト結果の自動レポート生成
- CI/CD連携: 継続的インテグレーション対応
技術的改善点
- 設定ファイル: JSON/YAML形式での設定管理
- ログ機能: 詳細なテスト履歴記録
- パフォーマンス: 大規模テストの最適化
- クラウド対応: リモートテスト環境への展開
このプロジェクトは、実際の開発現場での課題解決から生まれた実用的なツールです。クライアントの要求に応じた機能拡張、品質管理の徹底、そして将来的な保守性を考慮した設計により、継続的に価値を提供できるソリューションとなっています。