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

EspressoのテストをAndroidの最新トレンドに対応させよう / Make Espresso testing follow the cutting edge in Android development

TOYAMA Sumio
February 07, 2019

EspressoのテストをAndroidの最新トレンドに対応させよう / Make Espresso testing follow the cutting edge in Android development

DroidKaigi 2019のセッション「EspressoのテストをAndroidの最新トレンドに対応させよう」の発表スライドです。
サンプルコードのGitHubリポジトリは
https://github.com/sumio/android-sunflower-for-droidkaigi2019
です。

TOYAMA Sumio

February 07, 2019
Tweet

More Decks by TOYAMA Sumio

Other Decks in Programming

Transcript

  1. $ p :  # (TOYAMA Sumio) @sumio_tym (Twitter) /

    @sumio (GitHub) p  : DeNA SWET  (Software Engineer in Test) p :  p : Android "! https://peaks.cc/sumio_tym/android_testing 2
  2. %  3 Espresso(  Android )  "*! 

    AndroidX)  Kotlin& AAC (Android Architecture Components) +#& Kotlin AndroidX AAC Android$&   % ' 
  3. % * p #'&+  p Espresso  p "!

    : Android Sunflower p Espresso Test Recorder) p PageObject"" (, p AAC-$ (" p 4 Kotlin AndroidX AAC Kotlin AndroidX
  4. % * p #'&+  p Espresso  p "!

    : Android Sunflower p Espresso Test Recorder) p PageObject"" (, p AAC-$ (" p 5 Kotlin AndroidX AAC Kotlin AndroidX
  5. : Espresso p Android'+ UI https://developer.android.com/training/testing/espresso/ p ATSL (Android Testing

    Support Library)AndroidX Test # p % -$ p Espresso Test Recorder)    p    ". p * /!(,&   6 () () This logo image is reproduced from work created and shared by the Android Open Source Project (https://developer.android.com/license) and used according to terms described in the Creative Commons 2.5 Attribution License (http://creativecommons.org/licenses/by/2.5/).
  6.  : AndroidX AndroidX = Support Library + Android Testing

    Support Library + Jetpack components https://d.android.com/jetpack/androidx/ p   androidx.*  p     p Android Studio    9
  7.  : AAC (Android Architecture Components) %&" "  !

     #$ https://d.android.com/topic/libraries/architecture/ p 2018  Android Jetpack  10 pViewModel pLiveData pRoom pNavigation pPager pWorkManager...
  8.  ;8   p Espresso p CN62I?H$-AMO95 p API#%!%1J

     p AndroidX p D/  >3B4G7 ("+&.F0 *% p AAC (Android Architecture Components) p E:=),@K<.*'.%L 11
  9. % * p #'&+  p Espresso  p "!

    : Android Sunflower p Espresso Test Recorder) p PageObject"" (, p AAC-$ (" p 12 Kotlin AndroidX AAC Kotlin AndroidX
  10.   :   p Android Studio 3.3 p

       p Use AndroidX artifacts p (LanguageKotlin) 13 AndroidX
  11. build.gradle 15 android { ... testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } dependencies {

    ... androidTestImplementation 'androidx.test:runner:...' androidTestImplementation 'androidx.test.espresso:espresso-core:...' AndroidX
  12.    16  Latest Stable Version() androidx.test:runner 1.1.1

    androidx.test:rules 1.1.1 androidx.test.ext:junit-ktx 1.1.0 androidx.test:core-ktx 1.1.0 androidx.test.espresso:espresso-core 3.1.1 androidx.test.espresso:espresso-contrib 3.1.1 ()2019127  ActivityScenario () AndroidJUnit4() ActivityScenarioRule () AndroidX
  13. KotlinjvmTarget 1.8 : androidx.test.ext:junit-ktxJVM 1.7 17 tasks.withType(org.jetbrains.kotlin.gradle.tasks. KotlinCompile).all { sourceCompatibility

    = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 kotlinOptions { jvmTarget = '1.8' } } AndroidX
  14.    p )(AndroidX'Espresso  p &$" Use AndroidX

    artifacts p .+ Migrate to AndroidX...  p - ,   %  #*! p androidx.test.ext:junit-ktx p androidx.test:core-ktx 19 AndroidX
  15. % * p #'&+  p Espresso  p "!

    : Android Sunflower p Espresso Test Recorder) p PageObject"" (, p AAC-$ (" p 20 Kotlin AndroidX AAC Kotlin AndroidX
  16. ,%*%): Android Sunflower p Android Jetpack (≒AAC)  2 

    ,%*%) https://github.com/googlesamples/android-sunflower p %+(&,/3Kotlin6- 21  " #1 (04 )   .5 ($Android Sunflower%) ),'!#78   Copyright 2018 Google, Inc. Licensed under the Apache License, Version 2.0. Select text used for describing the plants are used from Wikipedia via CC BY-SA 3.0 US.
  17. % * p #'&+  p Espresso  p "!

    : Android Sunflower p Espresso Test Recorder) p PageObject"" (, p AAC-$ (" p 25 Kotlin AndroidX AAC Kotlin AndroidX
  18. Espresso Test Recorder:  #  p Android Studio 3.2

    (AndroidXKotlin! ) p  "    p adb$Android/  26 AndroidX Kotlin
  19. Espresso Test Recorder:    27 KotlinAndroidX  

     p    p    AndroidX Kotlin
  20. Espresso Test Recorder: "&# p /adb'! p  % 

     Android Studio p RunRecord Espresso Test p  %$ p Record Your Test  28 AndroidX Kotlin
  21. Espresso Test Recorder: ' " p ! ' p '

    Record Your Test % ($& 1  #() 29 AndroidX Kotlin
  22. Espresso Test Recorder: Assertion p    p Edit

    assertionSave Assertion 32 AndroidX Kotlin
  23. Espresso Test Recorder:  p Record Your Test  OK

      p Specify a test class for your test    p Test class name: () p Test class language: Kotlin 33 AndroidX Kotlin
  24. Espresso Test Recorder: ATSL or AndroidX Test? Espresso Test Recorder

     ( ) AndroidX   AndroidX Test  ATSL (Android Testing Support Library) AndroidX     34 AndroidX Kotlin
  25. Espresso Test Recorder:     35 Espresso Test

    Recorder   p AndroidJUnit4deprecated p ActivityTestRuledeprecated  () This text is reproduced from work created and shared by the Android Open Source Project (https://developer.android.com/license) and used according to terms described in Apache License, Version 2.0. URL: https://d.android.com/reference/androidx/test/ext/junit/rules/ActivityScenarioRule ()
  26. Espresso Test Recorder: deprecatedAndroidJUnit4 ( import ( ) 36 import

    androidx.test.runner.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4 AndroidX Kotlin
  27. Espresso Test Recorder:    deprecatedAndroidJUnit4  import Show

    Intention Actions (Option+Enter)  37 AndroidX Kotlin
  28. Espresso Test Recorder:    39 @Rule @JvmField var

    mActivityTestRule = ActivityTestRule(GardenActivity::class.java) @get:Rule val activityScenarioRule = activityScenarioRule<GardenActivity>() Java getter    API: activityScenarioRule read-only  AndroidX Kotlin
  29. ActivityTestRule vs ActivityScenarioRule Activity   p ActivityTestRule p ActivityScenarioRule

    41 @get:Rule val activityTestRule = ActivityTestRule(GardenActivity::class.java) @get:Rule val activityScenarioRule = activityScenarioRule<GardenActivity>() AndroidX Kotlin
  30. ActivityTestRule vs ActivityScenarioRule Activity    p ActivityTestRule 42

    @get:Rule val activityTestRule = ActivityTestRule(GardenActivity::class.java, false, false) ... // Activity   activityTestRule.launchActivity(null) AndroidX Kotlin
  31. ActivityTestRule vs ActivityScenarioRule Activity    p ActivityScenario (ActivityScenarioRule)

    43 // Rule    // Activity   launchActivity<GardenActivity>(null).use { ... //   ActivityRESUMED } AndroidX Kotlin
  32. ActivityTestRule vs ActivityScenarioRule ActivityScenario Activity   / 44 //

    Activity launchActivity<GardenActivity>(null) .use { scenario -> scenario.moveToState(State.STARTED) } AndroidX Kotlin scenario.onActivity { ... } (Espresso) 
  33.    p Recorder"%*#  ( ) p "%')

    Test class languageKotlin OK p AndroidX& AndroidX Test  p 2! $ p AndroidJUnit4 ( p ActivityTestRule → ActivityScenario / ActivityScenarioRule 45 AndroidX Kotlin
  34. % * p #'&+  p Espresso  p "!

    : Android Sunflower p Espresso Test Recorder) p PageObject"" (, p AAC-$ (" p 46 Kotlin AndroidX AAC Kotlin AndroidX
  35. Espresso Test Recorder ! 47 Recorder "  p %

           p $   Kotlin PageObject  (#) 
  36. PageObject$$ 2'(,4  https://github.com/SeleniumHQ/selenium/wiki/PageObjects p %6#(Page ) &5 p Page#:

       ! p "$(9/) or )0.+*- p !8 7 Page   p 3Page#! 1 48 Kotlin
  37. Sunflower PageObject MyGardenPage p // goPlantList(): PlantListPage p // plantName

    // assertPlanted(plantName: String): MyGardenPage 49 Kotlin
  38. #3: *0 PageObject ,1 *0 ( !&) (: droidkaigi/step0 1.

    PlantList .$  2. "Avocado" " (PlantDetail .$ ) 3. FAB2 My Garden /'  4. PlantDetail 4 5. My Garden 4 6. "Avocado"%+  -)  53 Kotlin
  39. :   PageObject  Android Studio p Move Line

    Up/Down p RefactorExtractMethod p RefactorExtractVariable 55 Opt + Shift + ↑/↓ Opt + Command + M Opt + Command + V macOS  Kotlin
  40.  :  PageObject ! Android Studio p RefactorInline p

    RefactorMove ( ) p Show Intention Actions 56 macOS  F6 Opt + Enter Opt + Command + N Kotlin
  41.   57 Step1  Step2-4    Page

      (  ) Step5  return value   PageObject
  42. 58 Step1   Step2-4     Page

     (  ) Step5  return value  PageObject
  43. Step1   Page    59 public 

     Extract Method Opt + Command + M Kotlin
  44. 61 Step1   Step2-4     Page

     (  ) Step5  return value  PageObject
  45. Step3    66   childAtPosition (Recorder )

    PageUtils.kt goPlantList MyGardenPage.kt assertPlanted showPlantDetail PlantListPage.kt goBackMyGarden goBackPlantList PlantDetailPage.kt addToMyGarden Kotlin
  46. Step4 object 69 Show Intention Actions    

      Show Intention Actions Opt + Enter Kotlin
  47. 71 Step1   Step2-4     Page

     (  ) Step5  return value  PageObject
  48. 74 Step1   Step2-4     Page

     (  ) Step5  return value  PageObject
  49.  :   p MyGardenPage.assertPlanted() ( '!' # 

    &   p "%$: droidkaigi/extra 78 Kotlin
  50.    p Espresso Test Recorder  PageObject 

     p Android Studio   ( ) p Kotlin Move  79 Kotlin
  51. % * p #'&+  p Espresso  p "!

    : Android Sunflower p Espresso Test Recorder) p PageObject"" (, p AAC-$ (" p 80 Kotlin AndroidX AAC Kotlin AndroidX
  52. % 5'#UI13  * p View.9 p ;)"/(ID )+8,$ 

    p  2 p 4!(-&7:<60    81 AAC AAC 
  53. AAC  ! p Room:  p LiveData RxJava !

    p Pager:   p LivePagedListBuilderRxPagedListBuilder p WorkManager:  82 ArchTaskExecutor Executors. newFixedThreadPool() AAC
  54. AAC  ! p Room:  p LiveData RxJava !

    p Pager:   p LivePagedListBuilderRxPagedListBuilder p WorkManager:  83 ArchTaskExecutor Executors. newFixedThreadPool() AAC
  55. ArchTaskExecutor:    85 AAC @get:Rule val countingRule =

    CountingTaskExecutorRule() @Test fun myTest() { onView(...).perform(...) // AAC   countingRule..drainTasks(1, TimeUnit.MINUTES) onView(...).perform(...) ... }   
  56. ArchTaskExecutor: G S 86 p TaskExecutorWithIdlingResourceRule  p B /

    . / AAC @get:Rule val executorRule = TaskExecutorWithIdlingResourceRule() Rule L: OK
  57. AAC  ! p Room:  p LiveData RxJava !

    p Pager:   p LivePagedListBuilderRxPagedListBuilder p WorkManager:  87 ArchTaskExecutor Executors. newFixedThreadPool() AAC
  58. ArchTaskExecutor :    88 ThreadPoolExecutor  p WorkManager

    import androidx.work.Configuration ... val executor = ... val configuration = Configuration.Builder() .setExecutor(executor) .build() WorkManager.initialize(context, configuration) AAC
  59. ArchTaskExecutor: # $' ! 89 IdlingThreadPoolExecutor"% androidx.test.espresso.idling:idling-concurrent:3.1.1 val executor =

    IdlingThreadPoolExecutor(...) val configuration = Configuration.Builder() .setExecutor(executor) .build() WorkManager.initialize(context, configuration) AAC   & ( https://bit.ly/2Biu8QJ ) 
  60. ArchTaskExecutor:  "  90   (: CoroutineWorker) asCoroutineDispatcher()

     class MyWorker(...): CoroutineWorker(...) { override val coroutineContext: CoroutineDispatcher get() { val executor = IdlingThreadPoolExecutor(...) return executor.asCoroutineDispatcher() } ... AAC CoroutineWorker  ! 
  61.    p AAC(!%     

       '" p ArchTaskExecutor&   p $#Executor&   p Kotlin &   91
  62. % * p #'&+  p Espresso  p "!

    : Android Sunflower p Espresso Test Recorder) p PageObject"" (, p AAC-$ (" p 92 Kotlin AndroidX AAC Kotlin AndroidX
  63. $#  93 p EspressoAndroidXKotlin )"*!  p AndroidX) Recorder

    OK p ,+ 'deprecated -&  (AndroidJUnit4ActivityScenarioRule) p PageObject  Kotlin  (%
  64. !   94 p AAC Espresso%   *"(

     ) p      ' $&#
  65. URL p AndroidX Test https://github.com/android/android-test p Yuki AnzaiAndroidX Testin Android

    Dev Summit 2018  https://speakerdeck.com/yanzm/androidx-test p AndroidX Test   https://developer.android.com/jetpack/androidx/releases/test 95
  66. "URL ( ( +) p !) Espresso &#% in DroidKaigi

    2017 https://droidkaigi.github.io/2017/timetable.html#session-26 p  Espresso $ ' in DroidKaigi 2018 https://droidkaigi.jp/2018/timetable?session=16928 p *Android(+) https://peaks.cc/sumio_tym/android_testing 96