test drive android with robolectric - atlanta android meetup
DESCRIPTION
Test drive your Android applications with Robolectric! Links: Robolectric: http://pivotal.github.com/robolectric/ Code from the talk: https://github.com/joemoore/RobolectricSample IntelliJ CE (free!): http://www.jetbrains.com/idea/download/index.html Note: I barowed heavily from Tyler Schultz's Robolectric side deck: http://www.slideshare.net/tylerschultz/robolectric-android-unit-testing-frameworkTRANSCRIPT
![Page 1: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/1.jpg)
Android Unit Test Framework
http://pivotal.github.com/robolectricFollow us on twitter: @robolectric
Tuesday, March 22, 2011
![Page 2: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/2.jpg)
Joe Moore@joem
Pivotal Labs@pivotallabs
Tuesday, March 22, 2011
![Page 3: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/3.jpg)
Talking Points
• Testing Approaches and Alternatives
• How Robolectric works
• How to extend Robolectric
• Workshop - write tests & help getting you setup
Tuesday, March 22, 2011
![Page 4: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/4.jpg)
Disclaimer
• I’m more of a Ruby guy now.
• My Java Fu is lacking!
Tuesday, March 22, 2011
![Page 5: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/5.jpg)
Pivotal Labs
• www.pivotallabs.com
• San Francisco (Headquarters), New York, Boulder, Singapore
• Primarily Rails - we do mobile too!
• Agile, XP, Continuos Integration, Pair Programming
Tuesday, March 22, 2011
![Page 6: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/6.jpg)
Pivotal Labs
• Jasmine - Javascript BDD test framework, @jasminebdd
• Cedar - iOS/Objective-C BDD test framework, @cedarbdd
• Pivotal Tracker - www.pivotaltracker.com
You may have heard of us:
Tuesday, March 22, 2011
![Page 7: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/7.jpg)
java.lang.RuntimeException(“Stub!”)
Tuesday, March 22, 2011
![Page 8: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/8.jpg)
Google has stripped the classes in the android.jar file and
have had all their method bodies replaced with:
java.lang.RuntimeException(“Stub!”)
Tuesday, March 22, 2011
![Page 9: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/9.jpg)
Additional Android testing challenges
• Many of the classes and methods are final
• Lack of interfaces
• Non public constructors
• static methods
Tuesday, March 22, 2011
![Page 10: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/10.jpg)
How have you been testing?
Tuesday, March 22, 2011
![Page 11: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/11.jpg)
Android Testing Approaches
Tuesday, March 22, 2011
![Page 12: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/12.jpg)
Android Testing Approaches
• No Tests! EGAD!
Tuesday, March 22, 2011
![Page 13: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/13.jpg)
Android Testing Approaches
• No Tests! EGAD!
• Android InstrumentationTests/Robotium - integration style testing of Android apps
Tuesday, March 22, 2011
![Page 14: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/14.jpg)
Android Testing Approaches
• No Tests! EGAD!
• Android InstrumentationTests/Robotium - integration style testing of Android apps
• Library of tested POJO’s, referenced from a non tested Android project
Tuesday, March 22, 2011
![Page 15: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/15.jpg)
Android Testing Approaches
• No Tests! EGAD!
• Android InstrumentationTests/Robotium - integration style testing of Android apps
• Library of tested POJO’s, referenced from a non tested Android project
• Mocking framework such as Easy Mock and Mockito
Tuesday, March 22, 2011
![Page 16: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/16.jpg)
It’s Getting Better
• Robotium
• AndroidMock
• Calculon
• Robolectric
Tuesday, March 22, 2011
![Page 17: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/17.jpg)
Robolectric
Why use Robolectric?What makes it so great?
Tuesday, March 22, 2011
![Page 18: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/18.jpg)
Why Use Robolectricvs. Android Instrumentation Tests?
• Run FAST in a normal JVM, not on the emulator in the Dalvik VM (except for that damn regression...)
- Running in a Dalvik VM requires dexing, packaging and installation on an emulator or device - slow!
- Tests execute quickly in the JVM and execute slowly on the emulator
Tuesday, March 22, 2011
![Page 19: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/19.jpg)
Why Use Robolectricvs. Android Instrumentation Tests?
• Iterate quickly!
• The latest Pivotal Android project is using Robolectric boasting 1,047 tests that run in 28 seconds!
Tuesday, March 22, 2011
![Page 20: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/20.jpg)
Why Use Robolectricvs. POJO lib approach?
• We used to do this.
• The POJO lib approach leads to code proliferation, interfaces with multiple implementations - code bloat!
• Robolectric allows for vastly increased test coverage. Test ALL your code, not just non-Android code.
Tuesday, March 22, 2011
![Page 21: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/21.jpg)
• Mocking frameworks can lead to tests that are reverse implementation of the code
• Can lead to tests that are hard to read
• Can lead to tests that don’t help refactoring
Why use Robolectricvs. Mock approach?
Tuesday, March 22, 2011
![Page 22: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/22.jpg)
Why Use Robolectric?
• Iterate quickly
• Robolectric allows for a black box style of testing
• Test behavior instead of implementation
• High test coverage
Tuesday, March 22, 2011
![Page 23: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/23.jpg)
How does it work?
• Shadow Objects
• View and Resource Loading
Tuesday, March 22, 2011
![Page 24: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/24.jpg)
How does it work?
• Robolectric intercepts the loading of Android classes under test
• Rewrites the method bodies of Android classes (using javassist)
• Binds new shadow objects to new Android objects
• The modified Android objects proxy method calls to the shadow objects
Shadow objects
Tuesday, March 22, 2011
![Page 25: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/25.jpg)
How does it work?
• Shadows back the Android classes. i.e. ShadowImageView backs the ImageView class.
• AndroidObject.someMethod() => proxies to => ShadowAndroidObject.someMethod()
• State is recorded so it can be verified in tests
Shadow objects
Tuesday, March 22, 2011
![Page 26: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/26.jpg)
How does it work?
• Robolectric parses layout files and builds a view object tree made of Android view objects and, of course, their shadows.
• Some of the view xml attributes are applied to the view object
• Strings, string arrays, and color resources are parsed loaded too.
View and Resource Loading
Tuesday, March 22, 2011
![Page 27: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/27.jpg)
• http://pivotal.github.com/robolectric/index.html
• http://github.com/pivotal/RobolectricSample
How can I get started?
Tuesday, March 22, 2011
![Page 28: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/28.jpg)
Robolectric IDE support
• We are IntelliJ guys
• Eclipse works, too
• Maven!
Tuesday, March 22, 2011
![Page 29: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/29.jpg)
Robolectric
Writing Tests
Tuesday, March 22, 2011
![Page 30: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/30.jpg)
Writing Tests
...@RunWith(RobolectricTestRunner.class)public class MyActivityTest {
@Test! public void shouldDoWizbangFooBar() {...
Tests that reference Android need to be annotated:
Tuesday, March 22, 2011
![Page 31: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/31.jpg)
Writing Tests@Testpublic void shouldShowLogoWhenButtonIsPressed() {
Activity activity = new MyActivity();activity.onCreate(null);ImageView logo = (ImageView) activity.findViewById(R.id.logo);Button button = (Button) activity.findViewById(R.id.button);
assertThat(logo.getVisibility(), equalTo(View.GONE));
button.performClick();
assertThat(logo.getVisibility(), equalTo(View.VISIBLE));}
Tuesday, March 22, 2011
![Page 32: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/32.jpg)
Writing Tests
Dealing with cases where Android classes do not provide a way to retrieve object state
Tuesday, March 22, 2011
![Page 33: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/33.jpg)
Writing TestsAccessing the Shadow Object
<ImageViewandroid:id=”@+id/logo”android:layout_width=”wrap_content”android:layout_height=”wrap_content”android:src=”@drawable/logo” />
...
@Testpublic void logoImageViewShouldUseTheLogoDrawable() {
ImageView logo = (ImageView) activity.findViewById(R.id.logo);// imageView only provides logo.getDrawable();ShadowImageView logoShadow = Robolectric.shadowOf(logo);assertThat(logoShadow.resourceId, equalTo(R.drawable.logo));
}
Tuesday, March 22, 2011
![Page 34: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/34.jpg)
Shadow Objects
• @RealObject
• __constructor__
• @Implements
• @Implementation
• Robolectric.bindAllShadowClasses()
Tuesday, March 22, 2011
![Page 35: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/35.jpg)
Shadow Objects@RealObject
• Robolectric is using reflection to instantiate the shadow object (default or no-args constructor)
• Robolectric will inject the Android object onto shadow object’s fields annotated with @RealObject
Tuesday, March 22, 2011
![Page 36: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/36.jpg)
Shadow Objects@RealObject
@Implements(View.class)public class ShadowView {
@RealObject private View realView; private int id;...
Tuesday, March 22, 2011
![Page 37: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/37.jpg)
Shadow Objects
• If no shadow class is registered for an Android class, the Android object’s super constructor will seek out a shadow class, up through the constructor super chain until one is found.
Tuesday, March 22, 2011
![Page 38: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/38.jpg)
Shadow Objects__constructor__
• When Robolectric is finished instantiating the shadow object, it will attempt to invoke a method on the shadow named __constructor__ that has the same args as the Android object’s constructor
Tuesday, March 22, 2011
![Page 39: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/39.jpg)
Shadow Objects__constructor__
public class Intent { public Intent(String action, Uri uri) { /* compiled code */ } ...}
public class ShadowIntent { public void __constructor__(String action, Uri uri) { ... } ...}
Tuesday, March 22, 2011
![Page 40: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/40.jpg)
Shadow Objects@Implements
@Implements(View.class)public class ShadowView {
@RealObject private View realView; private int id;...
Tuesday, March 22, 2011
![Page 41: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/41.jpg)
Shadow Objects@Implementation
public class ShadowTextView {... @Implementation public CharSequence getText() { return text; }...
Tuesday, March 22, 2011
![Page 42: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/42.jpg)
Shadow ObjectsRobolectric.bindAllShadowClasses()
• Where shadow objects are registered into Robolectric
• This is a current listing of all the shadow objects provided by Robolectric
Tuesday, March 22, 2011
![Page 43: Test Drive Android with Robolectric - Atlanta Android Meetup](https://reader034.vdocuments.mx/reader034/viewer/2022051208/54793195b479599f098b46c0/html5/thumbnails/43.jpg)
Joe Moore@joem
Pivotal Labs@pivotallabs
Thanks!
Tuesday, March 22, 2011