Bumble Tech
Published in

Bumble Tech

Photo by Jeremy Bishop on Unsplash

Automating Android Jetpack Compose using Appium

But first, what is Jetpack Compose?

Jetpack Compose is the modern toolkit for building native Android UI. Traditionally, Android UI has been created using XML layouts. But with Jetpack Compose XMLs are a thing of the past. With Jetpack Compose, UI is defined as composable functions written in Kotlin. It is concise, declarative, and much more developer-friendly than XMLs. Given that it has so many advantages, it may well become the first-class framework for writing Android UI.

Is, there any alternative in Appium?

Yes, there is— UiAutomator2. The UiAutomator2 testing framework relies on accessibility services. The Semantics tree corresponding to the Jetpack Compose’s composition is understandable for Accessibility services. Therefore, UiAutomator2 can see the semantics tree and find the elements e.g: by using accessibility identifiers (or content description). Appium has a driver built on top of the UiAutomator — appium-uiautomator2-driver. There is also some basic support of UiAutomator APIs in Appium-Espresso-driver and we started using it as a stop-gap.

// Test rules and transitive dependencies:androidTestImplementation("androidx.compose.ui:ui-test-junit4:$compose_version")// Needed for createComposeRule, but not createAndroidComposeRule:debugImplementation("androidx.compose.ui:ui-test-manifest:$compose_version")

Using Appium to automate Compose

The prerequisite for all of this is that you have to be using Appium’s espresso driver. To do this, set automationName capability to espresso.

driver.setSetting(“driver”, “compose”);
driver.setSetting(“driver”, “espresso”);
espressoBuildConfig: ‘{“additionalAndroidTestDependencies”: [“androidx.lifecycle:lifecycle-extensions:<version>”, “androidx.activity:activity:<version>”, “androidx.fragment:fragment:<version>”]}’

The Complete Example

This example is in ruby but can be applied to any other programming language of your choice.

require 'appium_lib'

def android_compose_caps()
{
platformName: 'Android',
deviceName: 'emulator-5556',
app: 'compose_playground.apk',
automationName: 'espresso',
newCommandTimeout: 0,
skipUnlock: true,
fullReset: false,
forceEspressoRebuild: true,
showGradleLog: true,
espressoBuildConfig: '{"additionalAndroidTestDependencies": ["androidx.lifecycle:lifecycle-extensions:2.2.0", "androidx.activity:activity:1.3.1", "androidx.fragment:fragment:1.2.0"]}'
}
end

@driver = Appium::Driver.new({ caps: android_compose_caps }, false)
@driver.start_driver

# click on the button with text 'Clickable Component'.
# This will later load a Compose screen with a clickable button
non_compose_button
= @driver.find_element(xpath: "//*[@text='Clickable Component']")
non_compose_button.click

# Change the drive context to 'compose' because now we are on a Compose screen
@driver.update_settings({'driver' => 'compose'})

# We can find Compose button using it's text with XPATH!
button
= @driver.find_element(xpath: "//*[@text='Click to see dialog']")

# we could also find the button using content-description as below
# button =
@driver.find_element(accessibility_id: "desc")

fail
("Text mismatch") unless button.text == 'Click to see dialog'

--

--

We’re the tech team behind social networking apps Bumble and Badoo. Our products help millions of people build meaningful connections around the world.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store