Top Banner
Android Unit Test Framework http://pivotal.github.com/robolectric Follow us on twitter: @robolectric Wednesday, October 27, 2010
47

Learn How to Unit Test Your Android Application (with Robolectric)

Jan 21, 2018

Download

Technology

Marakana Inc.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Learn How to Unit Test Your Android Application (with Robolectric)

Android Unit Test Framework

http://pivotal.github.com/robolectricFollow us on twitter: @robolectric

Wednesday, October 27, 2010

Page 2: Learn How to Unit Test Your Android Application (with Robolectric)

Tyler SchultzAgile Engineer, Pivotal Labs

Wednesday, October 27, 2010

Page 3: Learn How to Unit Test Your Android Application (with Robolectric)

Talking Points

• Testing Approaches and Alternatives

• How Robolectric works

• How to extend Robolectric

• Workshop - write tests & help getting you setup

Wednesday, October 27, 2010

Page 4: Learn How to Unit Test Your Android Application (with Robolectric)

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:

Wednesday, October 27, 2010

Page 5: Learn How to Unit Test Your Android Application (with Robolectric)

Why Unit Test?

Wednesday, October 27, 2010

Page 6: Learn How to Unit Test Your Android Application (with Robolectric)

Pivotal Labs

• www.pivotallabs.com

• San Francisco (Headquarters), New York, Boulder, Singapore

• Primarily Rails - we do mobile too!

• Agile, XP, Continuos Integration, Pair Programming

Wednesday, October 27, 2010

Page 7: Learn How to Unit Test Your Android Application (with Robolectric)

java.lang.RuntimeException(“Stub!”)

Wednesday, October 27, 2010

Page 8: Learn How to Unit Test Your Android Application (with Robolectric)

Google has stripped the classes in the android.jar file and have had all their method bodies replaced with:

throw new RuntimeException(“Stub!”);

Wednesday, October 27, 2010

Page 9: Learn How to Unit Test Your Android Application (with Robolectric)

Additional Android testing challenges

• Many of the classes and methods are final

• Lack of interfaces

• Non public constructors

• static methods

Wednesday, October 27, 2010

Page 10: Learn How to Unit Test Your Android Application (with Robolectric)

sfandroid.org members, what have you been doing?

Wednesday, October 27, 2010

Page 11: Learn How to Unit Test Your Android Application (with Robolectric)

Android Testing Approaches

Wednesday, October 27, 2010

Page 12: Learn How to Unit Test Your Android Application (with Robolectric)

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

Wednesday, October 27, 2010

Page 13: Learn How to Unit Test Your Android Application (with Robolectric)

Robolectric

Wednesday, October 27, 2010

Page 14: Learn How to Unit Test Your Android Application (with Robolectric)

Robolectric

• Christian Williams wrote the core while working on projects at Xtreme Labs of Toronto. Thank You Xtreme Labs!

• Robolectric is published under the MIT license

Wednesday, October 27, 2010

Page 15: Learn How to Unit Test Your Android Application (with Robolectric)

Robolectric

• Pivotal Labs has forked Xtreme Labs repo, renamed it to Robolectric, and expanded its functionality

• We’ve used Robolectric on several projects with great success!

Wednesday, October 27, 2010

Page 16: Learn How to Unit Test Your Android Application (with Robolectric)

Robolectric

Why use Robolectric?What makes it so great?

Wednesday, October 27, 2010

Page 17: Learn How to Unit Test Your Android Application (with Robolectric)

Why Use Robolectricvs. Android Instrumentation Tests?

• Tests Run outside of the emulator in a JVM, not the Dalvik VM

- 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

Wednesday, October 27, 2010

Page 18: Learn How to Unit Test Your Android Application (with Robolectric)

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!

Wednesday, October 27, 2010

Page 19: Learn How to Unit Test Your Android Application (with Robolectric)

Why Use Robolectricvs. POJO lib approach?

• 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.

Wednesday, October 27, 2010

Page 20: Learn How to Unit Test Your Android Application (with Robolectric)

• 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?

Wednesday, October 27, 2010

Page 21: Learn How to Unit Test Your Android Application (with Robolectric)

Why Use Robolectric?

• Iterate quickly

• Robolectric allows for a black box style of testing

• Test behavior instead of implementation

• High test coverage

Wednesday, October 27, 2010

Page 22: Learn How to Unit Test Your Android Application (with Robolectric)

How does it work?

Google has stripped the classes in the android.jar file and have had all their method bodies replaced with:

throw new RuntimeException(“Stub!”);

Wednesday, October 27, 2010

Page 23: Learn How to Unit Test Your Android Application (with Robolectric)

How does it work?

• Shadow Objects

• View and Resource Loading

Wednesday, October 27, 2010

Page 24: Learn How to Unit Test Your Android Application (with Robolectric)

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

Wednesday, October 27, 2010

Page 25: Learn How to Unit Test Your Android Application (with Robolectric)

How does it work?

• Shadows back the Android classes. i.e. ShadowImageView backs the ImageView class.

• Method calls to the Android object are proxied to the shadow object’s method of the same signature, if it exists.

• Simple implementations giving rudimentary behavior

• State is recorded so it can be verified in tests

Shadow objects

Wednesday, October 27, 2010

Page 26: Learn How to Unit Test Your Android Application (with Robolectric)

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 (currently applies: id, visibility, enabled, text, checked, and src)

• Strings, string arrays, and color resources are parsed loaded too.

View and Resource Loading

Wednesday, October 27, 2010

Page 27: Learn How to Unit Test Your Android Application (with Robolectric)

• RobolectricSample is a project that is setup to use Robolectric

• http://github.com/pivotal/RobolectricSample

How can I get started?

Wednesday, October 27, 2010

Page 28: Learn How to Unit Test Your Android Application (with Robolectric)

Getting Started with Robolectric

$ git clone git://github.com/pivotal/RobolectricSample.git

$ cd RobolectricSample

$ git submodule update --init

$ android update project -p .

$ ant clean test

These commands are available on the RobolectricSample README file

Wednesday, October 27, 2010

Page 29: Learn How to Unit Test Your Android Application (with Robolectric)

RobolectricSampleAnt Support

• RobolectricSample provides a build.xml file which defines a test task

• Useful for Continuous Integration

Wednesday, October 27, 2010

Page 30: Learn How to Unit Test Your Android Application (with Robolectric)

Robolectric IDE support

• RobolectricSample is setup with IntelliJ project files. We’re using the latest IntelliJ EAP.

• Eclipse compatibility is currently unknown. We need help from the community getting Eclipse support!

• If nothing else, you should be able to use your favorite tooling to write your code and use the ant tasks to build and test.

Wednesday, October 27, 2010

Page 31: Learn How to Unit Test Your Android Application (with Robolectric)

RobolectricSampleProject Layout

• RobolectricSample - main Android module

• robolectric - module containing the robolectric test framework (also a git submodule)

• aidl - module containing any aidl files your project defines

• code - module where application code and tests go

Wednesday, October 27, 2010

Page 32: Learn How to Unit Test Your Android Application (with Robolectric)

Robolectric

Writing Tests

Wednesday, October 27, 2010

Page 33: Learn How to Unit Test Your Android Application (with Robolectric)

Writing Tests

...@RunWith(RobolectricTestRunner.class)public class MyActivityTest {

@Test! public void shouldDoWizbangFooBar() {...

Tests that reference Android need to be annotated:

Wednesday, October 27, 2010

Page 34: Learn How to Unit Test Your Android Application (with Robolectric)

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));}

Wednesday, October 27, 2010

Page 35: Learn How to Unit Test Your Android Application (with Robolectric)

Writing Tests

Dealing with cases where Android classes do not provide a way to retrieve object state

Wednesday, October 27, 2010

Page 36: Learn How to Unit Test Your Android Application (with Robolectric)

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));

}

Wednesday, October 27, 2010

Page 37: Learn How to Unit Test Your Android Application (with Robolectric)

Shadow Objects

• @RealObject

• __constructor__

• @Implements

• @Implementation

• Robolectric.bindAllShadowClasses()

Wednesday, October 27, 2010

Page 38: Learn How to Unit Test Your Android Application (with Robolectric)

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

Wednesday, October 27, 2010

Page 39: Learn How to Unit Test Your Android Application (with Robolectric)

Shadow Objects@RealObject

@Implements(View.class)public class ShadowView {

@RealObject private View realView; private int id;...

Wednesday, October 27, 2010

Page 40: Learn How to Unit Test Your Android Application (with Robolectric)

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.

Wednesday, October 27, 2010

Page 41: Learn How to Unit Test Your Android Application (with Robolectric)

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

Wednesday, October 27, 2010

Page 42: Learn How to Unit Test Your Android Application (with Robolectric)

Shadow Objects__constructor__

public class Intent { public Intent(String action, Uri uri) { /* compiled code */ } ...}

public class ShadowIntent { public void __constructor__(String action, Uri uri) { ... } ...}

Wednesday, October 27, 2010

Page 43: Learn How to Unit Test Your Android Application (with Robolectric)

Shadow Objects@Implements

@Implements(View.class)public class ShadowView {

@RealObject private View realView; private int id;...

Wednesday, October 27, 2010

Page 44: Learn How to Unit Test Your Android Application (with Robolectric)

Shadow Objects@Implementation

public class ShadowTextView {... @Implementation public CharSequence getText() { return text; }...

Wednesday, October 27, 2010

Page 45: Learn How to Unit Test Your Android Application (with Robolectric)

Shadow ObjectsRobolectric.bindAllShadowClasses()

• Where shadow objects are registered into Robolectric

• This is a current listing of all the shadow objects provided by Robolectric

Wednesday, October 27, 2010

Page 46: Learn How to Unit Test Your Android Application (with Robolectric)

RobolectricRoadmap

• Eclipse support

• Simplified setup - robolectric.jar

• continued shadow updates and additions

• resource overrides, i.e. hdpi, landscape, i18n, etc.

Wednesday, October 27, 2010

Page 47: Learn How to Unit Test Your Android Application (with Robolectric)

Q & A & Workshop!

• git clone git://github.com/pivotal/RobolectricSample.git

• Mac users can download the latest IntelliJ EAP from my machine: http://tschultz.local

• Add a button to the homepage of RobolectricSample that toggles the visibility of the robolectric logo. Tests First!

http://pivotal.github.com/robolectrichttp://pivotal.github.com/RoblectricSample

twitter: @robolectric

Wednesday, October 27, 2010