Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
MCE2015 - Automated Testing for Modern Android ...
Search
Andy Dyer
February 06, 2015
Programming
1.5k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
MCE2015 - Automated Testing for Modern Android Applications
Andy Dyer
February 06, 2015
More Decks by Andy Dyer
See All by Andy Dyer
AppCraft: Faster Than a Speeding Release Train
abdyer
1
370
Multiple Developers, One App: How to Not Break Everything
abdyer
0
390
Things That Suck About Android Development
abdyer
0
620
Building an Android Wear app
abdyer
0
110
BABBQ5 - Automated Testing for Modern Android Applications
abdyer
14
3.8k
Other Decks in Programming
See All in Programming
源内ハンズオン概要編
hideg
0
210
tsc.rip を支える技術 / Kyoto.なんか #8
susisu
0
500
Jindong: Introducing Declarative Haptics in Compose Multiplatform
l2hyunwoo
0
130
異なる設計思想のフレームワークを経験して得た学び
amekuhideki
1
630
仕様駆動開発へのトライを機に チームに適合する手法を模索し続けている話
freee
PRO
0
620
Flow は今どうなっているか
mizdra
PRO
0
730
Deep dive into the select statement (GopherCon UK)
jespino
0
110
仕様駆動開発の消費期限
watany
20
9k
思考垂れ流し開発 ~音声入力 × AIエージェント × 開発ハーネスによる試行錯誤~
npostring
0
260
[PyCon KR 2026] More Variants, More Diversity for AI Accelerators
achimnol
0
110
レビュー履歴をAIに食わせて、 Compose移行を加速するs
shihochan
0
220
Japan Community Day at Kubecon + CloudNativeCon Japan 2026: Learning Container Privilege Control by Building My Own Low-Level Container Runtime
ternbusty
1
170
Featured
See All Featured
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
490
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
290
Product Roadmaps are Hard
iamctodd
55
12k
Faster Mobile Websites
deanohume
310
32k
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
580
Test your architecture with Archunit
thirion
2
2.4k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.8k
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
73
42k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
310
[RailsConf 2023] Rails as a piece of cake
palkan
59
6.9k
Building a Scalable Design System with Sketch
lauravandoore
463
34k
New Earth Scene 8
popppiees
3
2.5k
Transcript
Automated Testing for Modern Android Applications
Andy Dyer +AndrewDyer @dammitandy
None
Making Android apps testable
Dynamic languages Tests shouldn't drive implementation.
Static languages You know nothing.
Making Android apps testable 1. Dependency injection 2. Mocking &
stubbing 3. Unit & integration tests
Dependency injection
Dependency injection • Classes receive dependencies, don’t have to know
where to find them or how to create them • Swap components for mocks in tests • Use different components for different build flavors, etc.
Basic dependency injection public class Beer implements Reinheitsgebot { Water
water; Barley barley; Hops hops; public Beer(Water water, Barley barley, Hops hops) { this.water = water; this.barley = barley; this.hops = hops; } }
Dagger A Java dependency injection library
Dagger • Defining dependencies at compile time avoids reflection at
runtime • Compiler validates components, modules, and injections • Dagger 2 is currently in alpha, but already being used by Google in production apps google.github.io/dagger/
Dagger Modules @Module public class MyModule { @Provides @Singleton public
MyService provideMyService() { return new MyService(); } }
Dagger Components @Component(modules = MyModule.class) public interface Graph { void
inject(Activity activity); void inject(Fragment fragment); public final static class Initializer { public static Graph init(boolean mockMode) { return Dagger_Graph.builder().build(); } } }
Dagger Object Graph public class MyApplication extends Application { @Getter
static DemoApplication instance; @Getter Graph graph; @Override public void onCreate() { super.onCreate(); instance = this; graph = Graph.Initializer.init(false); } public void setMockMode(boolean useMock) { graph = Graph.Initializer.init(useMock); } }
Dagger dependency injection public class MyFragment extends Fragment { @Inject
MyService service; @Override public void onViewCreated(View view, Bundle savedInstanceState) { MyApplication.getInstance().getGraph().inject(this); service.getMyData(); } }
Learning more about Dagger • Jake Wharton - Dependency Injection
with Dagger 2 parleys.com/play/5471cdd1e4b065ebcfa1d557 • Gregory Kick - Dagger 2: A New Type of Dependency Injection youtube.com/watch?v=oK_XtfXPkqw
Mocking & Stubbing
Mocking & Stubbing • Substitute runtime implementation for something that
can be predictably tested in isolation • Verify behavior
A Java mocking library
Mockito • Mock/stub dependencies and function return values • Inject
mocks to validate behavior in tests • Use included Hamcrest matchers for clear, readable tests code.google.com/p/mockito/
Using Mockito // create mock MyClass mocked = mock(MyClass.class); //
specify behavior when(mocked.doSomething()).thenReturn(somethingElse); // verify method calls verify(mocked).getMyData(anyInt(), anyString());
Using Mockito // capture arguments ArgumentCaptor<Callback> captor = ArgumentCaptor.forClass(Callback.class); verify(authenticationService).login(anyString(),
anyString(), captor.capture()); // simulate error conditions, etc. captor.getValue().failure(RetrofitError.unexpectedError( "Invalid password", new Exception()));
Unit & Integration Tests
Tests or it didn't happen
Unit testing public class BeerTest extends InstrumentationTestCase { @Inject Beer
beer; @Override protected void setUp() throws Exception { MyApplication.getInstance().getGraph().inject(this); } public void testBeerIsGood() { assertTrue(beer.isGood()); } }
An Android UI testing library
Espresso • Handles activity creation & state sync • Simple,
concise API • Really fast! code.google.com/p/android-test-kit*
UI testing with Espresso public class MyActivityTest extends ActivityInstrumentationTestCase2<MyActivity> {
public MyActivityTest() { super(MyActivity.class); } @Override protected void setUp() throws Exception { super.setUp(); getActivity(); // trigger activity launch } public void testInvalidEmailShowsError() { onView(withId(R.id.email)).perform(typeText("abc"), closeSoftKeyboard()); onView(withId(R.id.email_sign_in_button)).perform(click()); onView(withId(R.id.email)).check(matches(withError( getActivity().getString(R.string.error_invalid_email)))); } }
Sample application • Dagger object graph • Retrofit API with
sample request • Lombok & Android Studio plugin • Login activity • Activity with fragment to make API request and display data
Testing the login activity • Simulate data entry and taps
to validate UI functionality • Simulate an error without making a network request
Testing the main activity • Verify the RecyclerView contains data
• Simulate taps to validate the appropriate URLs are loaded in a WebView
Testing the API • Use mock API response loaded from
text file to validate JSON parsing
Demo
Known issues • Some tests may fail on older devices/emulators
such as those running < API 18. Hopefully this will be fixed soon by an update to the test support library.
Additional resources • Bryan Stern/Circle Engineering - Instrumentation Testing with
Dagger, Mockito, and Espresso engineering.circle.com/instrumentation-testing-with-dagger- mockito-and-espresso
Conclusion Using dependency injection, mocking, and automated testing tools helps
us build better apps. Working together as a community, we can make testing even easier.
Questions?
Slides speakerdeck.com/abdyer/mce2015-automated-testing-for- modern-android-applications Code github.com/abdyer/android-test-demo/releases/tag/ mceconf-2015 +AndrewDyer @dammitandy