プロジェクト構成概要
- ディレクトリ構造:
(ドライバの基本設定、グローバル例外処理、エラーショット、レポート自動生成、アプリ共通操作メソッド、ユーティリティクラスのまとめ)
- パッケージの階層構造:
basepageパッケージはアプリ共通操作メソッド、AndroidDriverの基本設定、TestNGの共通実行順序BaseTestを管理し、ドライバを外部に公開。
- BaseAppクラスには以下の操作を含む:
By型でのクリック操作、入力フィールドへのデータ入力、ウィンドウ切り替え、上下左右のスワイプ操作、座標指定でのクリック、ADBコマンド直接実行、戻る/進む/リフレッシュ操作など。他のメソッドは必要に応じて追加可能。
サンプルメソッド:
/**
* 要素定位でWebElementを取得
*
* @param driver AndroidDriverインスタンス
* @param elementLocator By型の要素定位
* @return 見つかった要素
*/
public WebElement findElementWithWait(AndroidDriver driver, By elementLocator) {
try {
WebDriverWait wait = new WebDriverWait(driver, 10);
return wait.until(ExpectedConditions.presenceOfElementLocated(elementLocator));
} catch (NoSuchElementException | TimeoutException e) {
System.out.println("===現在のページに該当要素が見つからないため、テストを継続=== ");
}
return null;
}
/**
* 要素クリック処理
*
* @param driver AndroidDriverインスタンス
* @param elementLocator By型の要素定位
* @return クリックされた要素
*/
public WebElement performClick(AndroidDriver driver, By elementLocator) {
try {
long startTime = DateUtils.getCurrentTimeMillis();
MobileElement targetElement = (MobileElement) findElementWithWait(driver, elementLocator);
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(elementLocator));
if (targetElement.isEnabled()) {
targetElement.click();
log.info("クリック処理実行時間(ms):" + (DateUtils.getCurrentTimeMillis() - startTime));
return targetElement;
}
} catch (NoSuchElementException | TimeoutException e) {
System.out.println("===要素が見つからないためスクリーンショット保存→テスト継続=== ");
ScreenshotUtil.takeScreenshot(driver);
}
return null;
}
/**
* 入力フィールドへのデータ入力
*
* @param driver AndroidDriverインスタンス
* @param elementLocator By型の要素定位
* @param inputText 入力する文字列(複数可)
* @return 入力フィールド要素
*/
public WebElement inputText(AndroidDriver driver, By elementLocator, CharSequence... inputText) {
WebElement inputField = findElementWithWait(driver, elementLocator);
inputField.clear();
inputField.sendKeys(inputText);
return inputField;
}
/*===================== スワイプ操作 =====================*/
/**
* 上方向スワイプ
*/
public void swipeUp(AndroidDriver driver) {
int screenWidth = driver.manage().window().getSize().width;
int screenHeight = driver.manage().window().getSize().height;
new TouchAction(driver)
.press(PointOption.point(screenWidth / 2, screenHeight * 3 / 4))
.waitAction(WaitOptions.waitOptions(Duration.ofMillis(500)))
.moveTo(PointOption.point(screenWidth / 2, screenHeight / 4))
.release()
.perform();
}
/**
* 下方向スワイプ
*/
public void swipeDown(AndroidDriver driver) {
int screenWidth = driver.manage().window().getSize().width;
int screenHeight = driver.manage().window().getSize().height;
new TouchAction(driver)
.press(PointOption.point(screenWidth / 2, screenHeight / 4))
.waitAction(WaitOptions.waitOptions(Duration.ofMillis(500)))
.moveTo(PointOption.point(screenWidth / 2, screenHeight * 3 / 4))
.release()
.perform();
}
/*===================== 座標指定クリック =====================*/
/**
* 座標指定でのタップ操作
*/
public void tapAtCoordinate(AndroidDriver driver, int x, int y) {
WebDriverWait wait = new WebDriverWait(driver, 5);
new TouchAction(driver)
.tap(PointOption.point(x, y))
.release()
.perform();
}
/**
* ADBコマンドでデバイス操作
*/
public void executeADBCommand(AndroidDriver driver, String command) {
try {
Process process = Runtime.getRuntime().exec(command);
WebDriverWait wait = new WebDriverWait(driver, 5);
process.destroy();
} catch (IOException e) {
e.printStackTrace();
}
}
- pageパッケージ(POモード):
dataサブパッケージとelementサブパッケージに分離。要素定位と入力データはdataに、操作処理はelementに格納。
- testcaseパッケージ:
ビジネスフローに沿ったテストケースを記述(テストケースのメンテナンスはこのパッケージで実施)
- resourceパッケージ:
chromedriverやスクリーンショット、自動生成レポート(Spring Boot環境で直接アクセス可能)を配置。テストレポートとしてはAllure2が一般的で、GitHubリポジトリにアクセス可能。
- Allure2レポートの統合:
Windows環境では公式サイトからZIPファイルをダウンロードし、環境変数を設定。テスト実行後にallure-resultsフォルダが生成され、以下のコマンドでレポートを開く:
allure serve allure-results
実行フロー例:
- testcaseパッケージでテストケースを記述(BaseTestを継承してドライバを取得)
public class SampleTest extends BaseTest {
SamplePage samplePage = new SamplePage();
@Test
public void sampleTest() {
System.out.println(driver);
samplePage.performAction(driver);
}
}
- pageパッケージのelementサブパッケージで操作クラスを定義(BaseAppを継承)
public class SamplePage extends BaseApp {
public void performAction(AndroidDriver driver) {
log.info("要素操作実行");
clickButton(driver, SampleData.TARGET_ELEMENT);
}
}
- pageパッケージのdataサブパッケージで要素定位情報を定義
public class SampleData {
public static final By TARGET_ELEMENT = By.id("com.example.app:id/target_view");
}
- BaseAppで定義された共通メソッドの使用例
public WebElement clickButton(AndroidDriver driver, By elementLocator) {
try {
long startTime = DateUtils.getCurrentTimeMillis();
MobileElement target = (MobileElement) findElementWithWait(driver, elementLocator);
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(elementLocator));
if (target.isEnabled()) {
target.click();
log.info("クリック処理実行時間(ms):" + (DateUtils.getCurrentTimeMillis() - startTime));
return target;
}
} catch (Exception e) {
System.out.println("===要素未検出時の処理→スクリーンショット保存後テスト継続=== ");
ScreenshotUtil.takeScreenshot(driver);
}
return null;
}
- TestNGとの統合(Spring Boot環境での実装例)
public class TestRunner {
@Test
public void executeAllTests() {
TestNG testng = new TestNG();
ExtentTestNGIReporterListener listener = new ExtentTestNGIReporterListener();
testng.setTestClasses(new Class[] {SampleTest.class});
testng.addListener(listener);
testng.run();
}
}