Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
One way to organize UI tests (with Robots)
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Daniel
September 06, 2017
Programming
94
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
One way to organize UI tests (with Robots)
Slides for meetup:
https://www.meetup.com/es-ES/Medellin-Android/events/242937374/
Daniel
September 06, 2017
More Decks by Daniel
See All by Daniel
Dependency Inversion from S to D (SOLID)
danielgomezrico
0
41
Dependency Injection
danielgomezrico
0
77
Test Robots
danielgomezrico
0
69
(kotlin + patterns ) _ ui-test = happy developer DROIDS4DROIDS
danielgomezrico
0
50
(kotlin + patterns) * ui-tests = happy developer
danielgomezrico
0
58
(Android|iOS) + gitlab ci
danielgomezrico
0
140
Lets talk in / Dilo en Kotlin
danielgomezrico
0
96
Pimp my android project
danielgomezrico
1
76
WTF is origin
danielgomezrico
0
81
Other Decks in Programming
See All in Programming
Dataformのリポジトリを立ち上げるときにまずやること / dataform-day0-2026
snhryt
0
190
任せる範囲はこう広がった / How the Scope of AI Delegation Has Expanded
nrslib
0
160
技術記事、 専門家としてのプログラマ、 言語化
mizchi
13
6.6k
エンジニア向け会社紹介/Findy Company Profile
findyinc
6
350k
ふつうのFeature Flag実践入門
irof
8
4.2k
Vite+ Unified Toolchain for the Web
naokihaba
0
360
Mujeres en SEO Summit 2026 - Greatest Disaster Hits en Web Performance
guaca
0
210
LLMによるContent Moderationの本番運用の裏側と品質担保への挑戦
suikabar
3
790
Observability in Practice:Grafana 與 Edge Device SRE 的那些事
blueswen
0
180
Spring Security 実践 ─ GraphQL APIで実務に役立つ 認証・認可 を学ぶ
wagyu
0
260
軽量Java基盤の設計 DIコンテナに頼らない、長期保守と1秒起動の実現 JJUG CCC 2026 Spring
macha64
0
600
Datadog × OpenTelemetry 入門と実践のあいだ
kn_to_maxpno
1
180
Featured
See All Featured
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
250
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
310
Optimizing for Happiness
mojombo
378
71k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
210
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.9k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
52k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
55
3.4k
AI: The stuff that nobody shows you
jnunemaker
PRO
8
740
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
580
Transcript
A way to organize UI tests Daniel Gomez Rico Android
Lead Developer at Barista Ventures @aquicaipivara With UI Robots…
1. Login Example app 2. Main
Tests UI / otro Framework Tests without robots
@Test fun test_login_showMainView() { Espresso.onView(ViewMatchers.withId(R.id.loginUsernameEditText)) .perform(ViewActions.typeText("
[email protected]
"), ViewActions.closeSoftKeyboard()) Espresso.onView(ViewMatchers.withId(R.id.loginPasswordEditText)) .perform(ViewActions.typeText("12345678"),
ViewActions.closeSoftKeyboard()) Espresso.onView(ViewMatchers.withId(R.id.loginSubmitButton)).perform(ViewActions.click()) Espresso.onView(ViewMatchers.withText("Login")) .check(ViewAssertions.matches(ViewMatchers.isDisplayed())) } Without robots
Tests UI Or another Framework Tests without robots
Tests UI Tests with robots… UI Robots
@Test fun test_login_showMainView() { Espresso.onView(ViewMatchers.withId(R.id.loginUsernameEditText)) .perform(ViewActions.typeText("
[email protected]
"), ViewActions.closeSoftKeyboard()) Espresso.onView(ViewMatchers.withId(R.id.loginPasswordEditText)) .perform(ViewActions.typeText("12345678"),
ViewActions.closeSoftKeyboard()) Espresso.onView(ViewMatchers.withId(R.id.loginSubmitButton)) .perform(ViewActions.click()) Espresso.onView(ViewMatchers.withText("Login")) .check(ViewAssertions.matches(ViewMatchers.isDisplayed())) } Without robot Sample 1/3
@Test fun test_login_showMainView() { Espresso.onView(ViewMatchers.withId(R.id.loginUsernameEditText)) .perform(ViewActions.typeText("
[email protected]
"), ViewActions.closeSoftKeyboard()) Espresso.onView(ViewMatchers.withId(R.id.loginPasswordEditText)) .perform(ViewActions.typeText(“007"),
ViewActions.closeSoftKeyboard()) Espresso.onView(ViewMatchers.withId(R.id.loginSubmitButton)) .perform(ViewActions.click()) Espresso.onView(ViewMatchers.withText(“Main")) .check(ViewAssertions.matches(ViewMatchers.isDisplayed())) } MainRobot Looks like actions from a Login View -> LoginRobot
class LoginTests { @Test fun test_login_showMainView() { val mainRobot =
loginRobot.writeEmail("
[email protected]
") .writePassword(“007") .clickLoginButton() // Returns MainRobot mainRobot.checkIsVisible() } } With robots… Sample 1/3
class MainTests { @Test fun test_onLogout_showLoginView() { val mainRobot
= loginRobot.performLoginFlow() //return MainRobot mainRobot.clickLogoutButton() loginRobot.checkIsVisible() } } With robots… Sample 2/3
class LoginTestsWithoutRobot { @Test fun test_login_showMainView() { Espresso.onView(ViewMatchers.withId(R.id.loginUsernameEditText)) .perform(ViewActions.typeText("
[email protected]
"),
ViewActions.closeSoftKeyboard()) Espresso.onView(ViewMatchers.withId(R.id.loginPasswordEditText)) .perform(ViewActions.typeText("12345678"), ViewActions.closeSoftKeyboard()) Espresso.onView(ViewMatchers.withId(R.id.loginSubmitButton)).perform(ViewActions.click()) Espresso.onView(ViewMatchers.withText("Login")) .check(ViewAssertions.matches(ViewMatchers.isDisplayed())) } @Test fun test_login_withEmptyEmail_showsError() { Espresso.onView(ViewMatchers.withId(R.id.loginUsernameEditText)) .perform(ViewActions.typeText(""), ViewActions.closeSoftKeyboard()) Espresso.onView(ViewMatchers.withId(R.id.loginPasswordEditText)) .perform(ViewActions.typeText("12345678"), ViewActions.closeSoftKeyboard()) Espresso.onView(ViewMatchers.withId(R.id.loginSubmitButton)).perform(ViewActions.click()) Espresso.onView(ViewMatchers.withId(R.id.loginUsernameEditText)) .check(ViewAssertions.matches(CustomMatchers.withError())) } @Test fun test_login_withEmptyPassword_showsError() { Espresso.onView(ViewMatchers.withId(R.id.loginUsernameEditText)) .perform(ViewActions.typeText("
[email protected]
"), ViewActions.closeSoftKeyboard()) Espresso.onView(ViewMatchers.withId(R.id.loginPasswordEditText)) .perform(ViewActions.typeText(""), ViewActions.closeSoftKeyboard()) Espresso.onView(ViewMatchers.withId(R.id.loginSubmitButton)).perform(ViewActions.click()) Espresso.onView(ViewMatchers.withId(R.id.loginPasswordEditText)) .check(ViewAssertions.matches(CustomMatchers.withError())) } } Without robot Sample 3/3
@Test fun test_login_showMainView() { val mainRobot = loginRobot.writeEmail("
[email protected]
") .writePassword("007") .clickLoginButton()
// Returns MainRobot mainRobot.checkIsVisible() } @Test fun test_login_withEmptyEmail_showsError() { loginRobot.writeEmail("") .writePassword("123") .clickLoginButton() loginRobot.checkEmailHaveError() } @Test fun test_login_withEmptyPassword_showsError() { loginRobot.writeEmail("
[email protected]
") .writePassword("") .clickLoginButton() loginRobot.checkPasswordHaveError() } With robots… Sample 3/3
class NewQuestionActivityTest { @Test fun newQuestionTest() { val mainRobot
= onBoardingRobot.clickLoginButton() .performLoginFlow() val newQuestionRobot = mainRobot.clickNewQuestionFab() val creditCardRobot = newQuestionRobot.writeDescription(getRandomQuestion()) .selectSubtopic(0) .selectExpert(0) .clickSubmitButton() .clickRushPaymentOption() .clickOkButton() val mainRobot = creditCardRobot.performSuccessFlow() mainRobot.validateIsVisible() } } With robots… “Big” test
fun selectSubtopic(index: Int) { click(R.id.newQuestionSubtopicsEditText) clickListItemDialogItem(index) } fun click(@IdRes id:
Int) { onView(withId(id)).perform(ViewActions.click()) } private fun clickListItemDialogItem(index: Int) { val action = RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(index, ViewActions.click()) Espresso.onView(ViewMatchers.withId(R.id.checkDialogRecyclerView)).perform(action) clickViewWithText("OK") } protected fun clickViewWithText(text: String) { screenshot("before_click") onView(allOf<View>(withText(text), isDisplayed())).perform(ViewActions.click()) screenshot("click") }
The UI Robot Sample project https://github.com/caipivara/androidmeetup-ui-robots Check
- https://academy.realm.io/posts/kau-jake-wharton-testing-robots/ - Android Dialogs (Sam Edwards: Espresso Robots +
Screenshots): https://www.youtube.com/watch?v=vsrX0gGZp3o - Sample: https://github.com/caipivara/androidmeetup-ui-robots - Icons: https://www.iconfinder.com/icons/58995/ lionel_preacherbot_robot_icon References
Gracias!!