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
99
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
43
Dependency Injection
danielgomezrico
0
78
Test Robots
danielgomezrico
0
74
(kotlin + patterns ) _ ui-test = happy developer DROIDS4DROIDS
danielgomezrico
0
53
(kotlin + patterns) * ui-tests = happy developer
danielgomezrico
0
59
(Android|iOS) + gitlab ci
danielgomezrico
0
140
Lets talk in / Dilo en Kotlin
danielgomezrico
0
98
Pimp my android project
danielgomezrico
1
77
WTF is origin
danielgomezrico
0
83
Other Decks in Programming
See All in Programming
AI Agent時代のリアーキテクチャ戦略と実践
hokaccha
1
640
Vibes Containers 〜AIで変わるコンテナ設計と運用〜
tkikuc
2
500
AIに既存システムを理解させる技術 ~レガシーを見捨てないハーネスエンジニアリング入門~
ochtum
0
210
FastAPI の並行処理モデルを完全に理解する
hoto17296
9
3.8k
【デモ】Kiroで体験する仕様駆動開発|設計からコーディングまでAIと進める開発フロー
cmkudo
0
600
kubernetes コンポーネント開発入門 / 新卒N年目の勉強会&交流会!〜〇〇への誘い〜 #n_study
mazrean
0
180
Swift愛好会100回記念 第1回を振り返る
jollyjoester
0
120
AIと壁打ちしながら進めるコスト管理
fufuhu
2
1.9k
XHTMLが残したもの
yosuke_furukawa
PRO
2
440
Press start. Python's next generation.
willingc
PRO
3
320
[GoCon2026] When Goroutines Are Not Enough: Runtime Locality in High-Throughput Go
takehaya
4
580
フロントエンドUIフレームワークのこれまでとこれから
ssssota
1
700
Featured
See All Featured
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
270
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
260
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.5k
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
660
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.4k
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
470
Un-Boring Meetings
codingconduct
0
410
ラッコキーワード サービス紹介資料
rakko
1
4.8M
Large-scale JavaScript Application Architecture
addyosmani
515
110k
The Limits of Empathy - UXLibs8
cassininazir
1
640
BBQ
matthewcrist
89
10k
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!!