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

17997dee8a3da090f62d8cf8c494d8ff?s=47 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
です。

17997dee8a3da090f62d8cf8c494d8ff?s=128

TOYAMA Sumio

February 07, 2019
Tweet

Transcript

  1. 2.

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

    %  3 Espresso(  Android )  "*! 

    AndroidX)  Kotlin& AAC (Android Architecture Components) +#& Kotlin AndroidX AAC Android$&   % ' 
  3. 4.

    % * p #'&+  p Espresso  p "!

    : Android Sunflower p Espresso Test Recorder) p PageObject"" (, p AAC-$ (" p 4 Kotlin AndroidX AAC Kotlin AndroidX
  4. 5.

    % * p #'&+  p Espresso  p "!

    : Android Sunflower p Espresso Test Recorder) p PageObject"" (, p AAC-$ (" p 5 Kotlin AndroidX AAC Kotlin AndroidX
  5. 6.

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

     : AndroidX AndroidX = Support Library + Android Testing

    Support Library + Jetpack components https://d.android.com/jetpack/androidx/ p   androidx.*  p     p Android Studio    9
  7. 10.

     : AAC (Android Architecture Components) %&" "  !

     #$ https://d.android.com/topic/libraries/architecture/ p 2018  Android Jetpack  10 pViewModel pLiveData pRoom pNavigation pPager pWorkManager...
  8. 11.

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

    % * p #'&+  p Espresso  p "!

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

      :   p Android Studio 3.3 p

       p Use AndroidX artifacts p (LanguageKotlin) 13 AndroidX
  11. 15.

    build.gradle 15 android { ... testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } dependencies {

    ... androidTestImplementation 'androidx.test:runner:...' androidTestImplementation 'androidx.test.espresso:espresso-core:...' AndroidX
  12. 16.

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

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

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

    % * p #'&+  p Espresso  p "!

    : Android Sunflower p Espresso Test Recorder) p PageObject"" (, p AAC-$ (" p 20 Kotlin AndroidX AAC Kotlin AndroidX
  16. 21.

    ,%*%): 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. 25.

    % * p #'&+  p Espresso  p "!

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

    Espresso Test Recorder:  #  p Android Studio 3.2

    (AndroidXKotlin! ) p  "    p adb$Android/  26 AndroidX Kotlin
  19. 27.

    Espresso Test Recorder:    27 KotlinAndroidX  

     p    p    AndroidX Kotlin
  20. 28.

    Espresso Test Recorder: "&# p /adb'! p  % 

     Android Studio p RunRecord Espresso Test p  %$ p Record Your Test  28 AndroidX Kotlin
  21. 29.

    Espresso Test Recorder: ' " p ! ' p '

    Record Your Test % ($& 1  #() 29 AndroidX Kotlin
  22. 32.

    Espresso Test Recorder: Assertion p    p Edit

    assertionSave Assertion 32 AndroidX Kotlin
  23. 33.

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

    Espresso Test Recorder: ATSL or AndroidX Test? Espresso Test Recorder

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

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

    Espresso Test Recorder: deprecatedAndroidJUnit4 ( import ( ) 36 import

    androidx.test.runner.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4 AndroidX Kotlin
  27. 37.

    Espresso Test Recorder:    deprecatedAndroidJUnit4  import Show

    Intention Actions (Option+Enter)  37 AndroidX Kotlin
  28. 39.

    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. 40.
  30. 41.

    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
  31. 42.

    ActivityTestRule vs ActivityScenarioRule Activity    p ActivityTestRule 42

    @get:Rule val activityTestRule = ActivityTestRule(GardenActivity::class.java, false, false) ... // Activity   activityTestRule.launchActivity(null) AndroidX Kotlin
  32. 43.

    ActivityTestRule vs ActivityScenarioRule Activity    p ActivityScenario (ActivityScenarioRule)

    43 // Rule    // Activity   launchActivity<GardenActivity>(null).use { ... //   ActivityRESUMED } AndroidX Kotlin
  33. 44.

    ActivityTestRule vs ActivityScenarioRule ActivityScenario Activity   / 44 //

    Activity launchActivity<GardenActivity>(null) .use { scenario -> scenario.moveToState(State.STARTED) } AndroidX Kotlin scenario.onActivity { ... } (Espresso) 
  34. 45.

       p Recorder"%*#  ( ) p "%')

    Test class languageKotlin OK p AndroidX& AndroidX Test  p 2! $ p AndroidJUnit4 ( p ActivityTestRule → ActivityScenario / ActivityScenarioRule 45 AndroidX Kotlin
  35. 46.

    % * p #'&+  p Espresso  p "!

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

    Espresso Test Recorder ! 47 Recorder "  p %

           p $   Kotlin PageObject  (#) 
  37. 48.

    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
  38. 49.

    Sunflower PageObject MyGardenPage p // goPlantList(): PlantListPage p // plantName

    // assertPlanted(plantName: String): MyGardenPage 49 Kotlin
  39. 53.

    #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
  40. 55.

    :   PageObject  Android Studio p Move Line

    Up/Down p RefactorExtractMethod p RefactorExtractVariable 55 Opt + Shift + ↑/↓ Opt + Command + M Opt + Command + V macOS  Kotlin
  41. 56.

     :  PageObject ! Android Studio p RefactorInline p

    RefactorMove ( ) p Show Intention Actions 56 macOS  F6 Opt + Enter Opt + Command + N Kotlin
  42. 57.

      57 Step1  Step2-4    Page

      (  ) Step5  return value   PageObject
  43. 58.

    58 Step1   Step2-4     Page

     (  ) Step5  return value  PageObject
  44. 59.

    Step1   Page    59 public 

     Extract Method Opt + Command + M Kotlin
  45. 61.

    61 Step1   Step2-4     Page

     (  ) Step5  return value  PageObject
  46. 66.

    Step3    66   childAtPosition (Recorder )

    PageUtils.kt goPlantList MyGardenPage.kt assertPlanted showPlantDetail PlantListPage.kt goBackMyGarden goBackPlantList PlantDetailPage.kt addToMyGarden Kotlin
  47. 69.

    Step4 object 69 Show Intention Actions    

      Show Intention Actions Opt + Enter Kotlin
  48. 71.

    71 Step1   Step2-4     Page

     (  ) Step5  return value  PageObject
  49. 72.
  50. 74.

    74 Step1   Step2-4     Page

     (  ) Step5  return value  PageObject
  51. 78.

     :   p MyGardenPage.assertPlanted() ( '!' # 

    &   p "%$: droidkaigi/extra 78 Kotlin
  52. 79.

       p Espresso Test Recorder  PageObject 

     p Android Studio   ( ) p Kotlin Move  79 Kotlin
  53. 80.

    % * p #'&+  p Espresso  p "!

    : Android Sunflower p Espresso Test Recorder) p PageObject"" (, p AAC-$ (" p 80 Kotlin AndroidX AAC Kotlin AndroidX
  54. 81.

    % 5'#UI13  * p View.9 p ;)"/(ID )+8,$ 

    p  2 p 4!(-&7:<60    81 AAC AAC 
  55. 82.

    AAC  ! p Room:  p LiveData RxJava !

    p Pager:   p LivePagedListBuilderRxPagedListBuilder p WorkManager:  82 ArchTaskExecutor Executors. newFixedThreadPool() AAC
  56. 83.

    AAC  ! p Room:  p LiveData RxJava !

    p Pager:   p LivePagedListBuilderRxPagedListBuilder p WorkManager:  83 ArchTaskExecutor Executors. newFixedThreadPool() AAC
  57. 85.

    ArchTaskExecutor:    85 AAC @get:Rule val countingRule =

    CountingTaskExecutorRule() @Test fun myTest() { onView(...).perform(...) // AAC   countingRule..drainTasks(1, TimeUnit.MINUTES) onView(...).perform(...) ... }   
  58. 86.

    ArchTaskExecutor: G S 86 p TaskExecutorWithIdlingResourceRule  p B /

    . / AAC @get:Rule val executorRule = TaskExecutorWithIdlingResourceRule() Rule L: OK
  59. 87.

    AAC  ! p Room:  p LiveData RxJava !

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

    ArchTaskExecutor :    88 ThreadPoolExecutor  p WorkManager

    import androidx.work.Configuration ... val executor = ... val configuration = Configuration.Builder() .setExecutor(executor) .build() WorkManager.initialize(context, configuration) AAC
  61. 89.

    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 ) 
  62. 90.

    ArchTaskExecutor:  "  90   (: CoroutineWorker) asCoroutineDispatcher()

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

       p AAC(!%     

       '" p ArchTaskExecutor&   p $#Executor&   p Kotlin &   91
  64. 92.

    % * p #'&+  p Espresso  p "!

    : Android Sunflower p Espresso Test Recorder) p PageObject"" (, p AAC-$ (" p 92 Kotlin AndroidX AAC Kotlin AndroidX
  65. 93.

    $#  93 p EspressoAndroidXKotlin )"*!  p AndroidX) Recorder

    OK p ,+ 'deprecated -&  (AndroidJUnit4ActivityScenarioRule) p PageObject  Kotlin  (%
  66. 94.

    !   94 p AAC Espresso%   *"(

     ) p      ' $&#
  67. 95.

    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
  68. 96.

    "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