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

Espressing yourself

Espressing yourself

Some hints on how to use dagger and mockito to easily build espresso tests.

Rui Gonçalo

May 30, 2017

Transcript

36 slides
  1. class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } } MainActivity.kt
  2. class MainActivity : AppCompatActivity() { @Inject lateinit var presenter: MainPresenter

    override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } } MainActivity.kt Dagger
  3. MainPresenter.kt class MainPresenter @Inject constructor( private val servicesManager: ServicesManager, private

    val getDataUseCase: GetDataUseCase) { private lateinit var view: MainPresenter.View fun attachView(view: MainPresenter.View) { this.view = view } ... interface View { ... } } Dagger
  4. AppComponent.kt @Singleton @Component(modules = arrayOf(AppModule::class)) interface AppComponent { fun plus(module:

    ActivityModule): ActivityComponent fun servicesManager(): ServicesManager } Dagger
  5. AppComponent.kt @Singleton @Component(modules = arrayOf(AppModule::class)) interface AppComponent { fun plus(module:

    ActivityModule): ActivityComponent fun servicesManager(): ServicesManager } Dagger AppComp AppModule
  6. MainModule.kt @Module open class MainModule { open fun provideGetDataUseCase() :

    GetDataUseCase { return GetDataUseCase } Dagger AppComp AppModule ActivityComp ActivityModule MainComp MainModule
  7. Dagger AppComp AppModule ActivityComp ActivityModule MainComp MainModule class MainActivity :

    AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) (application as App) .appComponent .plus(ActivityModule(this)) .plus(MainModule()) .inject(this) } } MainActivity.kt
  8. MainPresenter.kt class MainPresenter @Inject constructor( private val servicesManager: ServicesManager, private

    val getDataUseCase: GetDataUseCase) { fun attachView(view: MainPresenter.View) { this.view = view } fun start() { } fun stop() { } }
  9. MainPresenter.kt class MainPresenter (getDataUseCase) { private val subscriptions by lazy

    { CompositeSubscription() } fun start() { subscriptions.add( getDataUseCase.build() .subscribeOn(...) .observeOn(AndroidSchedulers.mainThread()) .subscribe( {result -> view.showResult(result)} , {error -> view.showError(error)}) ) } fun stop() { subscriptions.clear() } }
  10. MainActivity.kt class MainActivity : AppCompatActivity(), MainPresenter.View { @Inject lateinit var

    presenter: MainPresenter override fun onStart(){ super.onStart() presenter.start() } override fun onStop(){ super.onStop() presenter.stop() } override fun showResult(result) override fun showError(error) }
  11. MainActivityTest.kt @RunWith(AndroidJUnit4::class) @LargeTest class MainActivityTest { @Rule @JvmField val mainActivityTestRule

    = ActivityTestRule<MainActivity>(MainActivity::class.java) @Test fun something() { // test } }
  12. MainActivityTest.kt @RunWith(AndroidJUnit4::class) @LargeTest class MainActivityTest { @Rule @JvmField val mainActivityTestRule

    = ActivityTestRule<MainActivity>(MainActivity::class.java) @Test fun something() { // test } } https://github.com/fabioCollini/DaggerMock
  13. MainActivityTest.kt @RunWith(AndroidJUnit4::class) @LargeTest class MainActivityTest { val app = InstrumentationRegistry.getInstrumentation()

    .targetContext .applicationContext as App @Rule @JvmField val appComponentRule = DaggerMockRule(AppComponent::class.java, AppModule(app)). set { component -> app.appComponent = component } @Mock lateinit var getDataUseCase: GetDataUseCase @Mock lateinit var servicesManager: ServicesManager } https://github.com/fabioCollini/DaggerMock
  14. MainActivityTest.kt @RunWith(AndroidJUnit4::class) @LargeTest class MainActivityTest { @Mock lateinit var getDataUseCase:

    GetDataUseCase @Test fun something() { `when`(getDataUseCase.build()).thenReturn(Observable.just(result)) // test } } https://github.com/fabioCollini/DaggerMock
  15. MainActivityTest.kt @RunWith(AndroidJUnit4::class) @LargeTest class MainActivityTest { @Rule @JvmField val mainActivityTestRule

    = ActivityTestRule<MainActivity>(MainActivity::class.java, false, false) @Test fun something() { `when`(getDataUseCase.build()).thenReturn(Observable.just(result)) mainActivityTestRule.launchActivity() // test } } launchActivity
  16. MainActivityTest.kt @RunWith(AndroidJUnit4::class) @LargeTest class MainActivityTest { @Test fun something() {

    `when`(getDataUseCase.build()).thenReturn(Observable.just(result)) mainActivityTestRule.launchActivity() onView(withId(R.id.text)).check(matches(withText("result"))) } }
  17. MainActivityTest.kt @RunWith(AndroidJUnit4::class) @LargeTest class MainActivityTest { @Test fun something() {

    `when`(getDataUseCase.build()).thenReturn(Observable.just(result)) mainActivityTestRule.launchActivity() onView(withId(R.id.text)).check(matches(withText("result"))) } } http://jakewharton.com/testing-robots
  18. MainActivityTest.kt @RunWith(AndroidJUnit4::class) @LargeTest class MainActivityTest { val mainActions = MainActivityActions()

    val mainAssertions = MainActivityAssertions() @Test fun something() { `when`(getDataUseCase.build()).thenReturn(Observable.just(result)) mainActivityTestRule.launchActivity() mainAssertions.isDisplayingResult() } } http://jakewharton.com/testing-robots
  19. RoundActions.kt class RoundActions { fun onRound(func: RoundActions.() -> Unit) =

    RoundActions().apply { func() } fun openDrawer() { onView(withId(R.id.peekView)).perform(click()) } fun selectDistanceUnit(unit: DistanceUnit) { if (unit == DistanceUnit.METRIC) { onView(withId(R.id.metric)).perform(click()) } else { onView(withId(R.id.imperial)).perform(click()) } }
  20. RoundAssertions.kt class RoundAssertions { fun isDrawerOpen() { onView(withId(R.id.drawerContent)).check(matches(isCompletelyDisplayed())) } fun

    isDisplayingMetricLabel() { onView(allOf(withId(R.id.distanceUnitLabel), isCompletelyDisplayed())) .check(matches(withText("m"))) } }
  21. RoundActivityTest.kt class RoundActivityTest { @Test fun changeDistanceUnitsToMetric() { `when`(getDistanceUnitsUseCase.build()) .thenReturn(Observable.just(DistanceUnit.IMPERIAL))

    roundActivityTestRule.launchActivity() roundActions.onRound { openDrawer() openDistanceUnits() selectDistanceUnit(DistanceUnit.METRIC) } roundAssertions.isDisplayingMetricLabel() }
  22. Automatic UI testing spares manual QA tasks Make sure *nothing*

    breaks on refactoring Test on a set of emulators/real devices Test on different locales

More Decks by Rui Gonçalo

Other Decks in Programming