Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building the automated Android UI testing in Continuous integration at LINE MAN Wongnai

Building the automated Android UI testing in Continuous integration at LINE MAN Wongnai

"Building the automated Android UI testing in Continuous integration at LINE MAN Wongnai" at Android Bangkok 2023

Somkiat Khitwongwattana

November 06, 2023
Tweet

More Decks by Somkiat Khitwongwattana

Other Decks in Technology

Transcript

  1. Building the automated Android UI testing in Continuous Integration Somkiat

    Khitwongwattana Android GDE @akexorcist At LINE MAN Wongnai
  2. LINE MAN Wongnai LINE MAN Rider LINE MAN Driver Wongnai

    Merchant Wongnai POS Consumer Local Business Rider & Driver Wongnai POS Manager
  3. LINE MAN Wongnai LINE MAN Rider LINE MAN Driver Wongnai

    Merchant Wongnai POS React Native Native Android (Kotlin) Wongnai POS Manager
  4. Running Android UI testing in continuous integration is challenging for

    developers, but it's necessary for future scalability of Android apps.
  5. Our previous infrastructure Which isn’t good enough for current requirements

    • Not scalable • Not maintainable • Unstable 🥲 😢 😭
  6. Native Android React Native Marathon Detox Allure Jest Yes No

    UI Testing Integration End-to-end Test Reporting Yes Yes Test Executor Continuous Integration GitLab GitLab
  7. Android Device Provider Marathon Detox Allure Jest Yes No UI

    Testing Integration End-to-end Test Reporting Yes Yes Test Executor tinuous gration tLab tLab
  8. Firebase Test Lab Key Features • Test both Android and

    iOS apps • Real and virtual devices • Google Play Service included • Wide range of supported devices • Test matrix execution is supported Note: Test reports are stored on Google Cloud Storage https://firebase.google.com/products/test-lab
  9. Firebase Test Lab Pricing Virtual device • No-cost up to

    60 min / day • Then $1 / device / hour Physical device • No-cost up to 30 min / day • Then $5 / device / hour
  10. Genymotion Device Image Key Features • Available on well-known cloud

    service providers • Virtual devices without GPU • Remotely control via web browser and HTTP API • Run app for ARM natively with ARM64 instances • Provide SSH and ADB access https://www.genymotion.com
  11. Genymotion Device Image Pricing Depending on the instance size t4g.medium

    • 2 vCPU • 4GB of memory • $0.295 / hr c6g.xlarge • 4 vCPU • 8GB of memory • $0.636 / hr
  12. Smartphone Test Farm Key Features • Open-source project • Remote

    control any device from your browser • Monitor your device inventory • Reserve and release any device with STF API https://github.com/DeviceFarmer/stf
  13. Price Ease of use C ustom Test Executor VPN Stability

    M aintainability C onfigurability Firebase Test Lab Genymotion Device Image Smartphone Test Farm
  14. Run UI Test GitLab Runner Genymotion Device Image on AWS

    EC2 Start Job Create Instance Initialization Test Execution End Job Test Execution Initialization Destroy Instance
  15. Run UI Test GitLab Runner Genymotion Device Image on AWS

    EC2 Start Job Create Instance Initialization Test Execution End Job Test Execution Initialization Destroy Instance
  16. Run UI Test GitLab Runner Genymotion Device Image on AWS

    EC2 Start Job Create Instance Initialization Test Execution End Job Test Execution Initialization Destroy Instance Terraform
  17. Run UI Test GitLab Runner Genymotion Device Image on AWS

    EC2 Start Job Create Instance Initialization Test Execution End Job Test Execution Initialization Destroy Instance Connect ADB Shell Script
  18. Run UI Test GitLab Runner Genymotion Device Image on AWS

    EC2 Start Job Create Instance Initialization Test Execution End Job Test Execution Initialization Destroy Instance Install APKs & Run UI test Collect test result & device log
  19. Run UI Test GitLab Runner Genymotion Device Image on AWS

    EC2 Start Job Create Instance Initialization Test Execution End Job Test Execution Initialization Destroy Instance Terraform
  20. Run UI Test GitLab Runner Genymotion Device Image on AWS

    EC2 Start Job Create Instance Initialization Test Execution End Job Test Execution Initialization Destroy Instance
  21. Run UI Test GitLab Runner Genymotion Device Image on AWS

    EC2 Start Job Create Instance Initialization Test Execution End Job Test Execution Initialization Destroy Instance
  22. Run UI Test GitLab Runner Genymotion Device Image on AWS

    EC2 Start Job Create Instance Initialization Test Execution End Job Test Execution Initialization Destroy Instance Cron Job Destroy instance
  23. Run UI Test GitLab Runner Genymotion Device Image on AWS

    EC2 Start Job Create Instance Initialization Test Execution End Job Test Execution Initialization Destroy Instance Terraform
  24. AMI AWS VPC • AMI: Amazon Machine Image • VPC:

    Virtual Private Cloud Subscribe Launch Genymotion Instance
  25. Original Genymotion AMI • ADB disabled by default • No

    Google Mobile Services • Undesired screen size • No WebView engine • English language by default
  26. All setup operations Enable ADB connection Connect device Change screen

    resolution Change device location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB
  27. Genymotion HTTP API • ADB • Clipboard • Screen resolution

    • Screen orientation • Download, upload, or delete file • Send key, mouse, or tap event • Screenshot • Battery • GPS • And more
  28. All setup operations Enable ADB connection Connect device Change screen

    resolution Change device location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB POST /api/v1/configure/adb { "active": true, "active_on_reboot": true }
  29. All setup operations Enable ADB connection Connect device Change screen

    resolution Change device location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB adb connect <ip_address>
  30. All setup operations Enable ADB connection Connect device Change screen

    resolution Change device location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB POST /api/v1/android/resolution { "width": 720, "height": 1440, "dpi": 300 }
  31. Screen resolution configuration Mobile Tablet • 720 x 1,440 px

    • 384 x 768 dp • 300 DPI • 1,335 x 751 px • 1,335 x 751 dp • 160 DPI
  32. Screen resolution configuration Mobile Tablet • 720 x 1,440 px

    • 384 x 768 dp • 300 DPI • 1,335 x 751 px • 1,335 x 751 dp • 160 DPI https://developer.android.com/reference/android/util/DisplayMetrics
  33. Screen resolution configuration Mobile Tablet • 720 x 1,440 px

    • 384 x 768 dp • 300 DPI • 1,335 x 751 px • 1,335 x 751 dp • 160 DPI https://developer.android.com/reference/android/util/DisplayMetrics DP x (DPI / 160) = PX
  34. All setup operations Enable ADB connection Connect device Change screen

    resolution Change device location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB POST /api/v1/sensors/gps { "latitude": 13.7223497, "longitude": 100.5804235, "altitude": 0, "accuracy": 10, "bearing": 0, "speed": 0 }
  35. All setup operations Enable ADB connection Connect device Change screen

    resolution Change device location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB adb shell setprop persist.sys.local "th-TH"
  36. All setup operations Enable ADB connection Connect device Change screen

    resolution Change device location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB
  37. OpenGApps An open-source initiative that provides Google Apps package Pico

    package • Google Play services https://opengapps.org
  38. All setup operations Enable ADB connection Connect device Change screen

    resolution Change device location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB adb shell wget <download_url> -O /sdcard/Download/opengapps.zip adb shell system/bin/flash-archive.sh /sdcard/Download/opengapps.zip
  39. All setup operations Enable ADB connection Connect device Change screen

    resolution Change device location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB adb shell wget <download_url> -O /sdcard/Download/chrome.zip adb shell pm install -r /sdcard/Download/chrome.apk adb shell wget <download_url> -O /sdcard/Download/maps.zip adb shell pm install -r /sdcard/Download/maps.apk
  40. Enable ADB connection Connect device Change screen resolution Change device

    location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps All setup operations HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB adb reboot adb disconnect
  41. Enable ADB connection Connect device Change screen resolution Change device

    location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps All setup operations HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB
  42. Allow Google’s Location Service Using a shell script and ADB

    to enable Google's Location Service from the Google Maps app
  43. All setup operations Enable ADB connection Connect device Change screen

    resolution Change device location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB adb shell pm grant com.google.android.apps.maps \ android.permission.ACCESS_COARSE_LOCATION adb shell pm grant com.google.android.apps.maps \ android.permission.ACCESS_FINE_LOCATION
  44. All setup operations Enable ADB connection Connect device Change screen

    resolution Change device location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB adb shell uiautomator dump adb pull /sdcard/window_dump.xml
  45. All setup operations Enable ADB connection Connect device Change screen

    resolution Change device location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB adb shell uiautomator dump adb pull /sdcard/window_dump.xml <?xml version='1.0' encoding='UTF-8' standalone='yes' ?> <hierarchy rotation="0"> <node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.android.launcher3" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2072]"> <node index="0" text="" resource-id="" class="android.widget.LinearLayout" package="com.android.launcher3" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false"
  46. All setup operations Enable ADB connection Connect device Change screen

    resolution Change device location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB adb shell uiautomator dump adb pull /sdcard/window_dump.xml <?xml version='1.0' encoding='UTF-8' standalone='yes' ?> <hierarchy rotation="0"> <node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.android.launcher3" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2072]"> <node index="0" text="" resource-id="" class="android.widget.LinearLayout" package="com.android.launcher3" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false"
  47. All setup operations Enable ADB connection Connect device Change screen

    resolution Change device location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB adb shell uiautomator dump adb pull /sdcard/window_dump.xml <?xml version='1.0' encoding='UTF-8' standalone='yes' ?> <hierarchy rotation="0"> <node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.android.launcher3" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2072]"> <node index="0" text="" resource-id="" class="android.widget.LinearLayout" package="com.android.launcher3" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" text="" resource-id="" bounds="[0,0][1080,2072]"
  48. All setup operations Enable ADB connection Connect device Change screen

    resolution Change device location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB adb shell uiautomator dump adb pull /sdcard/window_dump.xml <?xml version='1.0' encoding='UTF-8' standalone='yes' ?> <hierarchy rotation="0"> <node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.android.launcher3" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2072]"> <node index="0" text="" resource-id="" class="android.widget.LinearLayout" package="com.android.launcher3" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" text="SKIP" bounds="[0,0][1080,2072]" Example
  49. All setup operations Enable ADB connection Connect device Change screen

    resolution Change device location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB PATTERN='string(//node[@text="SKIP"][1]/@bounds)' POSITION=$( xmllint --xpath $PATTERN window_dump.xml | awk -F '[\\[\\],]' '{printf("%d %d",($2+$5)/2,($3+$6)/2)}' ) adb shell input tab $POSITION
  50. All setup operations Enable ADB connection Connect device Change screen

    resolution Change device location Change device language Install OpenGApps Install Google Maps and Chrome for Android Reboot the device Reconnect the ADB after device rebooted Grant location permission for Google Maps Allow Google’s Location Service from Google Maps HTTP ADB HTTP HTTP ADB ADB ADB ADB ADB ADB ADB PATTERN='string(//node[@text="SKIP"][1]/@bounds)' POSITION=$( xmllint --xpath $PATTERN window_dump.xml | awk -F '[\\[\\],]' '{printf("%d %d",($2+$5)/2,($3+$6)/2)}' ) adb shell input tab $POSITION
  51. Allow Google’s Location Service • Launch Google Maps app •

    Tap on “SKIP” button • Tap on current location button • Tap on “OK” button • Back to home screen • Start the UI testing
  52. AMI AWS VPC • AMI: Amazon Machine Image • VPC:

    Virtual Private Cloud Subscribe Launch Genymotion Instance Terraform
  53. AMI AWS • AMI: Amazon Machine Image • VPC: Virtual

    Private Cloud Sub Launch VPC Genymotion Instance
  54. AMI AWS • AMI: Amazon Machine Image • VPC: Virtual

    Private Cloud Sub Launch VPC Genymotion Instance Setup Custom AMI Snapshot
  55. AMI AWS • AMI: Amazon Machine Image • VPC: Virtual

    Private Cloud Sub Launch VPC Genymotion Instance Setup Custom AMI Snapshot Packer
  56. GitLab Runner Genymotion Device Image on AWS EC2 Start Job

    Create Instance Initialization Test Execution End Job Test Execution Initialization Destroy Instance Terraform
  57. GitLab Runner Genymotion Device Image on AWS EC2 Start Job

    Pre-configured Instance Initialization Test Execution End Job Test Execution Initialization Destroy Instance Terraform Custom AMI
  58. Summary Now • More scalable and stable CI system for

    Android UI testing • Compatible with any mobile framework for Android app • All of our Android apps have been successfully migrated to this new CI system • Provide teams with a seamless opportunity to implement automated end-to-end testing • Genymotion's monthly costs are highly cost-effective for our CI/CD system's results
  59. Summary On the other side • Genymotion charges by usage

    time. Optimizing UI testing to reduce the time spent will significantly reduce costs for the company. • Working with a Site Reliability Engineer to create the system will take a few months, with additional months needed for improvements. • Running Genymotion with public IP address will be vulnerable to bot script embedding by attackers.