Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
One way to organize UI tests (with Robots)
Search
Daniel
September 06, 2017
Programming
100
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
47
Dependency Injection
danielgomezrico
0
81
Test Robots
danielgomezrico
0
75
(kotlin + patterns ) _ ui-test = happy developer DROIDS4DROIDS
danielgomezrico
0
55
(kotlin + patterns) * ui-tests = happy developer
danielgomezrico
0
60
(Android|iOS) + gitlab ci
danielgomezrico
0
150
Lets talk in / Dilo en Kotlin
danielgomezrico
0
99
Pimp my android project
danielgomezrico
1
79
WTF is origin
danielgomezrico
0
84
Other Decks in Programming
See All in Programming
iOSDC Japan 2026 - Swiftで作って学ぼう!データベース自作入門
kaseken
2
400
手動確認はもう限界 〜XCUITestでCustom URL Schemeの遷移を起動種別ごとに自動テストする〜 / Testing Custom URL Schemes with XCUITest
otouto
0
360
マイコン向けの軽量Ruby「PicoRuby」で各種デバイスを制御するネイティブアプリの実現手法
bash0c7
0
460
速く作れる。その次は、速く確かめられる開発へ 〜AIネイティブ開発を支える、Shift Down〜 / Can build fast. Next, moving to development where we can verify fast.
rkaga
7
5.1k
モジュールの視点からSwiftを読み解く #iosdc
s_shimotori
0
250
巨大モノリシックアプリ モダン化大作戦
ktcryomm
1
1.2k
App Intentsのビルドプロセスを支える技術
kntkymt
0
470
テストを司るデーモンに会いに行く 〜隔離した仮想マシンでテストを通すまで〜
h1d3mun3
1
590
パズルゲームの作り方 / how to make puzzle games
kaityo256
PRO
2
250
Turning Architecture into Unit Tests in the AI Era (NSSpain XIV)
steliosf
PRO
1
120
市販E-Readerを乗っ取れ 〜Embedded Swiftで電子ペーパーガジェットを制御する〜
trickart
0
220
WebRTC映像をAirPlayに対応させる挑戦.pdf
monolithic_adam
0
330
Featured
See All Featured
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
WENDY [Excerpt]
tessaabrams
14
39k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.6k
First, design no harm
axbom
PRO
2
1.3k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.6k
GraphQLとの向き合い方2022年版
quramy
50
15k
Making the Leap to Tech Lead
cromwellryan
135
10k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.5k
A Modern Web Designer's Workflow
chriscoyier
699
190k
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
390
Google's AI Overviews - The New Search
badams
0
1.6k
The SEO Collaboration Effect
kristinabergwall1
1
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!!