Unit Test Android Without Going Bald
-
Upload
david-carver -
Category
Technology
-
view
330 -
download
1
Transcript of 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
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.
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.
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.
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.
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.
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
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
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.
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.
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.
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
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
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.
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.