Slide 1

Slide 1 text

Kotlin Espresso Kakao 2018.03.19 (sumio)

Slide 2

Slide 2 text

04. p(': # 3 (TOYAMA Sumio) @sumio_tym (Twitter) / @sumio (GitHub) p$1: DeNA SWET (Software Engineer in Test) p%): p+/!: pDroidKaigi 2016-2018: Espresso UIAutomator p@IT2&,* (UI Automator / Appium-") 2

Slide 3

Slide 3 text

, Espresso: AndroidUI$"%#' Kotlin: Android+*0-1 75)24( KotlinEspresso$"%!& . #' Kakao/ 63 3

Slide 4

Slide 4 text

Espresso pAndroid%+UI Android Open Source Project, licensed under the Apache License, Version 2.0 https://d.android.com/training/testing/espresso/index.html 4 https://developer.android.com/training/testing/espresso/index.html &$ onView(ViewMatcher) .perform(ViewAction) .check(ViewAssertion); p ViewMatcherView" p ViewAction#!') p ViewViewAssertion, *(

Slide 5

Slide 5 text

Kakao pAgoda 2017, licensed under the Apache License, Version 2.0 GitHub(): https://github.com/agoda-com/Kakao API doc: https://goo.gl/ThVN6J pGitHub! : Nice and simple DSL for Espresso in Kotlin p Iñaki VillarOne Espresso with Kotlin, please in GDG DevFest Bangkok 2017 https://speakerdeck.com/cdsap/one-espresso-with-kotlin-please 5 https://github.com/agoda-com/Kakao/blob/1.2.1/README.md

Slide 6

Slide 6 text

6 repositories { jcenter() } dependencies { androidTestImplementation 'com.agoda.kakao:kakao:1.2.1' } ! Espresso3.0.1 )' RecyclerView GitHubmaster#(" % (1.2.1 &$)

Slide 7

Slide 7 text

7 @Rule @JvmField val rule = ActivityTestRule(MyActivity::class.java) val screen = MyActivityScreen() @Test fun myKakaoTest() { screen { myButton { click() } myTextView { hasText("Clicked!") } } }

Slide 8

Slide 8 text

8 @Rule @JvmField val rule = ActivityTestRule(MyActivity::class.java) val screen = MyActivityScreen() @Test fun myKakaoTest() { screen { myButton { click() } myTextView { hasText("Clicked!") } } } screen Screen(UI)

Slide 9

Slide 9 text

9 @Rule @JvmField val rule = ActivityTestRule(MyActivity::class.java) val screen = MyActivityScreen() @Test fun myKakaoTest() { screen { myButton { click() } myTextView { hasText("Clicked!") } } } perform(ViewAction) check(ViewAssertion) Kakao

Slide 10

Slide 10 text

Screen 10 open class MyActivityScreen: Screen() { val myButton: KButton = KButton { withId(R.id.button) withText("OK") } val myTextView: KTextView = KTextView { withId(R.id.textView) } }

Slide 11

Slide 11 text

Screen 11 open class MyActivityScreen: Screen() { val myButton: KButton = KButton { withId(R.id.button) withText("OK") } val myTextView: KTextView = KTextView { withId(R.id.textView) } } Screen

Slide 12

Slide 12 text

Screen 12 open class MyActivityScreen: Screen() { val myButton: KButton = KButton { withId(R.id.button) withText("OK") } val myTextView: KTextView = KTextView { withId(R.id.textView) } } ViewKakao KBaseView https://goo.gl/qveQ48

Slide 13

Slide 13 text

Screen 13 open class MyActivityScreen: Screen() { val myButton: KButton = KButton { withId(R.id.button) withText("OK") } val myTextView: KTextView = KTextView { withId(R.id.textView) } } onView(ViewViewMatcher) AND

Slide 14

Slide 14 text

RecyclerView Espresso: RecyclerViewActions p : ( ) Kakao: KRecycler{View,Item} p (KRecyclerItem) 14

Slide 15

Slide 15 text

KRecyclerItem) 15 Title 0 OK Title 4 OK Title 3 OK Title 2 OK Title 1 OK Title 0 OK R.id.title R.id.button ( Title 0 Clicked

Slide 16

Slide 16 text

KRecyclerItem) 16 open class MyRecyclerScreen : Screen() { ... class Item(parent: Matcher) : KRecyclerItem(parent) { val title: KTextView = KTextView(parent) {withId(R.id.title)} val button: KButton = KButton(parent) {withId(R.id.button)} } }

Slide 17

Slide 17 text

( KRecyclerItem) 17 open class MyRecyclerScreen : Screen() { ... class Item(parent: Matcher) : KRecyclerItem(parent) { val title: KTextView = KTextView(parent) {withId(R.id.title)} val button: KButton = KButton(parent) {withId(R.id.button)} } } KRecyclerItem (

Slide 18

Slide 18 text

KRecyclerItem) 18 open class MyRecyclerScreen : Screen() { ... class Item(parent: Matcher) : KRecyclerItem(parent) { val title: KTextView = KTextView(parent) {withId(R.id.title)} val button: KButton = KButton(parent) {withId(R.id.button)} } } (

Slide 19

Slide 19 text

RecyclerViewScreen 19 open class MyRecyclerScreen : Screen() { val recycler: KRecyclerView = KRecyclerView({ withId(R.id.recycler_view) }, itemTypeBuilder = { itemType(::Item) } ); class Item(parent: Matcher) : KRecyclerItem(parent) { ... } }

Slide 20

Slide 20 text

RecyclerViewScreen 20 open class MyRecyclerScreen : Screen() { val recycler: KRecyclerView = KRecyclerView({ withId(R.id.recycler_view) }, itemTypeBuilder = { itemType(::Item) } ); class Item(parent: Matcher) : KRecyclerItem(parent) { ... } }

Slide 21

Slide 21 text

RecyclerView 21 val screen = MyRecyclerScreen() @Test fun testRecyclerView() { screen { recycler { childAt(0) { title { hasText("Title 0") } button { click() hasText("Clicked") } }}}}

Slide 22

Slide 22 text

RecyclerView 0 22 val screen = MyRecyclerScreen() @Test fun testRecyclerView() { screen { recycler { childAt(0) { title { hasText("Title 0") } button { click() hasText("Clicked") } }}}}

Slide 23

Slide 23 text

RecyclerView 0 23 val screen = MyRecyclerScreen() @Test fun testRecyclerView() { screen { recycler { childAt(0) { title { hasText("Title 0") } button { click() hasText("Clicked") } }}}}

Slide 24

Slide 24 text

RecyclerView 24 val screen = MyRecyclerScreen() @Test fun testRecyclerView() { screen { recycler { childAt(0) { title { hasText("Title 0") } button { click() hasText("Clicked") } }}}} KRecyclerItem

Slide 25

Slide 25 text

RecyclerView 25 val screen = MyRecyclerScreen() @Test fun testRecyclerView() { screen { recycler { childWith { withDescendant { withText("Title 0") } } perform { title { ... } button { ... }}}}}

Slide 26

Slide 26 text

RecyclerView 26 val screen = MyRecyclerScreen() @Test fun testRecyclerView() { screen { recycler { childWith { withDescendant { withText("Title 0") } } perform { title { ... } button { ... }}}}}

Slide 27

Slide 27 text

RecyclerView 27 val screen = MyRecyclerScreen() @Test fun testRecyclerView() { screen { recycler { childWith { withDescendant { withText("Title 0") } } perform { title { ... } button { ... }}}}} childWith() perform

Slide 28

Slide 28 text

: pEspresso pespresso-intent: KIntent p: https://goo.gl/ZiHuY3 pespresso-web: KWebView p: https://goo.gl/mfNYMa 28

Slide 29

Slide 29 text

0)* pEspressoAPI 4 +% !13.( p KBaseView: https://goo.gl/qveQ48 p ViewBuilder: https://goo.gl/esEMsf p BaseAction : https://goo.gl/wNB82F p BaseAssertions : https://goo.gl/3rYFMQ pEspresso'API#/$& p -)Espresso API2 "API, (matches / assert / act) 29

Slide 30

Slide 30 text

pEspresso KotlinDSL7 KakaoG? p$!#DSL( pRecyclerView@B/+< pAPI9ED%; (API docC3 ) p42.=1-2*F 6 A0) ,> p2018&3'5:8*" 30

Slide 31

Slide 31 text

31