Danny Preussler (Viacom), Mobile Kotlin all your tests, CodeFest 2017

16b6c87229eaf58768d25ed7b2bbbf52?s=47 CodeFest
January 31, 2018

Danny Preussler (Viacom), Mobile Kotlin all your tests, CodeFest 2017

https://2017.codefest.ru/lecture/1155

Kotlin was the rising star of programming languages in 2016. It not only became final with version 1.0 but also got rapidly adopted in the android community. But many companies are struggling to add Kotlin to an existing Java project. It's not easy to add a new language to an existing team. But it's much easier to introduce Kotlin to your project using the backdoor: your unit tests. So let's look at Kotlin more from a testing perspective. How does it look like to write tests in Kotlin, what possibilities of the language will help us?

16b6c87229eaf58768d25ed7b2bbbf52?s=128

CodeFest

January 31, 2018
Tweet

Transcript

  1. Kotlin all your tests Danny Preussler Android Lead, (Google Developer

    Expert)
  2. Kotlin all your tests Danny Preussler Android Lead, (Google Developer

    Expert)
  3. fun test() Kotlin all your tests Danny Preussler Android Lead,

    (Google Developer Expert)
  4. @PreusslerBerlin Our world so far …

  5. @PreusslerBerlin

  6. @PreusslerBerlin Watch the cool kids…

  7. @PreusslerBerlin But then …

  8. @PreusslerBerlin

  9. @PreusslerBerlin

  10. @PreusslerBerlin Kotlin stole the best from the best

  11. @PreusslerBerlin Kotlin stole got inspired by the best from of

    the best
  12. @PreusslerBerlin JVM based

  13. @PreusslerBerlin Functional inspired

  14. @PreusslerBerlin Statically typed

  15. @PreusslerBerlin Statically typed val number = 5

  16. @PreusslerBerlin Designed with Android in mind

  17. @PreusslerBerlin Null safe

  18. @PreusslerBerlin Null safe

  19. @PreusslerBerlin Reduce boilerplate

  20. @PreusslerBerlin No need for Java8

  21. @PreusslerBerlin Awesome tooling support

  22. @PreusslerBerlin Awesome tooling support

  23. @PreusslerBerlin

  24. @PreusslerBerlin BUT

  25. @PreusslerBerlin

  26. @PreusslerBerlin “No Kotlin in production”

  27. @PreusslerBerlin

  28. @PreusslerBerlin But wait …

  29. @PreusslerBerlin But wait … A backdoor

  30. @PreusslerBerlin No one cares about your tests anyway right?

  31. @PreusslerBerlin Tests are a safe place for experiments

  32. @PreusslerBerlin Let’s test in Kotlin

  33. @PreusslerBerlin Kotlin is expressive

  34. @PreusslerBerlin @Test void testHandlesNullArguments()

  35. @PreusslerBerlin @Test fun testHandlesNullArguments()

  36. @PreusslerBerlin @Test fun testHandlesNullArguments()

  37. @PreusslerBerlin @Test fun handlesNullArguments()

  38. @PreusslerBerlin @Test fun handles_null_arguments()

  39. @PreusslerBerlin @Test fun ‘handles null arguments’()

  40. @PreusslerBerlin Readability first

  41. @PreusslerBerlin String jsonText = "{\r\n \"deal\" : {\r\n \"isTipped\" :

    true,\r\n \"id\" : \"D-Company-241907\",\r\n \"areas\" : [],\r\n \"smallImageUrl\" : \"http://uat-static.groupon.de/00/00/small0000.jpg\",\r\n \"finePrint\" : \"MULTI DEAL ext Codes\",\r\n \"says\" : {\r\n \"emailContent\" : \"\",\r\n \"id\" : \"\",\r\n \"websiteContent\" : \"\",\r\n \"title\" : \"\",\r\n \"websiteContentHtml\" : \"\",\r\n \"emailContentHtml\" : \"\"\r\n },\r\n \"endAt\" : \"2014-03-31T22:59:00Z\",\r\n \"shortAnnouncementTitle\" : \"D-Company: 50% sparen in QA_AutoTestCity2\",\r\n \"placeholderUrl\" : \"http://assets2.grouponcdn.com/images/groupon/grayPlaceholder.png\",\r\n \"shippingAddressRequired\" : false,\r\n \"type\" : \"groupon\",\r\n \"isSoldOut\" : false,\r\n \"priority\" : 0,\r\n \"options\" : [\r\n {\r\n \"status\" : \"open\",\r\n \"title\" : \"MULTI DEAL ext Codes Option1\",\r\n \"isLimitedQuantity\" : false,\r\n \"tax\" : {\r\n \"amount\" : 16,\r\n \"currencyCode\" : \"EUR\",\r\n \"formattedAmount\" : \"0,16 \u20AC\"\r\n },\r\n \"minimumPurchaseQuantity\" : 1,\r\n \"expiresInDays\" : 62,\r\n \"discount\" : {\r\n \"amount\" : 100,\r\n \"currencyCode\" : \"EUR\",\r\n
  42. @PreusslerBerlin val jsonText = """ { "channels":{ "BOOKING":1443439538, "GTG":1443439537, }

    } """
  43. @PreusslerBerlin ... tested.updateNetworkStatus(networkInfo) assertFalse(tested.isCellularConnected()) assertFalse(tested.isWifiConnected()) ...

  44. @PreusslerBerlin ... tested.updateNetworkStatus(networkInfo) assertFalse(tested.isNotOnAnyNetwork()) ...

  45. @PreusslerBerlin fun ConnectivityReceive.isNotOnAnyNetwork(): Boolean{ return !isCellularConnecrted() && !isWifiConnected()) }

  46. @PreusslerBerlin fun ConnectivityReceiver.isNotOnAnyNetwork() = { !isCellularConnecrted() && !isWifiConnected()) }

  47. @PreusslerBerlin ... tested.updateNetworkStatus(networkInfo) tested.assertNotOnAnyNetwork() ...

  48. @PreusslerBerlin fun ConnectivityReceiver.assertNotOnAnyNetwork(){ assertFalse(isConnected()) assertFalse(isWifiConnected()) }

  49. @PreusslerBerlin Keep it short

  50. @PreusslerBerlin ... Map<TYPE, Integer> signalStrength = new HashMap<>(); signalStrength.put(EDGE, 80);

    signalStrength.put(WIFI to 90); ...
  51. @PreusslerBerlin ... val signalStrength = hashMapOf(EDGE to 80, WIFI to

    90) ...
  52. @PreusslerBerlin Make it consistent

  53. @PreusslerBerlin assertFailsWith<NoSuchElementException>( none.get() )

  54. @PreusslerBerlin What about mocks?

  55. @PreusslerBerlin Kotlin Mockito github.com/nhaarman/mockito-kotlin

  56. @PreusslerBerlin Syntactical Sugar around Mockito

  57. @PreusslerBerlin var resources = mock<Resources>()

  58. @PreusslerBerlin var resources : Resources = mock()

  59. @PreusslerBerlin whenever(resources.getString(R.string.title) .thenReturn(”Title")

  60. @PreusslerBerlin var resources = mock<Resources> { on { getString(R.string.title) }

    doReturn ”Title” }
  61. @PreusslerBerlin any() * without Java8

  62. @PreusslerBerlin verify(tracker).report(any()) * without Java8

  63. @PreusslerBerlin tracker.report(mock()) * without Java8

  64. @PreusslerBerlin verify(fragment).setArguments(bundle)

  65. @PreusslerBerlin verify(fragment).setArguments(bundle)

  66. @PreusslerBerlin verify(fragment).arguments = bundle

  67. @PreusslerBerlin inOrder(parcel).apply { verify(parcel).writeByte(0) verify(parcel).writeString("path") }

  68. @PreusslerBerlin argumentCaptor<VideoStartedReport>().apply { verify(tracker).report(capture()) assertEquals(value.id, TEST_ID) assertEquals(value.duration, TEST_DURATION) }

  69. @PreusslerBerlin Kluent github.com/MarkusAmshove/Kluent

  70. @PreusslerBerlin Readability first

  71. @PreusslerBerlin assertEquals("hello", greeting);

  72. @PreusslerBerlin greeting shouldEqual "hello"

  73. @PreusslerBerlin list shouldContain “jon”

  74. @PreusslerBerlin No magic here

  75. @PreusslerBerlin list.shouldContain(“jon”)

  76. @PreusslerBerlin infix fun <T> Array<T>.shouldContain(theThing: T)

  77. @PreusslerBerlin Spek github.com/JetBrains/spek

  78. @PreusslerBerlin SimpleSpec: Spek({ describe("a calculator") { val calculator = SampleCalculator()

    on("addition") { val sum = calculator.sum(2, 4) it("should return the sum") { assertEquals(6, sum) } } } }
  79. @PreusslerBerlin Tests are a great way to learn Kotlin

  80. @PreusslerBerlin Make a plan how to continue

  81. @PreusslerBerlin Make a plan how to continue •tutorials

  82. @PreusslerBerlin Make a plan how to continue •tutorials •hackathons

  83. @PreusslerBerlin Make a plan how to continue •tutorials •hackathons •coding

    Kata
  84. @PreusslerBerlin Build an experiment, learn from it, see prove it’s

    working
  85. @PreusslerBerlin

  86. fun test() Kotlin all your tests Danny Preussler @PreusslerBerlin