Unit Test Android Without Going Bald

17
Unit Testing Android without Going Bald! CodeMash 2015 David Carver Gplus: +David Carver Twitter: @kingargyle https://github.com/NineWorlds/serenity-android

Transcript of Unit Test Android Without Going Bald

Page 1: Unit Test Android Without Going Bald

Unit Testing Android without Going Bald!

CodeMash 2015David Carver

Gplus: +David CarverTwitter: @kingargyle

https://github.com/NineWorlds/serenity-android

Page 2: Unit Test Android Without Going Bald

What is Unit Testing??

● Issolated tests to a particular class.● Does not test the functionality of other classes.● Tests only the public methods.

– May test the protected methods

● Tests the expected output of a method.

Page 3: Unit Test Android Without Going Bald

Android Testing

● Difficult to Unit Test● Must run on device or emulator

– Emulator slow to start up and execute

– Devices must be connected to CI machines

● Slow startup and execution times.● Developers do not run the tests as often or do

not even write tests.● Leading to untested code, and more manual

testing or only Integration tests.

Page 4: Unit Test Android Without Going Bald
Page 5: Unit Test Android Without Going Bald

Why not just use AndroidTestCase

● Slow and requires an Emulator or Device to run.

● Can use Android Mocks for Activities and Services but still requires a device or emulator.

● Requires a separate project for tests.● Tests and code are not kept together.● Uses Junit and not Junit 4.

Page 6: Unit Test Android Without Going Bald

What other Options?

● Robotium – Integration / Functional testing framework that tests from the UI. Not designed for Unit Testing.

● Calabash – Ruby/Cucumber type framework. More suited for Integration / Behavior tests.

● UI Automator – Extremely slow. Integration testing

● MonekyRunner – Integration Testing.● All of these require a device or emulator to

run.

Page 7: Unit Test Android Without Going Bald

Unit Testing Goals

● Must be fast otherwise developers won't run them and won't write them.

● Should be written in the same language. Less learning curve.

● Should integrate with existing tools and IDEs.● Must provide a fast feedback on the

development cycle.● Ideally integrate with code coverage tools and

easy integration as part of the build.

Page 8: Unit Test Android Without Going Bald

Rogaine for Android Unit Testing

● Junit 4 – Provides a more modern way to test.● Mockito

– Mocking Framework

– Can mock concrete classes

– Fluent style API for easy readability and setup

– Can spy on existing methods and classes

● Robolectric – Provides a Mocking Framework and TestRunner for Android

● Dagger – Dependency Injection Framework

Page 9: Unit Test Android Without Going Bald

Robolectric

● Mocking framework for the Android Platform.– Provides mock implementations for various

Platform versions.

– Allows Tests to run on the Java VM instead of a device or emulator.

– Tests run locally

– Feedback cycle is seconds instead of minutes.

– Open Source project with large community

– https://github.com/robolectric/robolectric

Page 10: Unit Test Android Without Going Bald

Mockito

● Mocking Framework that does the heavy lifting for you.

● doReturn(true).when(mockView).isVisible()– When the method isVisible is called return true as

the result.

– Mock code never executes real implementations.

● Allows for issolation of the Class/Method under tests from it's dependencies.

● Helps focus testing to the result of the method and not testing of other frameworks.

Page 11: Unit Test Android Without Going Bald

Mockito

● View spyView = spy(realView)● doReturn(true).when(spyView).isVisible()

– When the method isVisible is called return true as the result.

– Mock code never executes real implementations.

● verify(spyView).isVisible()– Allows verification that a method is called without

actually calling the underlying code.

– Good for mocking out protected methods that otherwise aren't accessible.

Page 12: Unit Test Android Without Going Bald

Real World Results

● Selenium Android Driver – extremely slow● UI Automator – 20 tests – 8 minutes to

execute.● Robolectric, Mockito, plus RoboGuice –

better, 600 tests, about 8 minutes to execute.● Robolectric, Mockito, plus Dagger – 1700

tests, 3 minutes to execute.– Code Coverage using Jacoco – 91%

● Robolectric allows for integration with existing Technical Debt tools like Sonar.

Page 13: Unit Test Android Without Going Bald
Page 14: Unit Test Android Without Going Bald

Test Examples

● Simple Junit 4 test● Robolectric Activity Test● Robolectric plus Mockito Test – (Views)● https://github.com/NineWorlds/serenity-

android/tree/master/serenity-app/src/test/java

Page 15: Unit Test Android Without Going Bald

Making your Code Testable

● Avoid Anonymous Inner Classes– Hard to write unit tests for.

– End up writing Integration Tests

● Try to write classes and methods that follow the Single Responsibility Principal.

● Listeners should be implemented in their own Classes, not in Activities!

● Use Dependency Injection– Allows for easy injection of Mocks for tests

● Activities should just be lifecycle managers

Page 16: Unit Test Android Without Going Bald

Conclusion

● Robolectric does not replace Integration or Functional Tests.

● Robotium and UI Automator still have their places.

● DO NOT Use Robolectric as an Integration Test platform it is a Mocking Framework.

● Use Robolectric.buildActivity() sparingly. Has high startup overhead.

● Mockito can mock anything in the Android Framework, but may have large number of mocks.

Page 17: Unit Test Android Without Going Bald

Conclusion

● Running tests locally is 10 times faster and productive than running tests on a device.

● The more tests the less likely you are to have critical bugs slip through.

● If you get a bug...WRITE A TEST FOR IT.● Provides a regression test suite when multiple

developers are working on the code.● Lets you keep what little hair you may have

left.