Upgrade to Pro — share decks privately, control downloads, hide ads and more …

KotlinでEspressoテストがもっと書きやすくなるKakaoを試してみた / Trying Kakao which makes Espresso test easier to write

KotlinでEspressoテストがもっと書きやすくなるKakaoを試してみた / Trying Kakao which makes Espresso test easier to write

2018/3/19開催のAndroid Test Night #3の発表資料です。

TOYAMA Sumio

March 19, 2018
Tweet

More Decks by TOYAMA Sumio

Other Decks in Programming

Transcript

  1. Kotlin Espresso


    Kakao
    2018.03.19
    (sumio)

    View Slide

  2. 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

    View Slide


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

    View Slide

  4. 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,
    *(

    View Slide

  5. 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

    View Slide


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

    View Slide


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

    View Slide



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

    View Slide



  9. 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

    View Slide

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

    View Slide

  11. 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

    View Slide

  12. 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

    View Slide

  13. 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

    View Slide

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

    (KRecyclerItem)
    14

    View Slide

  15. 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

    View Slide


  16. 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)}
    }
    }

    View Slide

  17. ( 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
    (

    View Slide

  18. 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)}
    }
    }
    (

    View Slide

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

    View Slide

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


    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  24. RecyclerView

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

    KRecyclerItem



    View Slide

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

    View Slide

  26. RecyclerView

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



    View Slide

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

    perform

    View Slide

  28. :
    pEspresso

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

    View Slide

  29. 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

    View Slide


  30. pEspresso KotlinDSL7
    KakaoG?

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

    View Slide



  31. 31

    View Slide