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

TDD on Android (MobOS 2018)

TDD on Android (MobOS 2018)

Slides for my workshop giving in Cluj
Source: https://github.com/sporttotal-tv/android-tdd-workshop

Danny Preussler

February 16, 2018
Tweet

More Decks by Danny Preussler

Other Decks in Technology

Transcript

  1. @PreusslerBerlin History • Started with test first from XP in

    1999 by Kent Beck • Famous as TDD since Kent Becks book in 2003 • Just a rediscovery: test first was normal in early days of programming
  2. @PreusslerBerlin History • Started with test first from XP in

    1999 by Kent Beck • Famous as TDD since Kent Becks book in 2003 • Just a rediscovery: test first was normal in early days of programming
  3. @PreusslerBerlin History • Started with test first from XP in

    1999 by Kent Beck • Famous as TDD since Kent Becks book in 2003 • Just a rediscovery: test first was normal in early days of programming
  4. @PreusslerBerlin “Code without tests is bad code.” “any code without

    test is a legacy code.” (Michael C. Feathers)
  5. @PreusslerBerlin Tests give confidence “how do you know something work

    when you don’t have test for it?” (Robert ‘Uncle Bob’ Martin)
  6. @PreusslerBerlin Tests are documentation • The only doc that lives

    (with your code) • Test code will become more important than your production code
  7. @PreusslerBerlin About me • Talking about testing for 10y now

    • Its all about discipline • I am a learner like you • Let’s dive in together
  8. @PreusslerBerlin What I learned • ”test after” does not work

    (enough) Test1 Test2 Class1 Class2 Class3 Test3
  9. @PreusslerBerlin …there is one other [discipline] that is, and that’s

    Accounting. The right mistake … that one-digit error can crash the company and send the offenders off to jail. How do accountants deal with that sensitivity? Well, they have disciplines.
  10. @PreusslerBerlin …there is one other [discipline] that is, and that’s

    Accounting. The right mistake … that one-digit error can crash the company and send the offenders off to jail. How do accountants deal with that sensitivity? Well, they have disciplines.
  11. @PreusslerBerlin …there is one other [discipline] that is, and that’s

    Accounting. The right mistake … that one-digit error can crash the company and send the offenders off to jail. How do accountants deal with that sensitivity? Well, they have disciplines.
  12. @PreusslerBerlin Dual entry book keeping Everything is said twice. Every

    transaction is entered two times — once on the credit side and once on the debit side. Those two transactions follow separate mathematical pathways until they end up at this wonderful subtraction on the balance sheet that has to yield to zero.
  13. @PreusslerBerlin Dual entry book keeping Everything is said twice. Every

    transaction is entered two times — once on the credit side and once on the debit side. Those two transactions follow separate mathematical pathways until they end up at this wonderful subtraction on the balance sheet that has to yield to zero.
  14. @PreusslerBerlin Dual entry book keeping Everything is said twice. Every

    transaction is entered two times — once on the credit side and once on the debit side. Those two transactions follow separate mathematical pathways until they end up at this wonderful subtraction on the balance sheet that has to yield to zero.
  15. @PreusslerBerlin Dual entry book keeping This is what test-driven development

    is: dual-entry bookkeeping. Everything is said twice — once on the test side and once on the production code side and everything runs in an execution that yields either a green bar or a red bar just like the zero on the balance sheet.
  16. @PreusslerBerlin Dual entry book keeping This is what test-driven development

    is: dual-entry bookkeeping. Everything is said twice — once on the test side and once on the production code side and everything runs in an execution that yields either a green bar or a red bar just like the zero on the balance sheet.
  17. @PreusslerBerlin Dual entry book keeping This is what test-driven development

    is: dual-entry bookkeeping. Everything is said twice — once on the test side and once on the production code side and everything runs in an execution that yields either a green bar or a red bar just like the zero on the balance sheet.
  18. @PreusslerBerlin “If you’re doing test-driven development well, you’ll never write

    comments in your code because your tests are a form of documentation for how your program should work,” (Alex Clark, Codecademy)
  19. @PreusslerBerlin The 3 rules of TDD • You must write

    a failing test before you write any production code. • You must not write more of a test than is sufficient to fail, or fail to compile. • You must not write more production code than is sufficient to make the currently failing test pass. nano-cycle (seconds)
  20. @PreusslerBerlin The 3 rules of TDD • You must write

    a failing test before you write any production code. • You must not write more of a test than is sufficient to fail, or fail to compile. • You must not write more production code than is sufficient to make the currently failing test pass. nano-cycle (seconds)
  21. @PreusslerBerlin The 3 rules of TDD • You must write

    a failing test before you write any production code. • You must not write more of a test than is sufficient to fail, or fail to compile. • You must not write more production code than is sufficient to make the currently failing test pass. nano-cycle (seconds)
  22. @PreusslerBerlin Red Green Refactor • Make it fail • Make

    it work • Make it right micro-cycle (minutes)
  23. @PreusslerBerlin Red Green Refactor • Create a unit tests that

    fails • Write just enough production code to makes that test pass. • Clean up the mess you just made. micro-cycle (minutes)
  24. @PreusslerBerlin Red Green Refactor • Create a unit tests that

    fails • Write just enough production code to makes that test pass. • Clean up the mess you just made. micro-cycle (minutes)
  25. @PreusslerBerlin Red Green Refactor • Create a unit tests that

    fails • Write just enough production code to makes that test pass. • Clean up the mess you just made. micro-cycle (minutes)
  26. @PreusslerBerlin Babysteps The philosophy is based on the idea that

    our limited minds are not capable of pursuing the two simultaneous goals of all software systems: 1. Correct behavior. 2. Correct structure.
  27. @PreusslerBerlin Red Green Refactor • Always be one step away

    from green bar • Think of new test-> write it down • It’s getting ugly? -> write it down
  28. @PreusslerBerlin Why? • Test all business needs • Less coupled

    to implementation • Less mocking • Forces small changes • TDD is more about design
  29. @PreusslerBerlin Isn’t it slow? Writing tests is slower than not

    writing tests. You’ll write at least as much test code as production code TDD adds 10% — 30% on initial costs = longer to complete their projects
  30. @PreusslerBerlin Isn’t it slow? Writing tests is slower than not

    writing tests. You’ll write at least as much test code as production code TDD adds 10% — 30% on initial costs = longer to complete their projects
  31. @PreusslerBerlin Isn’t it slow? Research shows that TDD: • Reduces

    defect density by 60-90 % • Reduces production bug density by 40–80%
  32. @PreusslerBerlin Isn’t it slow? Without TDD, you spend a few

    weeks writing code which mostly works and spend the next year "testing" and fixing many (but not all) of the bugs With TDD, you spend a year writing code which actually works. Then you do final integration testing for a few weeks.
  33. @PreusslerBerlin Isn’t it slow? • Feature takes longer • You

    write at least as much test code as production code
  34. @PreusslerBerlin Isn’t it slow? • Bugfixing phase is shorter •

    Debugging disappears • Ci finds bugs before tester does • Long term it’s much faster no more big rewrite
  35. @PreusslerBerlin TDD and architecture • TDD does not replace Architecture

    and Design • Have a vision in your head • NO big up front design • Defer architecture decisions as long as possible
  36. @PreusslerBerlin TDD and architecture • TDD does not replace Architecture

    and Design • Have a vision in your head • NO big up front design • Defer architecture decisions as long as possible
  37. @PreusslerBerlin TDD and architecture • TDD does not replace Architecture

    and Design • Have a vision in your head • No big up front design • Defer architecture decisions as long as possible
  38. @PreusslerBerlin TDD and architecture • TDD does not replace Architecture

    and Design • Have a vision in your head • NO big up front design • Defer architecture decisions as long as possible
  39. @PreusslerBerlin TDD and architecture Write the tests that forces you

    to write the code you want to write Tip: Create a list of tests on paper
  40. @PreusslerBerlin Violations of DRY are typically referred to as WET

    solutions, which is commonly taken to stand for either "write everything twice" or "we enjoy typing” (http://en.wikipedia.org/wiki/Don't_repeat_yourself)
  41. @PreusslerBerlin Lets talk about Activities • now the tricky part

    starts https://www.flickr.com/photos/muchadoaboutnothing/438734626
  42. @PreusslerBerlin Android SDK under test • Android classes can be

    loaded on JVM: build/generated/mockable-android-XX.jar • No more finals!
  43. @PreusslerBerlin Android SDK under test • Empty methods with default

    return values android { … testOptions { unitTests.returnDefaultValues = true } -> no code will run
  44. @PreusslerBerlin Inversion of Control Common implementations: • Factory tracker =

    Factory.createTracker() • Service Locator • Dependency Injection
  45. @PreusslerBerlin Inversion of Control Common implementations: • Factory • Service

    Locator tracker = Locator.get(Tracker.class) • Dependency Injection
  46. @PreusslerBerlin Inversion of Control Common implementations: • Factory • Service

    Locator • Dependency Injection @Inject Tracker tracker;
  47. @PreusslerBerlin The problem of v4… Activity • mockable.jar not existing

    for libraries, including support library L -> real code will run
  48. @PreusslerBerlin What’s left? • Activities needs to be declared in

    manifest • Permissions for older devices (internet)
  49. @PreusslerBerlin Live coding • Manifest via lint lintOptions { check

    'Registered' warningsAsErrors true } * Has issues with Gradle Plugin 3.0 and Kotlin @PreusslerBerlin
  50. @PreusslerBerlin Lets talk about data binding • Testing android view

    classes are hard • So let’s make sure we don’t need to test them!
  51. @PreusslerBerlin Data binding… who is the view? • Solves the

    one big android question once and for all
  52. @PreusslerBerlin .. show a toast class SeriesViewModel : Viewmodel() {

    … @Bindable var error = ObservableField<String>()
  53. @PreusslerBerlin .. show a toast (alternative) <FrameLayout app:showError="@{viewModel.errorAppeared}"> @BindingAdapter("showError") fun

    ViewGroup.onErrorAppeared(error: String?){ errorString?.let { showToast(context, error)) } }
  54. @PreusslerBerlin What about Espresso • problem: • need to be

    fast! • need to run continuously • fast feedback
  55. @PreusslerBerlin Tired of issues like java.lang.NullPointerException at org.robolectric.manifest.MetaData. init(MetaData.java:55) at

    org.robolectric.manifest.AndroidMa nifest.initMetaData(AndroidManifes t.java:377).... ? Sleepy by Tomas; flickr.com/photos/tma/2438467223; CC 2.0 Don’t spent more time fixing your test setup than fixing your app Sleepy by Tomas; flickr.com/photos/tma/2438467223; CC 2.0
  56. @PreusslerBerlin What’s wrong with Robolectric? • Developers used too much

    magic forgot what unit test should be • Your tests rely on correct 3rd party implementation • Tests itself becomes flaky • It’s slower than pure JUnit
  57. @PreusslerBerlin Prototypes, POC and MVPs • For prototypes: hacking together

    is fine But after: start from scratch and build it test driven • For MVP: an MVP is a minimum feature set but no excuse for bad quality
  58. @PreusslerBerlin If it's worth building, it's worth testing If it's

    not worth testing, why are you wasting your time working on it?
  59. @PreusslerBerlin If it's worth building, it's worth testing If it's

    not worth testing, why are you wasting your time working on it?
  60. @PreusslerBerlin TDD on Android? • its possible! • its fun!

    https://www.flickr.com/photos/chefranden/14838138493
  61. @PreusslerBerlin Tools used • github.com/MarkusAmshove/Kluent • github.com/nhaarman/mockito-kotlin • Final mocking

    with mockito2: github.com/mockito/mockito/wiki/What%2 7s-new-in-Mockito-2#mock-the- unmockable-opt-in-mocking-of-final- classesmethods
  62. @PreusslerBerlin Tools used • Protected onCreate call in Kotlin: github.com/

    dpreussler/android-tdd-utils • Test friendly dependency Injection: github.com/ stephanenicolas/toothpick
  63. @PreusslerBerlin Tools used • Some test utils code for FragmentActivity,

    check TestUtils.kt github.com/ sporttotal-tv/android-tdd-workshop
  64. @PreusslerBerlin More resources • Test Driven Development by Example (Kent

    Beck) • https://cleancoders.com/videos • https://online-training.jbrains.ca/p/wbitdd-01 • http://news.codecademy.com/test-driven- development/