📜 ⬆️ ⬇️

Kakao - how to make UI testing great again

image

At Agoda, we pay a lot of attention to various types of testing our code. This helps us ensure its stability and find possible product problems at an early stage.

At the moment, testing the user interface on Android for us is a small personal affiliate of hell. Google provides us with Espresso along with several extensions, UI automator and so on. And although the tools do an excellent job with the task entrusted to them, they do it not very beautifully. When you need to test a case that is different from a simple click on a button, your test code turns into a mess that is difficult to read. Just take a look:
')
@Test public void espressoTest() { onView(allOf(allOf(withId(R.id.label_bf_hotelname), isDescendantOfA(withId(R.id.custom_view_trip_review))), isDescendantOfA(withId(R.id.contentView)))) .check(matches(withEffectiveVisibility(View.VISIBLE))); } 

For me, this code looks unreadable. It is very difficult to support the work of more than 1000 UI tests of our Android application with a similar syntax. But Google announced the official support of the Kotlin language as a language for Android development at the Google I / O 2017 conference. Then we thought: “But we can try to migrate our tests to Kotlin!”

But simply translating code from Java to Kotlin does not solve our problem with the readability of tests, since we are still dependent on Espresso. Fortunately, Kotlin provides us with many tools for creating a DSL. With this in mind, we presented how our UI tests should look like on Kotlin. We wanted the test to look higher like this:

 @Test fun espressoTest() { screen { hotelName { isVisible() } } } 

Looks great, don't you think so? Much more readable and easily understood code than using Espresso. And in most situations more compact. Have we managed to achieve this syntax? And how!

image

Meet Kakao - a simple Kotlin DSL for Android UI test with Espresso. Kakao provides a convenient syntax for creating UI tests using abstraction of your Activity / Fragment or View through the Screen class.

 open class TestActivityScreen: Screen<TestActivityScreen>() { val content: KView = KView { withId(R.id.content) } val map: KView = KView { withId(R.id.map) } val button: KButton = KButton { withId(R.id.button) } val textViewLarge: KTextView = KTextView { withId(R.id.text_view_large) } val textViewSmall: KTextView = KTextView { withId(R.id.text_view_small) } } 

To start using Kakao, you must include Kotlin support in your project. You can find all the information you need to do this on developer.android.com . Then you need to declare your hierarchy of interface elements using the classes that the library provides. All these classes (KView, KTextView, KButton) are empty classes that inherit the logic of interfaces: actions (actions) and assertions (Assertions). The library also provides helper classes for creating DSL-style matcher. One of these classes is called ViewBuilder and is used in the constructors of all KView heirs.

 class KTextView : KBaseView<KTextView>, TextViewAssertions { constructor(function: ViewBuilder.() -> Unit): super(function) constructor(parent: Matcher<View>, function: ViewBuilder.() -> Unit): super(parent, function) constructor(parent: DataInteraction, function: ViewBuilder.() -> Unit): super(parent, function) } 

After declaring the user interface hierarchy, you can directly access the Screen object and all KView objects in it using the invoke operator and perform various actions or statements in a cascading style:

 @RunWith(AndroidJUnit4::class) class TestActivityTest { @Rule @JvmField val rule = ActivityTestRule(TestActivity::class.java) val screen = TestActivityScreen() @Test fun test() { screen { content { isVisible() } textViewLarge { click() isVisible() hasAnyText() } textViewSmall { isVisible() hasAnyText() } map { click() hasAnyTag("test_tag", "non_test_tag") } button { hasText("BUTTON") } } } } 

We have already translated most of our tests for using Kakao and are very pleased with the result. The library also supports more complex constructs such as RecyclerView, ListView, WebView, and so on. It also has a convenient approach to customization, allowing you to easily create your own KView implementations with a different set of actions and statements, nested elements and logic.

We decided to release this tool publicly so that other developers could start writing UI tests on Kotlin without needing to adhere to the Espresso syntax, which we think is outdated.

You can connect Kakao to your project by simply adding this line to your build.gradle:

 androidTestCompile 'com.agoda.kakao:kakao:1.0.0' 

Join us on GitHub , rate Kakao and let's do UI testing again great! Happy testing!

Source: https://habr.com/ru/post/339664/


All Articles