Save 37% off PRO during our Black Friday Sale! »

The Importance of Being Tested

The Importance of Being Tested

Slides of the talk I gave at Droidcon Berlin 2021

6923bdeb363961b064d2cdb6329982d6?s=128

Roberto Orgiu

October 21, 2021
Tweet

Transcript

  1. Roberto Orgiu | Senior Android Engineer @ NYTimes | @_tiwiz

    The importance of being tested
  2. What is testing about?

  3. Correctness Functioning

  4. Is everything testable?

  5. class Repository { private val dep = Dependency( ) fun

    fetch() = dep.getData( ) }
  6. class Repository ( private val dep: Dependenc y ) {

    fun fetch() = dep.getData( ) }
  7. What should I test?

  8. Test the logic, not the code. Fabio Collini (probably?)

  9. fun testCode() { repository.fetch( ) verify(mockDependency).getData( ) }

  10. fun testLogic() { val actualResult = repository.fetch( ) verify(actualResult )

    .isEqualTo(expectedResult ) }
  11. Was that unit testing?

  12. Was that unit testing? Is unit testing enough?

  13. cwti.link/twitch

  14. What about integration testing?

  15. What about integration testing? integration tests validate the collaboration and

    interaction of a group of units.
  16. My take on integration testing

  17. My take on integration testing •No Android deps •Test fl

    ow from start to end •Use Robolectric
  18. class RootFragment : Fragment() { lateinit var repository: Repositor y

    lateinit var view: Vie w fun onResume() { val response = repository.fetchThings( ) view.bindResults(response ) } }
  19. class IntegrationTest { private val mock = TestDouble(Service() ) private

    val testFragment = RootFragment( ) fun integrationTest() { run(testFragment).verify( ) } } androidTest
  20. What about Network?

  21. What about network? Network is unreliable

  22. What about network? • Retro fi t + OkHttp +

    MockWebServer • Ktor + MockEngine
  23. val retrofit = Retrofit.Builder( ) .baseUrl("https://api.github.com/" ) .build( ) This

    should come from the outside!
  24. val retrofit = Retrofit.Builder( ) .baseUrl(url ) .build( )

  25. val server = MockWebServer( ) server.enqueue ( MockResponse().setBody("hello, world!" )

    ) server.start( ) val url = server.url( )
  26. HttpClient(Android) { install(Logging) { … } install(JsonFeature) { … }

    } This should come from the outside!
  27. val mockEngine = MockEngine { request - > respond (

    content = ByteReadChannel(content) , status = HttpStatusCode.OK , headers = headersOf(ContentType, type ) ) }
  28. What about UI testing?

  29. What about UI testing?

  30. @get:Rule var activityScenarioRule = activityScenarioRule<MyActivity>( ) @Tes t fun changeText()

    { onView(withId(startViewId) ) .perform ( typeText(MESSAGE) , closeSoftKeyboard( ) ) onView(withId(buttonViewId) ) .perform(click() ) onView(withId(targetView) ) .check(matches(withText(MESSAGE)) ) }
  31. None
  32. None
  33. @Composabl e fun SimpleUI() { var clicks by remember {

    mutableStateOf(0) } Column { Button ( onClick = { clicks++ } ) { Text(text = "Click me" ) } if (clicks > 0) { Text(text = "$clicks" ) } } }
  34. @get:Rul e val composeTestRule = createComposeRule( ) @Tes t fun

    verify_initial_case() { composeTestRule.setContent { SimpleUI( ) } composeTestRule.onNodeWithTag("clicks" ) .assertDoesNotExist( ) }
  35. @get:Rul e val composeTestRule = createComposeRule( ) @Tes t fun

    verify_last_case() { composeTestRule.setContent { SimpleUI( ) } composeTestRule.onNodeWithText("Click me" ) .performClick( ) with(composeTestRule.onNodeWithTag("clicks")) { assertIsDisplayed( ) assertTextEquals("1" ) } }
  36. How can I start testing?

  37. Roberto Orgiu | Senior Android Engineer @ NYTimes | @_tiwiz

    Thanks for listening. Q&A Time