Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
CIでAndroidUIテストの様子を録画してみた
mkeeda
May 17, 2022
Programming
0
330
CIでAndroidUIテストの様子を録画してみた
Mobile勉強会 Wantedly × チームラボ #5
https://wantedly.connpass.com/event/244011/
mkeeda
May 17, 2022
Tweet
Share
More Decks by mkeeda
See All by mkeeda
Jetpack Compose 完全に理解した
mkeeda
1
450
5分でわかるCompose Modifiers deep dive
mkeeda
1
200
みんなで準備するスポンサー
mkeeda
0
70
What's new in Android development tools まとめ
mkeeda
0
860
Other Decks in Programming
See All in Programming
フロントエンドで学んだことをデータ分析で使ってみた話
daichi_igarashi
0
180
SHOWROOMの分析目的を意識した伝え方・コミュニケーション
hatapu
0
240
Remix + Cloudflare Pages + D1 で ポケモン SV のレンタルチームを検索できるアプリを作ってみた
kuroppe1819
4
1.3k
Micro Frontends with Module Federation @MicroFrontend Summit 2023
manfredsteyer
PRO
0
500
まだ日本国内で利用できないAppActionsにトライしてみた / MoT TechTalk #15
mot_techtalk
0
110
Cloudflare WorkersでGoを動かすライブラリを作っている話
syumai
1
310
ECテックカンファレンス2023
kspace
1
290
Swift Concurrency in GoodNotes
inamiy
4
1.3k
PHPDocにおける配列の型定義を少し知る
shimabox
1
130
量子コンピュータ時代のプログラミングセミナー / 20221222_Amplify_seminar _route_optimization
fixstars
0
240
AWS App Runnerがそろそろ本番環境でも使い物になりそう
n1215
PRO
0
960
jq at the Shortcuts
cockscomb
1
410
Featured
See All Featured
Bootstrapping a Software Product
garrettdimon
299
110k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
318
19k
Music & Morning Musume
bryan
37
4.6k
Keith and Marios Guide to Fast Websites
keithpitt
407
21k
What the flash - Photography Introduction
edds
64
10k
Testing 201, or: Great Expectations
jmmastey
25
5.7k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
44
14k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
15
1.2k
YesSQL, Process and Tooling at Scale
rocio
159
12k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
10
1.3k
Design by the Numbers
sachag
271
18k
Gamification - CAS2011
davidbonilla
75
4.1k
Transcript
CIでAndroidUIテストの様⼦を 録画してみた .PCJMFษڧձ8BOUFEMZºνʔϜϥϘ NLFFEB
About me • mkeeda (向井⽥ ⼀平) • Twitter: @mr_mkeeda •
Github: @mkeeda • Android Engineer at Cybozu, Inc 2
UIテストあるある • 不安定🤮 • CIでだけUIテストが落ちる🤮 • エラーがよくわからない🤮 • エラーが毎回違う🤮 3
UIテストの様⼦を録画してみた • CIのテスト実⾏時は Androidエミュレータの画⾯が⾒れない • UIテストが落ちるときの画⾯の状態を知りたい • Firebase test
labは使ってない • テスト失敗時にGithub Actionsの アーティファクトに録画データを残す 4
Androidデバイス画⾯収録の基本 • 録画開始 • adb shell screenrecord <ファイルパス> • ※ファイルパスはAndroidデバイスのパス
• 録画停⽌ • Ctrl + C (mac は Command + C) • 録画ファイル取得 • adb pull <録画ファイルのパス> <ローカルデバイスの保存先パス> 5
テストケースごとに録画してみる • ScreenRecordRule を作る • “record_<テストメソッド名>.mp4” というファイル名で保存する 6 @RunWith(AndroidJUnit4::class) class
SampleUiTest { @get:Rule var activityRule: ActivityScenarioRule<LoginActivity> = ActivityScenarioRule(LoginActivity::class.java) @get:Rule var screenRecordRule = ScreenRecordRule() @Test fun test() { // run test } }
テストコードから adb コマンドを実⾏ • UiAutomation.executeShellCommand(String command) を使う • ローカルマシンで adb
shell <command> をするのと同等 7 val uiAutomation = InstrumentationRegistry.getInstrumentation().uiAutomation // ը։࢝ uiAutomation.executeShellCommand("screenrecord /sdcard/record.mp4") // ըऴྃ (Ctrl + C) ϓϩηεID͕ඞཁ uiAutomation.executeShellCommand("kill -SIGINT $screenRecordProcessId")
screenrecord のプロセスを得る 8 fun executeCommand(cmd: String): String { val parcelFileDescriptor
= uiAutomation.executeShellCommand(cmd) return ParcelFileDescriptor.AutoCloseInputStream(parcelFileDescriptor).use { inputStream -> inputStream.readBytes().toString(Charset.defaultCharset()) } } fun findProcessIds(processName: String): List<Int> { return executeCommand(cmd = "pidof $processName") .trim() .split(Regex("\\s+")) .filter { it.isNotEmpty() } .map { it.toInt() } } val screenRecordProcessIds = findProcessIds(processName = "screenrecord")
ScreenRecordRule 9 class ScreenRecordRule : TestWatcher() { private val shell
= Shell() private var screenRecordProcessIds: List<Int> = emptyList() override fun starting(description: Description) { shell.executeCommand(cmd = "screenrecord /sdcard/record_${description.methodName}.mp4", awaitOutput = false) screenRecordProcessIds = shell.findProcessIds(processName = "screenrecord") } override fun finished(description: Description) { // গ͠Ԇ͔ͤͯ͞Βऴྃͤ͞ͳ͍ͱ࠷ޙ·ͰըͰ͖ͳ͍ͱ͖͕͋ͬͨͷͰํͳ͘ Thread.sleep(5000) // ͯ͢ͷscreenrecordϓϩηεΛࢭΊΔ // 1σόΠεͰ࣮ߦ͍ͯ͠ΕଞͷςετέʔεͷըΛࢭΊͯ͠·͏Մೳੑ͍ͣ screenRecordProcessIds.forEach { pid -> shell.executeCommand(cmd = "kill -SIGINT $pid", awaitOutput = false) } } }
Github Actionsでの録画データの回収 • テストが失敗したときだけ録画をCIのアーティファクトとして保存する 10 - name: Run android tests
uses: reactivecircus/
[email protected]
with: api-level: 31 arch: x86_64 disable-animations: true script: | ./gradlew connectedDebugAndroidTest || (mkdir screen_record; adb shell 'ls sdcard/record_*.mp4' | tr -d '\r' | xargs -I% adb pull % ./screen_record && exit 1) - name: Save screen record if: failure() uses: actions/
[email protected]
with: name: screen-records path: ./screen_record
• adbコマンドを使えばAndroidTestの実⾏の様⼦を 録画できる • 実⾏時の様⼦を知って テスト失敗時の原因追求ができる • 乱⽤するとテスト時間の増⼤に繋がりそう
• ScreenRecordRuleのソースコード https://gist.github.com/mkeeda/30b8cfdcec53859a2cd39cac36d7fc9e 11 まとめ To Be Continued
参考 • Android Debug Bridge (adb) | Android Developers
https://developer.android.com/studio/command-line/adb • UiAutomation | Android Developers https://developer.android.com/reference/android/app/ UiAutomation#executeShellCommand(java.lang.String) • androidx.benchmark.Shell https://cs.android.com/androidx/platform/frameworks/support/+/ androidx-main:benchmark/benchmark-common/src/main/java/androidx/ benchmark/Shell.kt 12