ローソンデジタルイノベーション テックブログ

ローソンデジタルイノベーション(LDI)の技術ブログです

Appiumは複数アプリを操作できる

ども。LDI品質管理部の仙波です。
スマホアプリの自動テストを担当しています。

最近は運動不足解消のためよく散歩していますが、新たなルートを開拓するのが楽しみです。

さて、今日もAppiumの使い方を探求しましょう。
今日は複数のアプリを操作する方法を紹介します。

同じ端末の中で複数のアプリを操作する

Appiumはテスト対象のアプリを操作してシステムテストを行うことができるツールですが、実はテスト対象以外のアプリも操作することができます。

もう少し具体的に言うと、画面に表示されているUIは、OSのUIだろうが、アプリのUIだろうが、どんなものでも操作できます。

たとえば、ホーム画面からアプリのアイコンをタップして起動したり、起動中の他のアプリに切り替えて操作することができます。

また、設定アプリでWi-FiをOFFにしてから、テスト対象アプリに切り替えて、Pull to Refreshで通信エラーダイアログが表示されることを確認する、というテストシナリオも実行できます。


以下に簡単なテストコードのサンプルを示します。言語はKotlinです。


driverのインスタンスを生成する共通関数

import io.appium.java_client.MobileElement
import io.appium.java_client.android.AndroidDriver
import io.appium.java_client.ios.IOSDriver
import org.openqa.selenium.remote.DesiredCapabilities
import java.net.URL

fun getAndroidDriver(): AndroidDriver<MobileElement> {

    // DesiredCapabilities
    val capabilities = DesiredCapabilities()
    capabilities.setCapability("automationName", "UiAutomator2")
    capabilities.setCapability("platformName", "Android")
    capabilities.setCapability("platformVersion", "10")
    capabilities.setCapability("appPackage", "com.android.settings")
    capabilities.setCapability("appActivity", "com.android.settings.Settings")

    // appiumServerAddress
    val appiumServerAddress = URL("http://127.0.0.1:4723/wd/hub")

    // AndroidDriver
    return AndroidDriver<MobileElement>(appiumServerAddress, capabilities)
}

fun getIOSDriver(): IOSDriver<MobileElement> {

    // DesiredCapabilities
    val capabilities = DesiredCapabilities()
    capabilities.setCapability("automationName", "XCUITest")
    capabilities.setCapability("platformName", "iOS")
    capabilities.setCapability("platformVersion", "14.3")
    capabilities.setCapability("deviceName", "iPhone 12 Pro")
    capabilities.setCapability("bundleId", "com.apple.Preferences")

    // appiumServerAddress
    val appiumServerAddress = URL("http://127.0.0.1:4724/wd/hub")

    // IOSDriver
    return IOSDriver<MobileElement>(appiumServerAddress, capabilities)
}


AndroidDriverを起動し、複数のアプリを操作するサンプル

import io.appium.java_client.android.nativekey.AndroidKey
import io.appium.java_client.android.nativekey.KeyEvent
import org.junit.jupiter.api.Test

class MultipleApps {

    @Test
    fun launchApps() {

        // Appium Serverに接続し、AndroidDriverを取得
        val androidDriver = getAndroidDriver()

        // ホームを表示
        androidDriver.pressKey((KeyEvent(AndroidKey.HOME)))
        Thread.sleep(1000)

        // 電卓アイコンをタップ
        androidDriver.findElementByXPath("//*[@text='電卓']").click()
        Thread.sleep(4000)

        // ホームを表示
        androidDriver.pressKey((KeyEvent(AndroidKey.HOME)))
        Thread.sleep(1000)

        // マップアイコンをタップ
        androidDriver.findElementByXPath("//*[@text='マップ']").click()
        Thread.sleep(4000)

        // ホームを表示
        androidDriver.pressKey((KeyEvent(AndroidKey.HOME)))
        Thread.sleep(1000)

        // Chromeアイコンをタップ
        androidDriver.findElementByXPath("//*[@text='Chrome']").click()
        Thread.sleep(4000)

    }

}


これを実行すると以下のように画面が表示されます。

f:id:wave1008:20210527000519p:plain


複数の端末で複数のアプリを操作する

1つのテストシナリオの中で複数の端末のアプリを操作することもできます。

この場合、前提条件としてAppium Serverのプロセスは別ポートで複数起動しておく必要があります。

appium -p 4723

f:id:wave1008:20210527092454p:plain:w400


appium -p 4724

f:id:wave1008:20210527092505p:plain:w400



以下にサンプルのテストコードを示します。

import com.google.common.collect.ImmutableMap
import io.appium.java_client.android.nativekey.AndroidKey
import io.appium.java_client.android.nativekey.KeyEvent
import org.junit.jupiter.api.Test

class MultipleAppsOverPhones {

    @Test
    fun launchAppsOverPhones() {

        // [Android] Appium Serverに接続し、AndroidDriverを取得(port=4723)
        val androidDriver = getAndroidDriver()

        // [iOS] Appium Serverに接続し、IOSDriverを取得(port=4724)
        val iosDriver = getIOSDriver()

        // [Android] ホームを表示
        androidDriver.pressKey((KeyEvent(AndroidKey.HOME)))
        Thread.sleep(1000)
        // [Android] マップアイコンをタップ
        androidDriver.findElementByXPath("//*[@text='マップ']").click()
        Thread.sleep(4000)

        // [iOS] ホームを表示
        iosDriver.executeScript("mobile: pressButton", ImmutableMap.of("name", "home"))
        Thread.sleep(1000)
        // [iOS] マップアイコンをタップ
        iosDriver.findElementByXPath("//*[@label='マップ']").click()
        Thread.sleep(4000)
    }

}


これを実行すると以下のように画面が表示されます。



初期状態
f:id:wave1008:20210527002227p:plain

Androidの設定アプリが起動
f:id:wave1008:20210527002242p:plain

iOSの設定アプリが起動
f:id:wave1008:20210527002253p:plain

Androidのホーム画面を表示
f:id:wave1008:20210527002303p:plain

Androidのマップを起動
f:id:wave1008:20210527002313p:plain

iOSのホーム画面を表示
f:id:wave1008:20210527002324p:plain

iOSのマップを起動
f:id:wave1008:20210527002333p:plain

1つのテストシナリオで複数端末を同時に操作する必要に迫られることはあまりないかもしれませんが、このような場合でもAppiumを使用して自動化することができます。