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

Have you met Test?

Have you met Test?

Talk from GDG DevFest Yangon 2018

0991ca4bc363163337f7b02b98af538a?s=128

Aung Kyaw Paing

October 29, 2018
Tweet

More Decks by Aung Kyaw Paing

Other Decks in Programming

Transcript

  1. Have you met Test? nexlabs

  2. What’s Testing? /

  3. What’s Testing? / take measures to check the quality, performance,

    or reliability of (something), especially before putting it into widespread use or practice.
  4. What’s Testing? Making sure something works as intended /

  5. / GDG Yangon DevFest GDG,Yangon,DevFest

  6. / import org.junit.Test class StringUtilsConversionTest { @Test fun testConversion() {

    } }
  7. / import org.junit.Test class StringUtilsConversionTest { @Test fun testConversion() {

    //Declare necessary inputs val stringList = listOf("GDG", "Yangon", "DevFest") } }
  8. / import org.junit.Test class StringUtilsConversionTest { @Test fun testConversion() {

    //Declare necessary inputs val stringList = listOf("GDG", "Yangon", "DevFest") //Declare expected value val expected = "GDG,Yangon,DevFest" } }
  9. / @Test fun testConversion() { //Declare necessary inputs val stringList

    = listOf("GDG", "Yangon", "DevFest") //Declare expected value val expected = "GDG,Yangon,DevFest" //Declare actual val actual = StringUtils.convertStringListToString(stringList) }
  10. / object StringUtils { fun convertStringListToString(stringList: List<String>): String { TODO("not

    implemented") } }
  11. / @Test fun testConversion() { //Declare necessary inputs val stringList

    = listOf //Check if two values are equal("GDG", "Yangon", "DevFest") //Declare expected value val expected = "GDG,Yangon,DevFest" //Declare actual val actual = StringUtils.convertStringListToString(stringList) //Check if two values are equal org.junit.Assert.assertEquals(expected, actual) }
  12. /

  13. / fun convertStringListToString(stringList: List<String>): String { TODO("not implemented") }

  14. / fun convertStringListToString(stringList: List<String>): String { return "GDG,Yangon,DevFest" }

  15. /

  16. / @Test fun testWithFourStrings() { //Declare necessary inputs val stringList

    = listOf("GDG", "Yangon", "DevFest", "Android") //Declare expected value val expected = "GDG,Yangon,DevFest,Android" //Declare actual val actual = StringUtils.convertStringListToString(stringList) //Check if two values are equal org.junit.Assert.assertEquals(expected, actual) }
  17. /

  18. / fun convertStringListToString(stringList: List<String>): String { if (stringList.size == 4)

    { return "GDG,Yangon,DevFest,Android" } return "GDG,Yangon,DevFest" }
  19. /

  20. / @Test fun testWithThreeStringCaseTwo() { //Declare necessary inputs val stringList

    = listOf("GDG", "Yangon", "Best") //Declare expected value val expected = "GDG,Yangon,Best" //Declare actual val actual = StringUtils.convertStringListToString(stringList) //Check if two values are equal org.junit.Assert.assertEquals(expected, actual) }
  21. /

  22. / fun convertStringListToString(stringList: List<String>): String { val stringBuilder = StringBuilder()

    stringList.forEachIndexed { index, string -> stringBuilder.append(string) //If Index is last, we don't append delimiter if (index != stringList.lastIndex) { stringBuilder.append(",") } } return stringBuilder.toString() }
  23. /

  24. Strategies to green-light • Fake It till you make it

    • Use Obvious Implementation /
  25. Strategies to green-light • Fake It till you make it

    • “Return a constant and gradually replace constants with variables until you have the real code” • Use Obvious Implementation /
  26. / fun convertStringListToString(stringList: List<String>): String { return "GDG,Yangon,DevFest" }

  27. / fun convertStringListToString(stringList: List<String>): String { if (stringList.size == 4)

    { return "GDG,Yangon,DevFest,Android" } return "GDG,Yangon,DevFest" }
  28. / fun convertStringListToString(stringList: List<String>): String { val stringBuilder = StringBuilder()

    stringList.forEachIndexed { index, string -> stringBuilder.append(string) //If Index is last, we don't append delimiter if (index != stringList.lastIndex) { stringBuilder.append(",") } } return stringBuilder.toString() }
  29. Strategies to green-light • Fake It till you make it

    • “Return a constant and gradually replace constants with variables until you have the real code” • Use Obvious Implementation • “Type in the real implementation.” /
  30. / GDG Yangon DevFest GDG|Yangon|DevFest

  31. / @Test fun testWithDifferentDelimiter() { //Declare necessary inputs val stringList

    = listOf("GDG", "Yangon", "Best") //Declare expected value val expected = "GDG|Yangon|Best" //Declare actual val actual = StringUtils.convertStringListToString(stringList) //Check if two values are equal org.junit.Assert.assertEquals(expected, actual) }
  32. / fun convertStringListToString(stringList: List<String>): String { val stringBuilder = StringBuilder()

    stringList.forEachIndexed { index, string -> stringBuilder.append(string) //If Index is last, we don't append delimiter if (index != stringList.lastIndex) { stringBuilder.append(",") } } return stringBuilder.toString() }
  33. / fun convertStringListToString( stringList: List<String>, delimiter: String ): String {

    val stringBuilder = StringBuilder() stringList.forEachIndexed { index, string -> stringBuilder.append(string) //If Index is last, we don't append delimiter if (index != stringList.lastIndex) { stringBuilder.append(delimiter) } } return stringBuilder.toString() }
  34. / fun convertStringListToString( stringList: List<String>, delimiter: String ): String {

    val stringBuilder = StringBuilder() stringList.forEachIndexed { index, string -> stringBuilder.append(string) //If Index is last, we don't append delimiter if (index != stringList.lastIndex) { stringBuilder.append(delimiter) } } return stringBuilder.toString() }
  35. / val actual = StringUtils.convertStringListToString(stringList, ",")

  36. / val actual = StringUtils.convertStringListToString(stringList, “|")

  37. /

  38. / val stringBuilder = StringBuilder() stringList.forEachIndexed { index, string ->

    stringBuilder.append(string) //If Index is last, we don't append delimiter if (index != stringList.lastIndex) { stringBuilder.append(delimiter) } } return stringBuilder.toString()
  39. As test get more specific, real code get more generic

    /
  40. As test get more specific, real code get more generic

    / Triangulation Method
  41. Testing in Android /

  42. Testing in Android / 70%

  43. Testing in Android / 70% 20%

  44. Testing in Android / 70% 20% 10%

  45. Mocking /

  46. / 3 True False 32 3 x 2

  47. / interface DataSource { fun getValue(): Int fun isSomething(): Boolean

    }
  48. / class RealDataSource : DataSource { override fun getValue(): Int

    { //Do Network call TODO() } override fun isSomething(): Boolean { //Do Network call TODO() } }
  49. / class GetCalculatedValue { fun execute(): Int { TODO() }

    }
  50. / class GetCalculatedValueTest { @Test fun testTrueCase() { TODO("not implemented")

    } @Test fun testFalseCase() { TODO("not implemented") } }
  51. / fun testTrueCase() { val fakeDataSource = object : DataSource

    { override fun getValue(): Int { return 3 } override fun isSomething(): Boolean { return true } } val expected = 9 val getCalculatedValue = GetCalculatedValue() val actual = getCalculatedValue.execute() assertEquals(expected, actual) }
  52. / fun testTrueCase() { val fakeDataSource = object : DataSource

    { override fun getValue(): Int { return 3 } override fun isSomething(): Boolean { return true } } val expected = 9 val getCalculatedValue = GetCalculatedValue() val actual = getCalculatedValue.execute(fakeDataSource) assertEquals(expected, actual) }
  53. / class GetCalculatedValue { fun execute(): Int { TODO() }

    }
  54. / class GetCalculatedValue { fun execute(dataSource: DataSource): Int { TODO()

    } }
  55. / class GetCalculatedValue { fun execute(dataSource: DataSource): Int { return

    dataSource.getValue() * dataSource.getValue() } }
  56. / fun testFalseCase() { val fakeDataSource = object : DataSource

    { override fun getValue(): Int { return 3 } override fun isSomething(): Boolean { return false } } val expected = 6 val getCalculatedValue = GetCalculatedValue() val actual = getCalculatedValue.execute(fakeDataSource) assertEquals(expected, actual) }
  57. / val getCalculatedValue = GetCalculatedValue() val actual = getCalculatedValue.execute(fakeDataSource)

  58. / val getCalculatedValue = GetCalculatedValue(fakeDataSource) val actual = getCalculatedValue.execute() class

    GetCalculatedValue constructor(val dataSource: DataSource) { }
  59. / fun execute(): Int { return if (dataSource.isSomething()) { dataSource.getValue()

    * dataSource.getValue() } else { dataSource.getValue() * 2 } }
  60. Mockito /

  61. Mockito / org.mockito:mockito-core org.mockito:mockito-inline com.nhaarman:mockito-kotlin

  62. / val fakeDataSource = object : DataSource { override fun

    getValue(): Int { return 3 } override fun isSomething(): Boolean { return true } } val getCalculatedValue = GetCalculatedValue(fakeDataSource) val actual = getCalculatedValue.execute()
  63. / class GetCalculatedValueTest { @Mock lateinit var fakeDataSource: DataSource lateinit

    var getCalculatedValue: GetCalculatedValue }
  64. / @Before fun setUp() { }

  65. / @Before fun setUp() { } @After fun tearDown() {

    }
  66. / @Mock lateinit var fakeDataSource: DataSource lateinit var getCalculatedValue: GetCalculatedValue

    @Before fun setUp() { MockitoAnnotations.initMocks(this) getCalculatedValue = GetCalculatedValue(fakeDataSource) }
  67. / @Test fun testTrueCase() { whenever(fakeDataSource.isSomething()).thenReturn(true) whenever(fakeDataSource.getValue()).thenReturn(3) val expected =

    9 val actual = getCalculatedValue.execute() assertEquals(expected, actual) }
  68. / @Test fun testTrueCase() { whenever(fakeDataSource.isSomething()).thenReturn(true) whenever(fakeDataSource.getValue()).thenReturn(3) val expected =

    9 val actual = getCalculatedValue.execute() assertEquals(expected, actual) }
  69. / .thenThrow(//Throwable) .thenAnswer { //Do Stuffs } .thenReturn(//Return value)

  70. / fun testTrueCase() { whenever(fakeDataSource.isSomething()).thenReturn(true) whenever(fakeDataSource.getValue()).thenReturn(3) val expected = 9

    val actual = getCalculatedValue.execute() verify(fakeDataSource).isSomething() verify(fakeDataSource).getValue() assertEquals(expected, actual) }
  71. / fun testTrueCase() { whenever(fakeDataSource.isSomething()).thenReturn(true) whenever(fakeDataSource.getValue()).thenReturn(3) val expected = 9

    val actual = getCalculatedValue.execute() verify(fakeDataSource).isSomething() verify(fakeDataSource).getValue() assertEquals(expected, actual) }
  72. / fun testTrueCase() { whenever(fakeDataSource.isSomething()).thenReturn(true) whenever(fakeDataSource.getValue()).thenReturn(3) val expected = 9

    val actual = getCalculatedValue.execute() verify(fakeDataSource, times(1)).isSomething() verify(fakeDataSource, times(1)).getValue() assertEquals(expected, actual) }
  73. / fun execute(): Int { return if (dataSource.isSomething()) { dataSource.getValue()

    * dataSource.getValue() } else { dataSource.getValue() * 2 } }
  74. / fun execute(): Int { val value = dataSource.getValue() return

    if (dataSource.isSomething()) { value * value } else { value * 2 } }
  75. / fun testTrueCase() { whenever(fakeDataSource.isSomething()).thenReturn(true) whenever(fakeDataSource.getValue()).thenReturn(3) val expected = 9

    val getCalculatedValue = GetCalculatedValue(fakeDataSource) val actual = getCalculatedValue.execute() verify(fakeDataSource, times(1)).isSomething() verify(fakeDataSource, times(1)).getValue() assertEquals(expected, actual) }
  76. Robolectric /

  77. / - Run instrumentation test on JVM - Allow running

    integration tests without android device Robolectric
  78. Espresso (UI Testing) /

  79. / Espresso (UI Testing) - Not recommend to run on

    physical device
  80. / @RunWith(AndroidJUnit4::class) @LargeTest class MainActivityTest { }

  81. / @Rule @JvmField val activityTestRule = ActivityTestRule<MainActivity>( MainActivity::class.java, false, false

    )
  82. / Espresso Idling Resource

  83. / public String getName();

  84. / public boolean isIdleNow();

  85. / public void registerIdleTransitionCallback(ResourceCallback callback); public interface ResourceCallback { public

    void onTransitionToIdle(); }
  86. / @Override public String getName() { return "ViewPagerIdlingResource"; } @Override

    public boolean isIdleNow() { return viewPager == null || isIdle; } @Override public void onPageScrollStateChanged(int state) { this.isIdle = state != ViewPager.SCROLL_STATE_SETTLING; if (this.isIdle) { this.resourceCallback.onTransitionToIdle(); } }
  87. / Espresso + Dagger

  88. / Espresso + Dagger @Module class TestApplicationModule @Component(modules = [TestApplicationModule:class]

    interface TestApplicationComponent class TestApplication : Application
  89. / Espresso + Dagger @Provides fun sharedPref(context: Context): SharedPreferences {

    val pref = PreferenceManager.getDefaultSharedPreferences(context); pref.edit { clear() } return pref }
  90. / Espresso + Dagger @Provides @Singleton fun userRepository(): UserRepository {

    return mock() }
  91. / Espresso + Dagger interface TestAppComponent { //... fun userRepository():

    UserRepository //... }
  92. / Espresso + Dagger class TestApplication { companion object {

    lateinit var appComponent: TestAppComponent } override fun onCreate() { super.onCreate() appComponent = //... } }
  93. / Espresso + Dagger val appComponent = TestApplication.appComponent whenever(appComponent.userRepository().login()).thenReturn(true)

  94. / Espresso + Dagger @Rule @JvmField val activityTestRule = ActivityTestRule<MainActivity>(

    MainActivity::class.java, false, false )
  95. / Espresso + Dagger @Rule @JvmField val activityTestRule = ActivityTestRule<MainActivity>(

    MainActivity::class.java, false, false ) val activity = activityTestRule.launchActivity(null)
  96. Static Analysis / • Lint • PMD • Findbugs •

    Checkstyle
  97. Where do I start? /

  98. / • Write a test whenever app crash Where do

    I start?
  99. / • Write a test whenever app crash • Start

    writing in complex parts Where do I start?
  100. / • Write a test whenever app crash • Start

    writing in complex parts • Learn tools in free time Where do I start?
  101. Continuous Integration/Deployment /

  102. Recap /

  103. Have you met Test? nexlabs