SlideShare a Scribd company logo
New Android build system
Flavored with Roboguice and Robolectric

Andreas Würl, Thomas Endres
Ultracode Meetup, 2013-11-13
Overview
A short introduction
New Android build system
Roboguice
Robolectric
The speakers
Andreas Würl is an IT consultant for TNG Technology
consulting currently working in Unterföhring. In his free
time, he is contributing to the Blitzortung app available for
Android and in development for iOS.
Thomas Endres is also an IT consultant for TNG
Technology consulting. In his free time, he is developing
software for controlling drones with bare hands, building
apps and contributing to HTML5 frameworks.
Our apps
Blitzortung
Simple to use map based application visualizing real time
lightning data provided by blitzortung.org. The current
thunderstorm situation at your fingertips.
Be Quiet - The noise alert
Whether you work in an office or in a class room, Be
Quiet will help you reduce noise. When the volume is too
high, it will blink and play a siren sound.
Overview
A short introduction
New Android build system
Roboguice
Robolectric
Building Android applications
Old school

Based on Ant
No built-in dependency management
Quite inflexible
Using old built-in library versions
No support for real unit tests
Test project needed for instrumentation tests
The build xml file
<target name="compile" depends="-resource-src, -aidl"
description="Compiles project's .java files into .class files">
<!-- ... -->
<javac encoding="ascii" target="1.5" debug="true" extdirs=""
destdir="${out.classes.absolute.dir}"
bootclasspathref="android.target.classpath"
verbose="${verbose}" classpath="${extensible.classpath}"
classpathref="android.libraries.jars">
<src path="${source.absolute.dir}" />
<src path="${gen.absolute.dir}" />
<src refid="android.libraries.src" />
<classpath>
<fileset dir="${external.libs.absolute.dir}" includes="*.jar" />
<fileset dir="${extensible.libs.classpath}" includes="*.jar" />
</classpath>
</javac>
</target>

Customization is very difficult
[Ultracode Munich #4] Short introduction to the new Android build system including Android Studio, Roboguice and Robolectric
Building Android applications
The alternative

Based on Maven → Maven plugin
Allows for dependency management
A lot more flexible
→ But still far from being perfect
Real unit tests are possible
Still using a test project for instrumentation tests
The POM file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tngtech.internal.android</groupId>
<artifactId>android-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>apk</packaging>
<dependencies>
<dependency>
<groupId>com.google.android</groupId>
<artifactId>android</artifactId>
<version>${platform.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.jayway.maven.plugins.android.generation2</groupId>
<artifactId>android-maven-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<androidManifestFile>${project.basedir}/AndroidManifest.xml</androidManifestFile>
<assetsDirectory>${project.basedir}/assets</assetsDirectory>
<resourceDirectory>${project.basedir}/res</resourceDirectory>
<sdk><platform>18</platform></sdk>
</configuration>
</plugin>
</plugins>
</build>
</project>
Building Android applications
The new way

Based on Gradle → Gradle-Plugin
Built-in dependency management
Using common Java patterns
→ But flexible enough to change that
Real unit tests through plugins
Instrumentation tests within the same project
The Gradle build file
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.6.+'
}
}
apply plugin: 'android'
repositories {
mavenCentral()
}
dependencies {
// Put all dependencies here
}
android {
compileSdkVersion 18
buildToolsVersion "18.1.1"
defaultConfig {
minSdkVersion 18
targetSdkVersion 18
}
}
Android Studio
Android Studio
The facts

Based on IntelliJ
Ready to use
No additional plugins needed
Brings shortcuts for AVD and SDK manager
Out of the box support for the new build system
Possibility to migrate old projects
[Ultracode Munich #4] Short introduction to the new Android build system including Android Studio, Roboguice and Robolectric
Overview
A short introduction
New Android build system
Roboguice
Robolectric
What the heck is Roboguice?
A dependency injection container
An implementation of JSR 330
A fork of the Guice framework for the JDK
Easy to configure and to use
Dependency injection

Instead of taking

public class MainActivity extends Activity{
private LocationManager locationManager;
public void onCreate(Bundle savedInstance) {
// ...
locationManager = (LocationManager)
getSystemService(Activity.LOCATION_SERVICE);
}
}

be given
public class MainActivity extends RoboActivity{
@Inject
private LocationManager locationManager;
public void onCreate(Bundle savedInstance) {
// ...
}
}
Principles of DI
Don't let a class create objects on its own
Instead, pass them the objects they need
Then you can exchange them for test purposes
You can pass in test doubles
But you can also exchange the "real" object easily
Loose coupling becomes a reality
How can you inject objects?
Through the constructor:

@Inject
public MainActivity(LocationManager locationManager) {
// ...
this.locationManager = locationManager;
}

Into the field itself:
@Inject
private LocationManager locationManager;

Into a property:
@Inject
public void setLocationManager(LocationManager locationManager) {
this.locationManager = locationManager;
}
What can be injected?
Arbitrary objects with a zero-arg constructor
Objects with a constructor managed by Roboguice
Views:
@InjectView(R.id.specialButton)
private Button button;

Resources:
@InjectResource(R.drawable.specialPicture)
private Drawable picture;

A lot of standard Android objects:
LocationManager, AssetManager, ...
AlarmManager, NotificationManager, ...
Vibrator
Robo* classes
For DI to work, you have to extend the robo classes:
Use them instead of the standard Android classes
RoboActivity instead of Activity
RoboListActivity instead of ListActivity
RoboService instead of Service
RoboFragment instead of Fragment
...
Injecting providers:
Sometimes, you need more than one object of a class
public class SomeObjectProvider implements Provider<SomeObject> {
@Inject
private SomeOtherObject someOtherObject;
@Override
public SomeObject get() {
return new SomeObject(someOtherObject);
}
}
private class SomeObjectUser {
@Inject
private Provider<SomeObject> someObjectProvider;
private SomeObject getObject() {
return someObjectProvider.get();
}
}
Injecting injectors
You can also inject an injector
Then, you can get arbitrary objects out of the injector
@Inject
private Injector injector;
public <T> T giveMeAnObjectOf(Class<T> clazz) {
return injector.getInstance(clazz);
}
[Ultracode Munich #4] Short introduction to the new Android build system including Android Studio, Roboguice and Robolectric
Configuration
By defining a module, you can configure the objects injected
public class SomeModule extends AbstractModule {
@Override
public void configure() {
// Bind an interface to a specific class
bind(SomeInterface.class).to(SomeImplementation.class);
// Bind a standard provider to the class
bind(SomeClass.class).toProvider(SomeClassProvider.class);
}
}

Modules are discovered via "roboguice_modules.xml"
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="roboguice_modules">
<item>com.mypackage.SomeModule</item>
</string-array>
</resources>
Integrate Roboguice (1)
Add roboguice to the compile dependencies:
// build.gradle
dependencies {
// ...
compile 'roboguice:roboguice:2.+'
}

Extend the Robo* classes in your objects:
public class SomeActivity extends RoboActivity {
// ...
}

Inject your dependencies:
@Inject
private SomeObject someObject;
Integrate Roboguice (2)
Configure the module:
public class SomeModule extends AbstractModule {
@Override
protected void configure() {
bind(SomeClass.class).toProvider(SomeClassProvider.class);
// ...
}
}

Register the module:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="roboguice_modules">
<item>com.mypackage.SomeModule</item>
</string-array>
</resources>

Write unit tests:
public class SomeActivityTest {
// How to do that?
}
Overview
A short introduction
New Android build system
Roboguice
Robolectric
Android testing
in new build system

Based on JUnit3
Requires separate test project
Requires emulator or device for execution
Lacks real mocking
But initial support for some frameworks
[Ultracode Munich #4] Short introduction to the new Android build system including Android Studio, Roboguice and Robolectric
Can I run tests locally?
No. It's impossible!
Any method of the SDK will throw the following
exception when called:
java.lang.RuntimeException: Stub!
at android.*

Why is that?
Android SDK jars for development only contain method stubs
Is there a solution?
Yes! Use Robolectric
What the heck is Robolectric?
Android SDK wrapper/enabler for local test execution
Just another dependency of your project
Sometimes dependency order is important
Uses some magic to enable use of the stubbed SDK jars
Unfortunately not yet complete
What do I get?
Tests are running on the dev machine
Current version of JUnit 4 is used
Any Mock- or Match-Framework can be used
Can be used in parallel with instrumentation tests
How do I enable Robolectric?
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.6.+'
classpath 'com.squareup.gradle:gradle-android-test-plugin:0.9.+'
}
}
apply plugin: 'android'
apply plugin: 'android-test'
...
How do I implement a test?
Just use the RobolectricTestRunner
@RunWith(RobolectricTestRunner.class)
class SomeActivityTest {
@Before
public void setUp() {
// Preparation for every test
}
@Test
public void testSomething() {
// Your test code belongs here
assertThat(1, is(not(2));
}
}
Basic concepts
Shadows

TextView textView = (TextView) mainActivity.findViewById(R.id.helloWorld);
final ShadowTextView shadowTextView = Robolectric.shadowOf(textView);
assertThat(shadowTextView.innerText(), is("Hello World!"));

Implementation in Robolectric
@Implements(TextView.class)
public class ShadowTextView extends ShadowView {
@RealObject TextView realTextView;
@Override
public String innerText() {
CharSequence text = realTextView.getText();
return (text == null || realTextView.getVisibility() != View.VISIBLE) ? "" : text.toString();
}
@Implementation
public void setPaintFlags(int paintFlags) {
this.paintFlags = paintFlags;
}
}
Basic concepts

Robolectric builds up a full application context
Activities can be built
activity = Robolectric.buildActivity(MainActivity.class).create().get();

Testing resource access is possible as well
Resources resources = Robolectric.application.getResources();
assertThat(resources.getColor(R.color.Red), is(0xffff0000));

Modify preferences for tests
SharedPreferences defaultSharedPreferences =
ShadowPreferenceManager.getDefaultSharedPreferences(
Robolectric.application);
defaultSharedPreferences.edit()
.putBoolean("test", true).putFloat("limit", 1.0f).apply();
But ...

Android Studio integration is not yet available
Tests can be run via gradle task 'test'
> gradle test

IDE support only through ugly hacks
Summary

The new build system is a lot more flexible than the old one
Android Studio is a cool new tool for app development
It comes bundled with the SDK, you can start development
immediately
But there are still some issues with it
Roboguice makes it possbible to decouple your application
Robolectric can be used for local test execution
[Ultracode Munich #4] Short introduction to the new Android build system including Android Studio, Roboguice and Robolectric
Thank you!

Are there any questions?

andreas.wuerl@tngtech.com, thomas.endres@tngtech.com

More Related Content

PDF
Entwicklung mit Android Studio und Gradle
PPTX
Android Studio簡介
PDF
New to android studio
PDF
Android studio
PPTX
Introduction to android studio 2.0 and data binding library
PPTX
Gradle and Android Studio : Best of Friends
PPTX
Project a day 2 introduction to android studio
PDF
Android Studio vs. ADT
Entwicklung mit Android Studio und Gradle
Android Studio簡介
New to android studio
Android studio
Introduction to android studio 2.0 and data binding library
Gradle and Android Studio : Best of Friends
Project a day 2 introduction to android studio
Android Studio vs. ADT

What's hot (20)

PPTX
Android Studio vs Eclipse: What are the main differences?
PDF
Latest & interesting updates #android dev
PPTX
Exploring Android Studio
PDF
Head first android apps dev tools
PPTX
Comparison between Eclipse and Android Studio for Android Development
PPTX
React Native
PDF
Mobile Day - Intel XDK & Testing
PPTX
Android Studio 3 - Dependency-Aware Build Variants and Product Flavors
PDF
How to setup unit testing in Android Studio
PDF
Intro to Eclipse Che, by Tyler Jewell
PDF
#Code2Create:: Introduction to App Development in Flutter with Dart
PDF
Rapid Android Development for Hackathon
PPTX
Nativescript with angular 2
PDF
Experiences building apps with React Native @DomCode 2016
PDF
Getting Started with Cross-Platform Mobile Development with Flutter and Dart
PDF
From zero to hero with React Native!
PPTX
Fastlane
PPTX
Building your Own Mobile Enterprise Application: It’s Not as Hard as You Migh...
PPTX
Flutter 1
PDF
Intro to react native
Android Studio vs Eclipse: What are the main differences?
Latest & interesting updates #android dev
Exploring Android Studio
Head first android apps dev tools
Comparison between Eclipse and Android Studio for Android Development
React Native
Mobile Day - Intel XDK & Testing
Android Studio 3 - Dependency-Aware Build Variants and Product Flavors
How to setup unit testing in Android Studio
Intro to Eclipse Che, by Tyler Jewell
#Code2Create:: Introduction to App Development in Flutter with Dart
Rapid Android Development for Hackathon
Nativescript with angular 2
Experiences building apps with React Native @DomCode 2016
Getting Started with Cross-Platform Mobile Development with Flutter and Dart
From zero to hero with React Native!
Fastlane
Building your Own Mobile Enterprise Application: It’s Not as Hard as You Migh...
Flutter 1
Intro to react native
Ad

Similar to [Ultracode Munich #4] Short introduction to the new Android build system including Android Studio, Roboguice and Robolectric (20)

PDF
Learn How to Unit Test Your Android Application (with Robolectric)
PDF
Android Meetup Slovenija #3 - Testing with Robolectric by Ivan Kust
PPTX
Android developer's toolbox
PPTX
Robolectric Adventure
PDF
Android build process (1)
PDF
Introduction to Robotium
PDF
Droid con 2013 workshop unit testing in android [robolectirc]
PDF
Testing on Android
PDF
Thomas braun dependency-injection_with_robo_guice-presentation-final
ODP
Unit Test Android Without Going Bald
PDF
Robotium - sampath
ODP
Testing in Android: automatici, di integrazione, TDD e scenari avanzati
PPTX
Unit Testing Android Applications
PDF
Infinum Android Talks #13 - Developing Android Apps Like Navy Seals by Ivan Kušt
PDF
Inside Android Testing
PDF
Innovation Generation - The Mobile Meetup: Android Best Practices
PDF
Unit & Automation Testing in Android - Stanislav Gatsev, Melon
PPTX
Android Annotations and RoboGuice
PDF
Robotium Tutorial
Learn How to Unit Test Your Android Application (with Robolectric)
Android Meetup Slovenija #3 - Testing with Robolectric by Ivan Kust
Android developer's toolbox
Robolectric Adventure
Android build process (1)
Introduction to Robotium
Droid con 2013 workshop unit testing in android [robolectirc]
Testing on Android
Thomas braun dependency-injection_with_robo_guice-presentation-final
Unit Test Android Without Going Bald
Robotium - sampath
Testing in Android: automatici, di integrazione, TDD e scenari avanzati
Unit Testing Android Applications
Infinum Android Talks #13 - Developing Android Apps Like Navy Seals by Ivan Kušt
Inside Android Testing
Innovation Generation - The Mobile Meetup: Android Best Practices
Unit & Automation Testing in Android - Stanislav Gatsev, Melon
Android Annotations and RoboGuice
Robotium Tutorial
Ad

More from BeMyApp (20)

PPTX
Introduction to epid
PDF
Introduction ciot workshop premeetup
PPTX
Présentation des APIs cognitives IBM Watson
PDF
Crédit Agricole S.A. Personae et Parcours
PDF
Cisco Paris DevNet Hackathon slideshow - Intro
PPTX
Tumeurs Neuroendocrines : une vue d'ensemble
PPTX
Building your first game in Unity 3d by Sarah Sexton
PDF
Using intel's real sense to create games with natural user interfaces justi...
PPTX
Introduction to using the R200 camera & Realsense SDK in Unity3d - Jon Collins
PPTX
Audio Mixer in Unity5 - Andy Touch
PDF
Shaders - Claudia Doppioslash - Unity With the Best
PDF
[HACKATHON CISCO PARIS] Slideshow du workshop Smart City
PDF
Tools to Save Time
PDF
[Workshop e résidents] présentation intent, craft ai, dalkia et incubateur
PDF
[Webinar E-résidents #1] Présentation des différents métiers du bâtiment conn...
PPTX
[IoT World Forum Webinar] Review of CMX Cisco technology
PDF
HP Helion Episode 6: Cloud Foundry Summit Recap
PDF
Webinar UI/UX by Francesco Marcellino
PDF
HP Helion Webinar #5 - Security Beyond Firewalls
PDF
HP Helion Webinar #4 - Open stack the magic pill
Introduction to epid
Introduction ciot workshop premeetup
Présentation des APIs cognitives IBM Watson
Crédit Agricole S.A. Personae et Parcours
Cisco Paris DevNet Hackathon slideshow - Intro
Tumeurs Neuroendocrines : une vue d'ensemble
Building your first game in Unity 3d by Sarah Sexton
Using intel's real sense to create games with natural user interfaces justi...
Introduction to using the R200 camera & Realsense SDK in Unity3d - Jon Collins
Audio Mixer in Unity5 - Andy Touch
Shaders - Claudia Doppioslash - Unity With the Best
[HACKATHON CISCO PARIS] Slideshow du workshop Smart City
Tools to Save Time
[Workshop e résidents] présentation intent, craft ai, dalkia et incubateur
[Webinar E-résidents #1] Présentation des différents métiers du bâtiment conn...
[IoT World Forum Webinar] Review of CMX Cisco technology
HP Helion Episode 6: Cloud Foundry Summit Recap
Webinar UI/UX by Francesco Marcellino
HP Helion Webinar #5 - Security Beyond Firewalls
HP Helion Webinar #4 - Open stack the magic pill

Recently uploaded (20)

PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
DOCX
The AUB Centre for AI in Media Proposal.docx
PPTX
Big Data Technologies - Introduction.pptx
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
Encapsulation_ Review paper, used for researhc scholars
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PPTX
A Presentation on Artificial Intelligence
PDF
KodekX | Application Modernization Development
PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PDF
Spectral efficient network and resource selection model in 5G networks
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
The Rise and Fall of 3GPP – Time for a Sabbatical?
“AI and Expert System Decision Support & Business Intelligence Systems”
The AUB Centre for AI in Media Proposal.docx
Big Data Technologies - Introduction.pptx
Understanding_Digital_Forensics_Presentation.pptx
20250228 LYD VKU AI Blended-Learning.pptx
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Chapter 3 Spatial Domain Image Processing.pdf
Review of recent advances in non-invasive hemoglobin estimation
Encapsulation_ Review paper, used for researhc scholars
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
A Presentation on Artificial Intelligence
KodekX | Application Modernization Development
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
Spectral efficient network and resource selection model in 5G networks
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Per capita expenditure prediction using model stacking based on satellite ima...
Build a system with the filesystem maintained by OSTree @ COSCUP 2025

[Ultracode Munich #4] Short introduction to the new Android build system including Android Studio, Roboguice and Robolectric

  • 1. New Android build system Flavored with Roboguice and Robolectric Andreas Würl, Thomas Endres Ultracode Meetup, 2013-11-13
  • 2. Overview A short introduction New Android build system Roboguice Robolectric
  • 3. The speakers Andreas Würl is an IT consultant for TNG Technology consulting currently working in Unterföhring. In his free time, he is contributing to the Blitzortung app available for Android and in development for iOS. Thomas Endres is also an IT consultant for TNG Technology consulting. In his free time, he is developing software for controlling drones with bare hands, building apps and contributing to HTML5 frameworks.
  • 4. Our apps Blitzortung Simple to use map based application visualizing real time lightning data provided by blitzortung.org. The current thunderstorm situation at your fingertips. Be Quiet - The noise alert Whether you work in an office or in a class room, Be Quiet will help you reduce noise. When the volume is too high, it will blink and play a siren sound.
  • 5. Overview A short introduction New Android build system Roboguice Robolectric
  • 6. Building Android applications Old school Based on Ant No built-in dependency management Quite inflexible Using old built-in library versions No support for real unit tests Test project needed for instrumentation tests
  • 7. The build xml file <target name="compile" depends="-resource-src, -aidl" description="Compiles project's .java files into .class files"> <!-- ... --> <javac encoding="ascii" target="1.5" debug="true" extdirs="" destdir="${out.classes.absolute.dir}" bootclasspathref="android.target.classpath" verbose="${verbose}" classpath="${extensible.classpath}" classpathref="android.libraries.jars"> <src path="${source.absolute.dir}" /> <src path="${gen.absolute.dir}" /> <src refid="android.libraries.src" /> <classpath> <fileset dir="${external.libs.absolute.dir}" includes="*.jar" /> <fileset dir="${extensible.libs.classpath}" includes="*.jar" /> </classpath> </javac> </target> Customization is very difficult
  • 9. Building Android applications The alternative Based on Maven → Maven plugin Allows for dependency management A lot more flexible → But still far from being perfect Real unit tests are possible Still using a test project for instrumentation tests
  • 10. The POM file <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.tngtech.internal.android</groupId> <artifactId>android-demo</artifactId> <version>1.0-SNAPSHOT</version> <packaging>apk</packaging> <dependencies> <dependency> <groupId>com.google.android</groupId> <artifactId>android</artifactId> <version>${platform.version}</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>com.jayway.maven.plugins.android.generation2</groupId> <artifactId>android-maven-plugin</artifactId> <version>3.7.0</version> <configuration> <androidManifestFile>${project.basedir}/AndroidManifest.xml</androidManifestFile> <assetsDirectory>${project.basedir}/assets</assetsDirectory> <resourceDirectory>${project.basedir}/res</resourceDirectory> <sdk><platform>18</platform></sdk> </configuration> </plugin> </plugins> </build> </project>
  • 11. Building Android applications The new way Based on Gradle → Gradle-Plugin Built-in dependency management Using common Java patterns → But flexible enough to change that Real unit tests through plugins Instrumentation tests within the same project
  • 12. The Gradle build file buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.6.+' } } apply plugin: 'android' repositories { mavenCentral() } dependencies { // Put all dependencies here } android { compileSdkVersion 18 buildToolsVersion "18.1.1" defaultConfig { minSdkVersion 18 targetSdkVersion 18 } }
  • 14. Android Studio The facts Based on IntelliJ Ready to use No additional plugins needed Brings shortcuts for AVD and SDK manager Out of the box support for the new build system Possibility to migrate old projects
  • 16. Overview A short introduction New Android build system Roboguice Robolectric
  • 17. What the heck is Roboguice? A dependency injection container An implementation of JSR 330 A fork of the Guice framework for the JDK Easy to configure and to use
  • 18. Dependency injection Instead of taking public class MainActivity extends Activity{ private LocationManager locationManager; public void onCreate(Bundle savedInstance) { // ... locationManager = (LocationManager) getSystemService(Activity.LOCATION_SERVICE); } } be given public class MainActivity extends RoboActivity{ @Inject private LocationManager locationManager; public void onCreate(Bundle savedInstance) { // ... } }
  • 19. Principles of DI Don't let a class create objects on its own Instead, pass them the objects they need Then you can exchange them for test purposes You can pass in test doubles But you can also exchange the "real" object easily Loose coupling becomes a reality
  • 20. How can you inject objects? Through the constructor: @Inject public MainActivity(LocationManager locationManager) { // ... this.locationManager = locationManager; } Into the field itself: @Inject private LocationManager locationManager; Into a property: @Inject public void setLocationManager(LocationManager locationManager) { this.locationManager = locationManager; }
  • 21. What can be injected? Arbitrary objects with a zero-arg constructor Objects with a constructor managed by Roboguice Views: @InjectView(R.id.specialButton) private Button button; Resources: @InjectResource(R.drawable.specialPicture) private Drawable picture; A lot of standard Android objects: LocationManager, AssetManager, ... AlarmManager, NotificationManager, ... Vibrator
  • 22. Robo* classes For DI to work, you have to extend the robo classes: Use them instead of the standard Android classes RoboActivity instead of Activity RoboListActivity instead of ListActivity RoboService instead of Service RoboFragment instead of Fragment ...
  • 23. Injecting providers: Sometimes, you need more than one object of a class public class SomeObjectProvider implements Provider<SomeObject> { @Inject private SomeOtherObject someOtherObject; @Override public SomeObject get() { return new SomeObject(someOtherObject); } } private class SomeObjectUser { @Inject private Provider<SomeObject> someObjectProvider; private SomeObject getObject() { return someObjectProvider.get(); } }
  • 24. Injecting injectors You can also inject an injector Then, you can get arbitrary objects out of the injector @Inject private Injector injector; public <T> T giveMeAnObjectOf(Class<T> clazz) { return injector.getInstance(clazz); }
  • 26. Configuration By defining a module, you can configure the objects injected public class SomeModule extends AbstractModule { @Override public void configure() { // Bind an interface to a specific class bind(SomeInterface.class).to(SomeImplementation.class); // Bind a standard provider to the class bind(SomeClass.class).toProvider(SomeClassProvider.class); } } Modules are discovered via "roboguice_modules.xml" <?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="roboguice_modules"> <item>com.mypackage.SomeModule</item> </string-array> </resources>
  • 27. Integrate Roboguice (1) Add roboguice to the compile dependencies: // build.gradle dependencies { // ... compile 'roboguice:roboguice:2.+' } Extend the Robo* classes in your objects: public class SomeActivity extends RoboActivity { // ... } Inject your dependencies: @Inject private SomeObject someObject;
  • 28. Integrate Roboguice (2) Configure the module: public class SomeModule extends AbstractModule { @Override protected void configure() { bind(SomeClass.class).toProvider(SomeClassProvider.class); // ... } } Register the module: <?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="roboguice_modules"> <item>com.mypackage.SomeModule</item> </string-array> </resources> Write unit tests: public class SomeActivityTest { // How to do that? }
  • 29. Overview A short introduction New Android build system Roboguice Robolectric
  • 30. Android testing in new build system Based on JUnit3 Requires separate test project Requires emulator or device for execution Lacks real mocking But initial support for some frameworks
  • 32. Can I run tests locally? No. It's impossible! Any method of the SDK will throw the following exception when called: java.lang.RuntimeException: Stub! at android.* Why is that? Android SDK jars for development only contain method stubs Is there a solution? Yes! Use Robolectric
  • 33. What the heck is Robolectric? Android SDK wrapper/enabler for local test execution Just another dependency of your project Sometimes dependency order is important Uses some magic to enable use of the stubbed SDK jars Unfortunately not yet complete
  • 34. What do I get? Tests are running on the dev machine Current version of JUnit 4 is used Any Mock- or Match-Framework can be used Can be used in parallel with instrumentation tests
  • 35. How do I enable Robolectric? buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.6.+' classpath 'com.squareup.gradle:gradle-android-test-plugin:0.9.+' } } apply plugin: 'android' apply plugin: 'android-test' ...
  • 36. How do I implement a test? Just use the RobolectricTestRunner @RunWith(RobolectricTestRunner.class) class SomeActivityTest { @Before public void setUp() { // Preparation for every test } @Test public void testSomething() { // Your test code belongs here assertThat(1, is(not(2)); } }
  • 37. Basic concepts Shadows TextView textView = (TextView) mainActivity.findViewById(R.id.helloWorld); final ShadowTextView shadowTextView = Robolectric.shadowOf(textView); assertThat(shadowTextView.innerText(), is("Hello World!")); Implementation in Robolectric @Implements(TextView.class) public class ShadowTextView extends ShadowView { @RealObject TextView realTextView; @Override public String innerText() { CharSequence text = realTextView.getText(); return (text == null || realTextView.getVisibility() != View.VISIBLE) ? "" : text.toString(); } @Implementation public void setPaintFlags(int paintFlags) { this.paintFlags = paintFlags; } }
  • 38. Basic concepts Robolectric builds up a full application context Activities can be built activity = Robolectric.buildActivity(MainActivity.class).create().get(); Testing resource access is possible as well Resources resources = Robolectric.application.getResources(); assertThat(resources.getColor(R.color.Red), is(0xffff0000)); Modify preferences for tests SharedPreferences defaultSharedPreferences = ShadowPreferenceManager.getDefaultSharedPreferences( Robolectric.application); defaultSharedPreferences.edit() .putBoolean("test", true).putFloat("limit", 1.0f).apply();
  • 39. But ... Android Studio integration is not yet available Tests can be run via gradle task 'test' > gradle test IDE support only through ugly hacks
  • 40. Summary The new build system is a lot more flexible than the old one Android Studio is a cool new tool for app development It comes bundled with the SDK, you can start development immediately But there are still some issues with it Roboguice makes it possbible to decouple your application Robolectric can be used for local test execution
  • 42. Thank you! Are there any questions? andreas.wuerl@tngtech.com, thomas.endres@tngtech.com