はじめに
1から簡単なAndroidアプリを作成し、それに対するE2EテストをAppiumで自動化しCI環境で実行できるようにする所までをやってみたのでその備忘録を残しておく。
※本記事はwebdriverioを用いているが、あえて最小で構築しているので@wdio/cli
は利用していない。
構築したアプリ・e2e自動テストのコード・CIパイプラインのコードは以下のGitHubにある。
内容
セクションは大きく3つで、
- アプリの実装について(Androidアプリを作成する)
- e2eテスト自動化のソースコードの実装について(AppiumによるE2Eテスト)
- CI上での自動テスト実行について(CI)
に分かれている。
Androidアプリを作成する
アプリの実装
Androidアプリのdeveloper向けのサイトにある公式チュートリアルがステップバイステップで丁寧&日本語字幕・解説があるので、これでアプリを作成するのがおススメ。
Kotlin での Android の基礎
※見た目は日本語モードでも英語になっているが、コンテンツの中身・字幕は日本語がある
※上記のKotlin での Android の基礎は、
https://developer.android.com/training/basics/firstapp?hl=ja#where-to-go-from-here から飛べるリンクのページ
AVD(エミュレータ)の作成
アプリを実際にPC上で起動しその動きを確認するためにはAVD(エミュレータ)が必要になるので仮想デバイスを作成して管理するを参照して作成する。
※ちなみに、このAVDはAppiumでE2Eテストを実行する時にも必要になる。
AVD(エミュレータ)の起動方法
Android Studioから起動するには以下の図の〇で作成したAVD名を選択し、▶をクリックすればいい。
ただ、このやり方だとAVDの起動時にイチイチAndroid Studioを立ち上げる必要があり面倒。
そこでemulator -list-avds
コマンドで作成済みのAVD一覧を表示させ、そのemulator {AVD名}
コマンドを実行するとAndroid Studioから毎回起動しなくてもAVDを起動できる。
C:\Users\user>emulator -list-avds
Pixel_3_XL_API_28
C:\Users\user>emulator @Pixel_3_XL_API_28
E2Eテストの実装対象になるアプリ一覧
実際に作成したアプリ① Happy Birthday Card App
単にメッセージが表示されているだけのアプリで、ソースコード全体はここ。
AppiumによるE2Eテスト
モバイルアプリのE2Eテスト自動化で定番のAppiumを使ってE2Eテストを実装した。
E2Eテストを実装する上でやった事としては以下。
- ローカル環境構築(CIについてはCIの項を参照)
- webdriverioの導入・テスト実装
- mochaの導入
- ロケータ指定する部分はutilityに
- webdriverioのlogをconsole上に出力させない
実際にE2Eテストを実装する上でどのようにロケータ情報などを調べるのか?については以下の項を参照。
- debbugerでのロケータ取得方法
ローカル環境構築
appium-doctor
でAndroidやiOSのアプリのテストのためのAppiumを実行する環境があるかを確認できる。
私の環境では以下のような結果だったのでJAVA_HOME・ANDROID_HOME(Java SDK, Android SDKのパス)の設定を行ったのでその時のlogを以下に書き残す(Windows)。
> appium-doctor
info AppiumDoctor Appium Doctor v.1.16.0
info AppiumDoctor ### Diagnostic for necessary dependencies starting ###
info AppiumDoctor ✔ The Node.js binary was found at: C:\Program Files\nodejs\node.EXE
info AppiumDoctor ✔ Node version is 14.16.0
WARN AppiumDoctor ✖ ANDROID_HOME environment variable is NOT set!
WARN AppiumDoctor ✖ JAVA_HOME environment variable is NOT set!
WARN AppiumDoctor ✖ adb, android, emulator could not be found because ANDROID_HOME or ANDROID_SDK_ROOT is NOT set!
WARN AppiumDoctor ✖ Cannot check %JAVA_HOME% requirements since the environment variable itself is not set
info AppiumDoctor ### Diagnostic for necessary dependencies completed, 4 fixes needed. ###
JAVA_HOMEの設定
https://adoptopenjdk.net/ から openjdk11 をインストールする。
※インストールの際、カスタムセットアップの画面でSet JAVA_HOME variable
がデフォルトだと× インストールしない
になっているので、ローカルハードドライブにインストール
に変更しないとパスが通らない。
インストール完了後、javac --version
とコマンドプロンプトで実行しバージョンが表示されれば OK。
(バージョンが表示されない時は再起動してJAVA_HOMEのパスがwindowsに通るようにする。)
ANDROID_HOMEの設定
Androidのアプリを作成するためにAndroid Studioをインストールすると、必要なAndroid SDK(+ SDK Tools)はインストール済みなはずなので、あとはそのSDKがある場所をWindowsの環境変数に設定してパスを通せばいい。
ただ、環境変数の登録にあたっては順番が大事なので注意。
私の環境では、C:\Users\user\AppData\Local\Android\Sdk
に SDK があったのでそれをそれぞれ、
- ANDROID_HOME
C:\Users\user\AppData\Local\Android\Sdk - Pathに以下の順でそれぞれ追加
- %ANDROID_HOME%emulator
- %ANDROID_HOME%tools
- %ANDROID_HOME%platform-tools
を環境変数に追加した。
最終的に再度appium-doctorを実行して以下のようにnecessary dependencies
が全て✔になっていればOK。
info AppiumDoctor Appium Doctor v.1.16.0
info AppiumDoctor ### Diagnostic for necessary dependencies starting ###
info AppiumDoctor ✔ The Node.js binary was found at: C:\Program Files\nodejs\node.EXE
info AppiumDoctor ✔ Node version is 14.16.0
info AppiumDoctor ✔ ANDROID_HOME is set to: C:\Users\user\AppData\Local\Android\Sdk
info AppiumDoctor ✔ JAVA_HOME is set to: C:\Program Files\AdoptOpenJDK\jdk-11.0.11.9-hotspot\
info AppiumDoctor Checking adb, android, emulator
info AppiumDoctor 'adb' is in C:\Users\user\AppData\Local\Android\Sdk\platform-tools\adb.exe
info AppiumDoctor 'android' is in C:\Users\user\AppData\Local\Android\Sdk\tools\android.bat
info AppiumDoctor 'emulator' is in C:\Users\user\AppData\Local\Android\Sdk\emulator\emulator.exe
info AppiumDoctor ✔ adb, android, emulator exist: C:\Users\user\AppData\Local\Android\Sdk
info AppiumDoctor ✔ 'bin' subfolder exists under 'C:\Program Files\AdoptOpenJDK\jdk-11.0.11.9-hotspot\'
info AppiumDoctor ### Diagnostic for necessary dependencies completed, no fix needed. ###
webdriverioの導入・テスト実装
今回はappiumでの自動化なので、appium serverとの通信を行う事になのでセッションを作る必要があるが、AppiumのGetting Startedに紹介されているやり方に沿って以下のように実装する。
(以下は単にセッションを繋いで切るだけのソースコード。remote()
で作成したセッションに対してhttps://webdriver.io/docs/api/webdriver に書かれているメソッドを使って実際にアプリを操作する。)
capabilities
についてはここを参照。
const wdio = require("webdriverio");
const opts = {
path: '/wd/hub',
port: 4723,
capabilities: {
platformName: "Android",
platformVersion: "9", // ここはandroidのemulatorのversion
deviceName: "Android Emulator",
app: `${__dirname.replace("__e2e__", "")}app/build/outputs/apk/debug/app-debug.apk`, // Androidのアプリ本体
automationName: "UiAutomator2"
}
};
async function main() {
const client = await wdio.remote(opts);
await client.deleteSession();
}
main();
mochaの導入
単純に以下のようにwebdriverioで操作をしてexpect.js
でassertionをしてもlog上はappium clientのlogが出るだけ結果が分かりにくいのでmochaを導入した。
// 省略
async function main() {
const client = await wdio.remote(opts);
const field = await client.$('//*[@resource-id="com.example.happybirthday:id/textView"]');
const value = await field.getText();
expect(value).to.equal("Happy Birthday, Sam!");
await client.deleteSession();
}
main();
node index.js
mochaの導入にあたって見たページは以下。
mochaで書いたソースコードは以下。
const wdio = require("webdriverio");
const expect = require("expect.js");
const by = require("../wedio/locator-helper");
const opts = require("../wedio/config");
describe('Create session and delete session', () => {
let client;
before(async () => {
client = await wdio.remote(opts);
});
describe('Happy Birthday App Test', () => {
it('check title text', async () => {
const field = await client.$("//android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[1]/android.view.ViewGroup/android.widget.TextView");
const value = await field.getText();
expect(value).to.equal("Happy Birthday");
});
it('check message text', async () => {
const field = await client.$(by.resourceId("com.example.happybirthday:id/textView"));
const value = await field.getText();
expect(value).to.equal("Happy Birthday, Sam!");
});
it('check from text', async () => {
const field = await client.$(by.resourceId("com.example.happybirthday:id/textView2"));
const value = await field.getText();
expect(value).to.equal("From Emma.");
});
})
after(async () => {
await client.deleteSession();
});
})
const by = require("../wedio/locator-helper");
やconst opts = require("../wedio/config");
のソースコードはGitHubから確認できる。
ロケータ指定する部分はutilityに
webとかであればfindElement()
などのメソッドをわざわざ呼び出さずともselectorsに書かれているような方法で簡単に要素を探し出せるが、Androidなどのモバイルだとそうはいかず、何通りかの方法で要素をしているする事になる。
※Android独自の要素指定方法であるUiSelector を用いて要素を探す時はAndroid UiAutomatorに書かれている方法が使える。
- resource-id
- xpath
- UiSelector
こういったものをソースコード上に書いてもいいがutilityとして別に切り出して用意しておくと便利。
具体的には以下のような感じ。
module.exports = {
/**
* リソースIDを指定するセレクタ
* @param {string} id resourceId-id
* @returns xpath
*/
resourceId(id) {
return `//*[@resource-id="${id}"]`;
},
/**
* クラス名を指定するセレクタ
* @param {string} className
* @returns UiSelector
*/
className(className) {
return `android=new UiSelector().className("${className}")`;
}
}
webdriverioのlogをconsole上に出力させない
何も設定をしないと以下のようにappium clientのlogとmochaのlogがごっちゃになって何が何だか分からなくなる。
> mocha --timeout 30s
Happy Birthday App Test
2021-07-30T07:32:27.849Z INFO webdriver: Initiate new session using the WebDriver protocol
2021-07-30T07:32:27.981Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session
2021-07-30T07:32:27.982Z INFO webdriver: DATA { 省略
2021-07-30T07:32:40.013Z INFO webdriver: COMMAND findElement("xpath", "//android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[1]/android.view.ViewGroup/android.widget.TextView")
2021-07-30T07:32:40.015Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session/27d30517-4d1e-4128-bb9e-733c5dd774d3/element
2021-07-30T07:32:40.015Z INFO webdriver: DATA {
using: 'xpath',
value: '//android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[1]/android.view.ViewGroup/android.widget.TextView'
}
2021-07-30T07:32:40.255Z INFO webdriver: RESULT {
'element-6066-11e4-a52e-4f735466cecf': 'f65a9d48-fff2-40b1-8301-5f11fa307990',
ELEMENT: 'f65a9d48-fff2-40b1-8301-5f11fa307990'
}
2021-07-30T07:32:40.269Z INFO webdriver: COMMAND getElementText("f65a9d48-fff2-40b1-8301-5f11fa307990")
2021-07-30T07:32:40.269Z INFO webdriver: [GET] http://127.0.0.1:4723/wd/hub/session/27d30517-4d1e-4128-bb9e-733c5dd774d3/element/f65a9d48-fff2-40b1-8301-5f11fa307990/text
2021-07-30T07:32:40.303Z INFO webdriver: RESULT Happy Birthday
✔ check title text (294ms)
2021-07-30T07:32:40.308Z INFO webdriver: COMMAND findElement("xpath", "//*[@resource- 省略
2021-07-30T07:32:40.309Z INFO webdriver: [POST] http://127.0.0.1:4723/wd/hub/session/27d30517-4d1e-4128-bb9e-733c5dd774d3/element
2021-07-30T07:32:40.309Z INFO webdriver: DATA 省略
2021-07-30T07:32:40.379Z INFO webdriver: RESULT 省略
2021-07-30T07:32:40.387Z INFO webdriver: COMMAND getElementText("0152bc52-dff5-4638-9979-e4689d0f71eb")
2021-07-30T07:32:40.387Z INFO webdriver: [GET] http://127.0.0.1:4723/wd/hub/session/27d30517-4d1e-4128-bb9e-733c5dd774d3/element/0152bc52-dff5-4638-9979-e4689d0f71eb/text
2021-07-30T07:32:40.413Z INFO webdriver: RESULT Happy Birthday, Sam!
✔ check message text (109ms)
2021-07-30T07:32:40.418Z INFO webdriver: COMMAND findElement("xpath", "//*[@resource- 省略
21-07-30T07:32:40.482Z INFO webdriver: RESULT 省略
2021-07-30T07:32:40.488Z INFO webdriver: COMMAND getElementText("17f89d91-f14e-47af-aebd-d365a9dfb67d")
2021-07-30T07:32:40.489Z INFO webdriver: [GET] http://127.0.0.1:4723/wd/hub/session/27d30517-4d1e-4128-bb9e-733c5dd774d3/element/17f89d91-f14e-47af-aebd-d365a9dfb67d/text
2021-07-30T07:32:40.511Z INFO webdriver: RESULT From Emma.
✔ check from text (94ms)
2021-07-30T07:32:40.512Z INFO webdriver: COMMAND deleteSession()
2021-07-30T07:32:40.513Z INFO webdriver: [DELETE] http://127.0.0.1:4723/wd/hub/session/27d30517-4d1e-4128-bb9e-733c5dd774d3
3 passing (14s)
そのためwebdriverioのoptionにoutputDir
キーを追加し、
outputDir: `${__dirname.replace(/__e2e__(\\|\/)wedio/, "")}__e2e__/`
のような記載してappium clientのlogは別の所に出力させるのがいいと思われる。
debbugerでのロケータ取得方法
e2eテストを実装していくにあたっては、要素を取得しそれに対して何らかのアクションを実行するがその要素を取得するためのロケータ情報はAppium Desktopで行う。
ロケータ情報を取得する時は、appium clientからAVD上にアプリを起動し、その状態で一時的にStopさせる必要があるのでnode のinspect
オプション × debugger
を使う。
describe('Create session and delete session', () => {
let client;
before(async () => {
client = await wdio.remote(opts);
});
it('debugger', async () => {
debugger;
});
after(async () => {
await client.deleteSession();
});
})
以下実際の流れ。
- appium serverとAVDを起動する
- テストを実行すると、Nodeのinspectの機能でコマンドラインで止まるのでそこで一旦放置
- Appium Desktopを起動する
-
File > New Session Window... > Attach to Session...タブ > Attach to Sessionボタン
で以下のような画面が表示されるのでここからロケータを取得する
※この時のポイントとしては、
- newCommandTimeout: 300 など長い時間に設定する
デフォルトでは 60(60 秒) になっているので、デバッグポイントで一時停止させた後、何も操作をしない(client から server にコマンドを送信しない)と 60 秒で session が切れてしまうため
※newCommandTimeoutはcapabilities
のキーの1つ
https://appium.io/docs/en/writing-running-appium/caps/ - --no-timeout に設定する
デフォルトでは 2s になっているので、mocha inspect --no-timeout
のように timeout しないようにしてからテスト実行しないと、appium desktop でロケータ情報などを取得している最中にデバッグが終了してしまう
のようにする事。
###テスト対象アプリ
テスト対象アプリ① Happy Birthday Card App
アプリとしては特にユーザが操作する事は全くできないアプリで、画面にテキストが表示されているもの。
そのためテスト内容としてはアプリに表示されているテキストが期待通りか?をassertionするテストを作成。
ソースコードは以下。
CI
ローカル環境でE2Eテストが実行できているだけではあまり意味がないため、CI環境で実行できるようにCIのパイプラインを構築した。
せっかくなので、
- CircleCi
- GitHub Actions
の2つのCICDプラットフォームでE2Eテスト自動化のパイプラインを構築した。
CircleCi
CircleCiの場合は公式ページにある程度ヒントになるyamlがあるのでそれを参考にすればいい。
使うコンテナはUsing Android Images with the Machine Executorという便利なコンテナが標準で用意されているのでそれを使う。これを使うとAndroidアプリのbuildを行ったり、emulatorを作成・起動するのが簡単にできる。
(GitHub:https://github.com/CircleCI-Public/android-image-preview-docs )
実際に作成したパイプラインのソースコードは以下。
GitHub Actions
GitHub Actionsの場合は、コンテナの選択を間違えると詰るので注意。大体CIを構築する時はubuntu-latest
を使うと思うがこれだとAndroidのemulatorが起動できない。
そのためGitHub Actionsでは、**macos-latest
**を使うようにする。
詳細はubuntu-latestでエラー『emulator: ERROR: x86 emulation currently requires hardware acceleration!』を使うを参照。
実際に作成したパイプラインのソースコードは以下。
※GitHub Actionsでのe2eテスト自動化は少し手間取った箇所があったのでそれを以下のトラブルシューティングに書き残しておく。
トラブルシューティング
sdkmanager, avdmanager コマンドの実行
sdkmanager
コマンドを実行しようと数するもエラー(GitHub Actions の JobURL はこれ)
sdkmanager "system-images;android-28;default;x86"
avdmanager --verbose create avd -n test -k "system-images;android-28;default;x86"
/home/runner/work/_temp/af62e0b9-d807-4eb2-87a6-f1e203106b6c.sh: line 2: sdkmanager: command not found
単純にデフォルトでパスが通っていないようなので、どこにsdkmanager
がいるかを探す必要がある。
探すとsdkmanager
はandroid_sdk/cmdline-tools/version/bin/
にあるので、
$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager
のように実行するればよい。
参考:Android SDK コマンドライン ツール
ライセンスへの同意
sdkmanager
コマンドを実行すると Android SDK のライセンス同意が表示され、それに対し標準入力を行わないとエラーになる。
これは
echo "y" | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "$SYSTEM_IMAGES"
のようにする事でコマンドからの質問に応答できる。
emulator コマンドの実行
emulator
はandroid_sdk/emulator/
にあるので
$ANDROID_HOME/emulator/emulator -avd test -verbose -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim
のように実行する。
参考:Android エミュレータ
※ちなみに、emulator 起動時に引数に色々オプションを付けられるがそれぞれ以下の通り。
コマンドライン オプション | 説明 |
---|---|
-avd avd name | 起動する avd の名前を指定する |
-verbose | エミュレータの初期化メッセージをターミナル ウィンドウに出力させる |
-no-window | エミュレータのグラフィカル ウィンドウ表示を無効にする |
-gpu mode | グラフィック アクセラレーション タイプをmodeに指定する |
-no-snapshot | スナップショットの復元後すぐに AVD クロック時刻の修正を試みないようにする |
-noaudio | 仮想デバイスのオーディオ サポートを無効にする |
-no-boot-anim | 起動を高速化するため、エミュレータ起動中の起動アニメーションを無効にする |
参考:コマンドラインからのエミュレータの起動
参考:コマンドラインからグラフィック アクセラレーションを設定する
emulatorがbootするまで待機する
emulator が起動するまでには少し時間がかかり、起動が完了してからテスト実行しないとテストが失敗する。
のでemulatorが起動完了する(boot completed)まで待つ必要がある。
emulator が起動完了すると以下のような log が出るが、
emulator: INFO: boot completed
これが出るまで待つには、
adb shell getprop init.svc.bootanim
というコマンドを利用すればいい。
実際の実装としては以下のようになる。
while [ "`adb shell getprop sys.boot_completed | tr -d '\r'`" != "1" ] ; do sleep 10 && echo "wait for boot..."; done
参考:Detect when Android emulator is fully booted
参考:【 tr 】コマンド――テキストファイルの文字を置換する/削除する
Background実行のjobのlogをArtifactに保存
CircleCi では background: true
で backgroud 実行させてそのlogも見れるが、GitHub Actionsではbackgroundで実行させる事はできてもそのlogがGitHub Actionsのconsoleに出力されない。
ex) https://github.com/yuta-katayama-23/MobileAppE2ETest/runs/3191394079?check_suite_focus=true
そのためappium server、AVDのlogそれぞれをArtifactに保存するように実装した。
- name: Start android emulator
# https://developer.android.com/studio/run/emulator-commandline
run: |
mkdir ~/log
$ANDROID_HOME/emulator/emulator -avd test -verbose -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim >> ~/log/emulator.log &
# 省略
- name: Start appium server
run: |
cd __e2e__
npm run s:appium >> ~/log/appium.log &
# 省略
- name: Archive emulator and appium server logs
if: always()
uses: actions/upload-artifact@v2
with:
name: log
path: ~/log
ubuntu-latest でエラー『emulator: ERROR: x86 emulation currently requires hardware acceleration!』
(前置き:ここにはubuntu-latest
でCIを構築しようとして失敗した時の作業logも細かく書いてある。)
GitHub Actions も CircleCi と考え方は同じで、基本的にはローカルでエミュレータ起動・Appium Server の起動を行い、その後テスト実行を行う手順と同じ事をコマンドで行えば GitHub Actions 上でも E2Eテストが実行できる。
GitHub Actions の Runner ubuntu-latest
に元々インストール済みのものを見ると、Android のアプリ build・E2E テストに必要なものはほぼインストール済みで、インストールする必要があるのは appium だけ。
※ちなみに、GitHub Actions の Runner 一覧はここ。
使うコンテナをubuntu-latest
に決め、パイプライン実装して実行すると、以下のようなlogが出てエラーに(jobのURLはこれ。)
logの内容から単純にKVMが必要そうと分かり、logに出ているリンクにアクセス。
emulator: CPU Acceleration: DISABLED
emulator: CPU Acceleration status: KVM requires a CPU that supports vmx or svm
emulator: ERROR: x86 emulation currently requires hardware acceleration!
CPU acceleration status: KVM requires a CPU that supports vmx or svm
More info on configuring VM acceleration on Linux:
https://developer.android.com/studio/run/emulator-acceleration#vm-linux
General information on acceleration: https://developer.android.com/studio/run/emulator-acceleration.
Android 公式のドキュメントに沿って Ubuntu KVM のインストールを行っていく
Linux ベースのシステムは、KVM ソフトウェア パッケージを介して VM アクセラレーションをサポートしています。 Linux システムに KVM をインストールする手順を行い、KVM が有効になっていることを確認します。Ubuntu システムについては、Ubuntu KVM のインストールの説明をご覧ください。
Ubuntu KVM のインストールのサイトに従ってやっていく(GitHub ActionsのRunner上で)。
sudo apt-get install cpu-checker
sudo /usr/sbin/kvm-ok
でチェックすると、、、
INFO: Your CPU does not support KVM extensions
KVM acceleration can NOT be used
と言われ、使えないの・・・となるが、以下のような注意書きがあり、今使える/使えないを示してるだけなので、install すれば OK そうと考える。
NOTE: You may see a message like "KVM acceleration can/can NOT be used". This is misleading and only means if KVM is currently available (i.e. "turned on"), not if it is supported.(「KVM アクセラレーションを使用できます/使用できません」のようなメッセージが表示される場合があります。 これは誤解を招く可能性があり、KVM が現在利用可能(つまり「オン」)である場合にのみ意味し、サポートされている場合はそうではありません。)
ubuntu-latest はCosmic (18.10) or later
2なので、
sudo apt-get install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils
を実行すればいい
その後、Add Users to Groups
を実行してvirsh list --all
でインストールが成功したか?を確認するもエラーが変わらず・・・
GitHub Actions の Marketplace にあるGitHub Action - Android Emulator Runnerを見ると、
The old ARM-based emulators were slow and are no longer supported by Google. The modern Intel Atom (x86 and x86_64) emulators require hardware acceleration (HAXM on Mac & Windows, QEMU on Linux) from the host to run fast. This presents a challenge on CI as to be able to run hardware accelerated emulators within a docker container, KVM must be supported by the host VM which isn't the case for cloud-based CI providers due to infrastructural limits.(古い ARM ベースのエミュレーターは低速であり、Google ではサポートされなくなりました。 最新の IntelAtom(x86 および x86_64)エミュレーターは、高速で実行するために、ホストからのハードウェアアクセラレーション(Mac および Windows では HAXM、Linux では QEMU)を必要とします。これは、Docker コンテナー内でハードウェアアクセラレーションエミュレーターを実行できるようにするという CI の課題を提示します。)
The macOS VM provided by GitHub Actions has HAXM installed so we are able to create a new AVD instance, launch an emulator with hardware acceleration, and run our Android tests directly on the VM. You can also achieve this on a self-hosted Linux runner, but it will need to be on a compatible instance that allows you to enable KVM - for example AWS EC2 Bare Metal instances.(GitHubActions が提供する macOSVM には HAXM がインストールされているため、新しい AVD インスタンスを作成し、ハードウェアアクセラレーションを使用してエミュレーターを起動し、VM で Android テストを直接実行できます。 セルフホストの Linux ランナーでもこれを実現できますが、KVM を有効にできる互換性のあるインスタンス(AWS EC2 ベアメタルインスタンスなど)で実行する必要があります。)
It is recommended to run this action on a macOS VM, e.g. macos-latest or macos-10.15 to take advantage of hardware accleration support provided by HAXM.(このアクションは、macOSVM で実行することをお勧めします。 macos-latest または macos-10.15 は、HAXM が提供するハードウェアアクセラレーションサポートを利用します。)
とか書いてあり、GitHub Actions 標準のubuntu-latest
でやるのは不可能である事が分かり方針転換でmacos-latest
に変更した。
kextstat | grep intel
で Intel HAXM カーネル拡張機能が使えるか?を確認すると、
121 0 0xffffff7f82c2f000 0x28000 0x28000 com.intel.kext.intelhaxm (7.6.5) 9C4BE7CB-745A-326F-81FF-6D7D61B68F87 <8 6 5 3 1>
と表示されたので OKそう。
その後emulator起動をしてみるとうまくいった。
参考文献
-
https://mochajs.org/#-inspect-inspect-brk-inspect
ソースコード上に以下のようにdebugger
を置き、node --inspect hoge.js
のようにテストを起動する。
(今回はmochaだが要領は同じで、debugger
を置き、mocha inspect --no-timeout
1でテストを実行すればいい。) ↩