KINTO Tech Blog
AutomationTesting

Appiumを利用したDark Mode自動化テスト

Cover Image for Appiumを利用したDark Mode自動化テスト

初めに

KINTOテクノロジーズのグローバル開発グループに所属しているパンヌウェイ(PannNuWai)です。グロバール開発グループでテスト自動化チームの担当としてプロダクト開発チーム用のテスト自動化環境の構築と整備をしていたり、プロダクトのテストチームでテストスクリプトを書いています。

私は、KINTOテクノロジーズに入社するまでもテスティングは担当していましたが、入社してから初めてAppiumの自動化テストを経験し、この間、様々なものを学びました。

Appiumは経験が無く、ゼロから勉強するところからのスタートでした。最初の環境設定から手探りで行いサーバーのアーキテクチャデザインまで行うことができようになりました。

この自動化テストでは、スマホアプリをメインにテストしましたが、その中で解決した課題を共有いたします。

本記事では自動化テストためAppium version 1.22.3を使ってDarkMode(ダークモード)に切り替える方法を話したいと思います。

自動化テストとは

ソフトウェアテストは不具合のある製品をリリースしてしまわないよう、ソフトウェアの問題を発見するために行う作業のことです。

本記事で「自動化テスト」とは支援ツールを用いてソフトウェアテストのプロセスを自動化することと言います。

自動化テストのメリット [1]

  • 不具合の早期発見
  • コストを抑えながら品質を高められる
  • 人的リソースが不足していてもテストできる
  • テストを高速で実施できる
  • ヒューマンエラーを排除できる
  • 営業時間外でもテストできる

Appium とは

iOSアプリ、Androidアプリ、およびデスクトッププラットフォームではネイティブ、ウェブビュー、ハイブリッドアプリをテストするためのオープンソースツールです。[2]

AppiumはJava,PHP,Pythonのプログラミング言語をサポートしているのでテスト者が好きな言語を選びながら簡単に使える自動化テストツールです。

Appiumのアーキテクチャでは

  • Appium Client
  • Appium Server
  • End Device

という三つのコンポーネントが有ります。

Appium Clientの中にはモバイルデバイスとアプリの詳細を設定されています。

Appium ServerにはNode.js言語を利用してjsonファイルを起動しながらシミュレーター(iOS)またはエミュレータ(Android)の接続を行います。

最後には起動されたAppium ServerによってEnd Deviceが発行されます。

Appium Inspector とは

Appium InspectorはモバイルアプリのUI要系を一意に識別するための標準的な手順です。実際のデバイスまたはシミュレーター(iOS)またはエミュレータ(Android)の両方で動作します。

注意点- Appium Inspectorツールはネイティブモバイルアプリケーションの属性のみを取得するように特別に設計されているため、Web ブラウザ(Chrome)でロケーターを見つけることをサポートしていません。

Appiumデスクトップアプリケーションは、Appiumサーバー自体とElementインスペクタの組み合わせで、テストスクリプトの開発中にモバイルアプリケーションのすべての目に見える要素を検出できるように設計されています。[3]

Dark Mode(ダークモード)とは

ダークモードはスマートフォンやノートパソコンなどのユーザーインターフェースの表示設定です。

明るい画面に対して暗いテキスト(ダークモード)が表示されている代わりに、黒い画面に対して明るい色のテキスト(ライトモード)が表示されることです。

現在ではスマートフォンのAndroidとiOS両方の既存ダークモード機能だけではなく、アプリの中にもダークモード機能をよく使います。モバイルアプリの自動化テストを行う場合はダークモード機能のテストも重要なチェック項目になりました。ですので、今回はAppiumを利用してモバイルアプリのダークモードについて話したいと思います。

問題点

Appiumを利用してダークモードのテストを行う場合、問題点があります。例えば、ログイン画面にusernamepasswordの文字が表示されているかをテストする際、Appium inspectorからusernamepasswordのelement存在する場所を取得します。通常は以下の通りでelementが表示されているのをチェックするのみです。

AssertTrue(driver.findElementByXPath("USER_NAME").isDisplayed());
AssertTrue(driver.findElementByXPath("PASSWORD").isDisplayed());

ですが、ダークモードの場合、elementの存在する場所を取得して表示をチェックするだけは不十分です。画面が黒い色に変更されているかをチェックするのはダークモードの大事な点です。黒い色と白い色のhexadecimal値をチェックする必要があります。

テスト方法

では、実際にAppiumでダークモードテスケースのソースコードを書いてみましょう。

changeToDarkTheme

ステップ 1

Appium inspectorからelementの存在する場所(ElementId)を取得します。

ステップ 2

デフォルト設定がライトモードになっているかどうかを
assertElementColorMode(MobileElement elementId, ColorMode colorMode)
で確認します。

ステップ 3

ダークモードのボタンを押下します。

ステップ 4

Display設定が ダークモードに変わるかどうかを
assertElementColorMode(MobileElement elementId, ColorMode colorMode)
で確認します。

public class DisplayChangePage extends Base {
    public static final String THEME_CELL_ID = "id/theme_parent";

    @Test(groups = "DisplayChangePage", dependsOnGroups = "Setting")
    public void changeToDarkTheme() {
        driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);

        MobileElement themeCell = getDriver().findElementById(THEME_CELL_ID);
        assertElementColorMode(themeCell, ColorMode.LIGHT);

        themeCell.click();

        driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
        tapElement(
                findElementByTextContains(ViewType.CHECKED_TEXT, resourceText("darkTheme"))
        );

        themeCell = getDriver().findElementById(THEME_CELL_ID);
        assertElementColorMode(themeCell, ColorMode.DARK);
    }
}

assertElementColorMode

Theme cellが存在しているElementIdと変更したいColorModeをパラメータとして設定しています。

ステップ 1

Theme cellが存在しているElementのエビデンスを取得します。getElementBufferedImage(MobileElement element)を使ってエビデンスを画像ファイルとして保存します。

ステップ 2

保存されている画像ファイルがnullにならないようにチェックします。

ステップ 3

画像ファイル(x = 10, y = 10)のポイントからカラーを取得して変更したいダークモードのカラーをチェックします。

public interface AppiumHelpersInterface extends FindElementsInterface {
    AppiumDriver<MobileElement> getDriver();
    Device getDevice();

    /**
     * Get buffered image of mobile element
     *
     * @param element Mobile element
     * @return Buffered image
     */
    default BufferedImage getElementBufferedImage(MobileElement element) {
        File image = element.getScreenshotAs(OutputType.FILE);
        try {
            return ImageIO.read(image);
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * Assert element's color mode
     *
     * @param element Mobile Element
     * @param mode    Color mode
     */
    default void assertElementColorMode(MobileElement element, ColorMode mode) {
        BufferedImage image = getElementBufferedImage(element);
        Assert.assertNotNull(image);
        Assert.assertTrue(Utils.getColorString(image, 10, 10).matches(mode.cellRegex()));
    }
}

getColorString

取得した画像のx-point, y-pointのカラーをhexadecimalに変更して配列を返却します。

    /**
     * Get color string from image at point x and y
     *
     * @param image BufferedImage
     * @param x     int
     * @param y     int
     * @return Hexadecimal Color String
     */
    public static String getColorString(BufferedImage image, int x, int y) {
        int rgba = image.getRGB(x, y);
        int[] rgb = new int[]{
                (rgba >> 16) & 0xff,
                (rgba >> 8) & 0xff,
                (rgba) & 0xff
        };

        return String.format("%02x%02x%02x", rgb[0], rgb[1], rgb[2]);
    }

cellRegex

ダークモードとライトモードの値を判断します。

public enum ColorMode {
    LIGHT,
    DARK;

    public String cellRegex() {
        // 22222 - lighter black
        if (this == DARK) return "2[(0-9|a-f)]2[(0-9|a-f)]2[(0-9|a-f)]";
        // ffffff
        return "f[(0-9|a-f)]f[(0-9|a-f)]f[(0-9|a-f)]";
    }
}
public interface ColorModeInterface {

    String darkModeScript();

    Map<String, Object> darkModeSettings();

    Map<String, Object> lightModeSettings();

    default void configureDarkMode(ColorMode mode) {
        getDriver().executeScript(darkModeScript(), mode == ColorMode.DARK ? darkModeSettings() : lightModeSettings());
    }
}

注意点

この方法はAppiumを利用したケースなのでNative Appのダークモード機能だけ使えます。

まとめ

本記事では、ダークモードの切り替える方法について説明しました。

ダークモードの自動化テストのためiOS(version13以上)とAndroid(version 5.0以上)両方で使えます。

今回はNative Appのダークモードテスト機能を行いましたが、今後はWeb Appのダークモードテストも試してみたいと思います。

グローバル開発内のテスト自動化チームは12月から増員しました。今後は、チームメンバーと一緒に、Appiumだけでなく、Katalonなど他のツールも用いた自動化テストに取り組んでいきたいです。

参考

脚注
  1. https://products.sint.co.jp/obpm/blog/test_automation ↩︎

  2. https://appium.io ↩︎

  3. https://www.kobiton.com/book/chapter-5-the-appium-inspector-2 ↩︎

Facebook

関連記事 | Related Posts

Cover Image for モバイルアプリ開発G紹介記事

モバイルアプリ開発G紹介記事

yena.h
yena.h
Cover Image for モバイルチーム勉強会

モバイルチーム勉強会

Cover Image for グローバル開発グループ(2/3)

グローバル開発グループ(2/3)

Cover Image for ネイティブアプリのQA業務の特徴

ネイティブアプリのQA業務の特徴

Cover Image for Vuetify と NuxtJS を使用した言語サポート

Vuetify と NuxtJS を使用した言語サポート

Xu Feng
Xu Feng
Cover Image for グローバル開発グループ(1/3)

グローバル開発グループ(1/3)

We are hiring!

【部長・部長候補】/プラットフォーム開発部/東京

プラットフォーム開発部 について共通サービス開発GWebサービスやモバイルアプリの開発において、必要となる共通機能=会員プラットフォームや決済プラットフォームの開発を手がけるグループです。KINTOの名前が付くサービスやTFS関連のサービスをひとつのアカウントで利用できるよう、様々な共通機能を構築することを目的としています。

【iOS/Androidエンジニア】モバイルアプリ開発G/東京・大阪

モバイルアプリ開発GについてKINTOテクノロジーズにおける、モバイルアプリ開発のスペシャリストが集まっているグループです。KINTOやmy routeなどのサービスを開発・運用しているグループと協調しながら品質の高いモバイルアプリを開発し、サービスの発展に貢献する事を目標としています。