SquishでAndroid向けQt Quickテスト


以前のブログ記事(リンク: [1], [2], [3] )では、QML コンポーネントをネイティブ Android アプリに組み込む方法について説明しました。この概念を、Qt Quick for Android と呼んでいます。これにより、Android Studio や Android ビルドシステムの使い慣れた環境から離れることなく、Qt を使用して Android アプリケーションに QML の機能を追加したり、UI 全体を QML で記述したりすることが簡単にできます。このブログ記事では、この技術で作成したアプリをテストするために、Qt Quality Assuranceツールを活用する方法について説明します。

GUI のテストに選んだツールは、優れたクロスプラットフォーム対応を提供する Squish です。しかし、「ちょっと待ってください。Squish を使ったことがありますが、Android と Qt では異なるエディションを選択しなければならないはずです。1 つのエディションだけでどのように機能するのですか?」という疑問が湧くかもしれません。実は、Squish は、この古いブログ記事で強調されているように、Qt と Android のコンテンツを一緒にテストすることをサポートしており、いくつかのビルドの違いがあるだけで、ここで同じ概念を使用することができます。

要約すると、前述ブログ記事では、Squish がネイティブ Android 要素を含む Qt アプリケーションのテストを、別々の Application Context を使用してサポートすることが説明されています。まず、Qt コンポーネントに Squish フックを追加し、最終的な APK からテストパッケージを作成して、Android 部分にインストルメンテーションを追加する必要があります。これらが完了すると、Squish for Androidでアプリケーションに接続し、コンテキストを切り替えることで、Qt Quick for AndroidアプリケーションのQt QuickコンポーネントとネイティブAndroidコンポーネントの両方を簡単にテストできます。素晴らしいですね!次に、テスト可能なアプリケーションの作成方法とテストケースの実行方法を見ていきましょう。Qtに付属のサンプルを起点として利用できます。

アプリのインストルメンテーション

アプリと通信するには、Squish はアプリケーションをテスト可能にするためにインストルメンテーションを行う必要があります。このケースでは、テスト対象アプリケーション (AUT) が異なるアーキテクチャ (Qt とネイティブ Android) の 2 つのコンポーネントで構成されているため、両方をインストルメンテーションする必要があります。Qt Quick コンポーネントは、APK ではなく Android Archive (AAR) ファイルとしてビルドするため、少し手間がかかります。

Qt Quick コンポーネントへのフック処理

Qt 部分については、Android テスト用の Squish のインストールに関する 公式ドキュメントに従ってください。Squish の Qt 組み込みフックを使用します。まず、Qt Quick プロジェクトの CMakeLists.txt に以下の内容を追加して、フックをビルドに追加します。

Set(SquishQtbuiltinHook_DIR /Users/<ユーザー名>/squish-9.0.1-qt69x-android-arm64-v8a)
# Look for Squish, optional and allowed to fail
find_package(SquishQtBuiltinHook)
# Add Squish to application target if found
if(SquishQtBuiltinHook_FOUND) 
    squish_qt_add_builtin_hook(qtquickview ATTACH_PORT 4567) 
endif() 

ポート番号は、システムポート以外から自由に選択できます。次に、IDE(Squish for Android)またはコマンドラインから、Qt Quick アプリを Squish に AUT として登録する必要があります。Squish のツールを使用すると、コマンドラインからの操作も簡単です。 

$ squishserver --config addAttachableAUT qtquickview localhost:4567 

また、ADB を使用してデバイスまたはエミュレータに接続しているため、ローカルポートをターゲットデバイスに転送する必要があります。

$ adb forward tcp:4567 tcp:4567 

通常の Android 用 Qt アプリケーションを構築している場合、この時点で完了しています。しかし、Qt コンポーネントが APK ではなく、Qt Gradle プラグインを使用して AAR に組み込まれているため、Squish フックの自動化の一部が機能していません(本記事投稿現時)。そのため、最終的な APK にいくつかのライブラリを手動で追加する必要があります。

今回は arm64-v8a デバイスでテストしているため、Android プロジェクトの下にディレクトリを作成し、そこに Squish ライブラリをコピーします。

mkdir –p app/libs/arm64-v8a 
cp ~/squish-9.0.1-qt69x-android-arm64-v8a/libs/*.so app/libs/arm64-v8a
cp ~/squish-9.0.1-qt69x-android-arm64-v8a/libs/extensions/qt/*.so app/libs/arm64-v8a 

そして、これらのファイルを APK にバンドルするには、app/build.gradle.kts の「android」セクションを変更する必要があります。 

android { 
    sourceSets.getByName("main").jniLibs.srcDir("libs") 
...

昔ながらの方法で Groovy DSL をまだ使用している場合は、次のようにします。

android { 
   SourceSets.main.jniLibs.srcDir 'libs'
...

もちろん、これらはすべて自動化することができます(そしておそらくそうすべきでしょう)。サンプルアプリを構築すると、アプリの Qt Quick 側が接続可能になり、テスト可能になります。やった!

ネイティブ Android コンポーネントのインストルメンテーション

Android 部分については、Squish は、アプリケーションをインストルメンテーションし、1 つのコマンドでターゲットデバイス/エミュレータにインストールする便利な apk-tool ツールを提供しています。以下のようなコマンドを実行します。

$ /Applications/Squish_for_Android_9.0.0/bin/apk-tool -j $JAVA_HOME -pkg
my_first_testable_app.apk -d emulator-5554 -o instrumented_app.apk
 

これにより、素晴らしい Qt Quick for Android アプリケーションが、インストルメンテーションされ、「emulator-5554」デバイスにインストールされます。

テストの実行

次に、両方のコンテキストでアプリ内のフックを起動して接続します。ここでは、汎用性が高く読みやすい Python を使用しますが、Squish のテストケースは 複数の言語でスクリプト化できます。

利便性を考慮し、アプリケーションコンテキストをSquishのテストモジュール内のinit()関数内で保存します。Android用のSquishのstartApplication()は、パッケージ名(この例ではcom.example.qtquickview_java)でアプリケーションを起動し、それにフックします。その後、attachToApplication()を使用して、登録されたAUT「qtquickview」に接続できます。

 

import test 

application_name = "qtquickview" 
package_name = “com.example.qtquickview_java” 

def init():
    test.log(“Start application in Android context”)
    test.ctx_android = squish.startApplication(package_name)
    test.log(“Connect to application in Qt context”) 
    test.ctx_qt = squish.attachToApplication(application_name)

実際のテストケースでは、コンテキストをすばやく切り替えて、コンポーネント間の相互作用や、必要なテストを実行できます。やった!以下の例では、Qt Quick for Androidを使用するアプリ(当社の例の一つ)に、Qt QuickコンポーネントとネイティブAndroidコンポーネントがあり、これらのコンポーネントが互いに影響し合っています。より具体的に説明すると、コードスニペットを理解するために、ネイティブAndroidの「Change Color」(色を変更) ボタンがQt Quickコンポーネントの背景色を変更します。これをテストするには、次のようなコードを書くことができます:

def main(): 
  test.log("Read Qt Quick component background color")
   qt_background_color = squish.waitForObjectExists(names.qt_MainRectangle).color

    test.log("Switch to Android context")
    squish.setApplicationContext(test.ctx_android)
    android_button = squish.waitForObjectExists(names.android_ChangeColor_Button)
    test.log("Tap on native Android Change Color button")
    squish.tapObject(android_button)
    
    test.log("Switch to Qt Quick context")
    squish.setApplicationContext(test.ctx_qt)
    test.log("Verify the Qt Quick component background color has changed")
new_background_color = squish.waitForObjectExists(names.qt_MainRectangle).color
  test.verify(new_background_color != qt_background_color)

Squish でテストコードを実行すると、すべてが正常に動作していることが確認できます。

anim-1

それだけです。


Blog Topics:

Comments