Macrobenchmarkとは
アプリの起動時間とか、フレーム時間とかを簡単に計測できるテストライブラリです。
https://developer.android.com/topic/performance/benchmarking/macrobenchmark-overview?hl=ja
UiAutomatorというのを使ってテストを書き、その上でいろいろ計測してくれます。
なのですごく細かい操作をして計測したい場合などは、UiAutomatorでのテストの書き方の知識も必要になってきます。
まあ、起動時間計測くらいなら比較的容易に出来るようになっています。
簡単なサンプルはこちらから。
https://developer.android.com/codelabs/android-macrobenchmark-inspect
(情報は古めなので注意)
実施環境など
ライブラリ | バージョン |
---|---|
uiautomator | "2.3.0" |
benchmark-macro-junit4 | "1.2.0-beta01" |
遭遇した問題
リストを最下部までスクロールして描画が完了するまでのフレーム時間計測を行いたいと思い、以下のようにテストを書きました。
ほぼcodelabのサンプルのままです。
@RunWith(AndroidJUnit4::class)
class ScrollBenchmark {
@get:Rule
val benchmarkRule = MacrobenchmarkRule()
@Test
fun scroll() = benchmarkRule.measureRepeated(
packageName = "xx.xxx.xxxx",
metrics = listOf(FrameTimingMetric()),
iterations = 5,
startupMode = StartupMode.COLD,
setupBlock = {
pressHome()
startActivityAndWait()
// リストの行が表示されるまで待つ
if (!device.wait(Until.hasObject(By.res("list_items")), 25_000)) {
fail("Could not find resource in time")
}
},
) {
val contentList = device.findObject(By.res("list"))
// Set gesture margin to avoid triggering system gesture navigation
contentList.setGestureMargin(device.displayWidth / 5)
// Scroll down the list to bottom
while (contentList.fling(Direction.DOWN)) {
// Wait for the scroll to finish
device.waitForIdle()
}
// Wait for the scroll to finish
device.waitForIdle()
}
ところが、contentList
がnullになってしまい、テストが落ちます。
端末での動作を見る限り、どうもsetupBlock
を実行後にすぐにアプリが終了されてしまっています。
measureBlock
の時点でアプリが終了しているので、当然list
が見つからないわけです。
解決策
benchmarkRule.measureRepeated
のパラメータ、startupMode=StartupMode.COLD
がいけないようです。
startupMode=StartupMode.WARM
にするとよいようです。
@Test
fun scroll() = benchmarkRule.measureRepeated(
packageName = "xx.xxx.xxxx",
metrics = listOf(FrameTimingMetric()),
iterations = 5,
startupMode = StartupMode.WARM, // ←ここ
setupBlock = {
あるいは、StartupMode.HOT
にして、毎回setupBlock内でkillProcess()
するのもよいようです。
StartupMode.WARM
だと、Activityは再作成されますがアプリプロセスは同じなので、設定値とかグローバル変数上のものなどは引き継がれて残ってしまうのでその辺が注意でしょうか。
参考ページ
あまり情報が無くて困っていましたが、最終的にはやっぱりStackoverflowにありました。
スレッドで提示されているissueを見ると、担当者は「期待された動作だ」と説明していますが、setup後にアプリを動かして計測したいのが普通じゃないのと思いますけどね。なんでsetup後にアプリのプロセスをkillするのが期待値なんだろう・・・?
現時点ではStatusはIn Progress (Accepted)
になっているので、今後修正される可能性はありそうですが。