#MBLTdev: Автоматическое тестирование Android приложений c...

40
Lovely Testing of Android Apps Effective and safe auto testing of Android apps. From Siberia with Love. Alex Korovyansky #{MBLT}DEV October 28, 2014

description

#MBLTdev: Конференция мобильных разработчиков Спикер: Автоматическое тестирование Android приложений c любовью http://mbltdev.ru/

Transcript of #MBLTdev: Автоматическое тестирование Android приложений c...

Page 1: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

Lovely Testing of Android AppsEffective and safe auto testing of Android apps. From Siberia with Love.

Alex Korovyansky #{MBLT}DEV

October 28, 2014

Page 2: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

Do we need auto testing for our Android apps?

Page 3: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

Yes, we do! If we want to be successful in long term.But, it should be safe (no flaky tests and buggy tools) and effective (easy to extend, fast to write, fast to run)!

Page 4: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

Problems

Page 5: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Complexity of mobile UI testing

Problems

Page 6: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Complexity of mobile UI testing

• Mobile artefacts (GPS, sensors, etc)

Problems

Page 7: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Complexity of mobile UI testing

• Mobile artefacts (GPS, sensors, etc)

• Huge number of different devices

Problems

Page 8: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Complexity of mobile UI testing

• Mobile artefacts (GPS, sensors, etc)

• Huge number of different devices

• Big number of different approaches

Problems

Page 9: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Complexity of mobile UI testing

• Mobile artefacts (GPS, sensors, etc)

• Huge number of different devices

• Big number of different approaches

• Lack of official documentation

Problems

Page 10: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Complexity of mobile UI testing

• Mobile artefacts (GPS, sensors, etc)

• Huge number of different devices

• Big number of different approaches

• Lack of official documentation

• Official solution is friend of slow and flaky tests

Problems

Page 11: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Complexity of mobile UI testing

• Mobile artefacts (GPS, sensors, etc)

• Huge number of different devices

• Big number of different approaches

• Lack of official documentation

• Official solution is friend of slow and flaky tests

• …

Problems

Page 12: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

Solutions

Page 13: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Instrumentation Framework (by Google)

Solutions

Page 14: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Instrumentation Framework (by Google)

• Robotium (by Jayway)

Solutions

Page 15: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Instrumentation Framework (by Google)

• Robotium (by Jayway)

• UIAutomator (by Google)

Solutions

Page 16: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Instrumentation Framework (by Google)

• Robotium (by Jayway)

• UIAutomator (by Google)

• Robolectric (by ExtremeLabs)

Solutions

Page 17: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Instrumentation Framework (by Google)

• Robotium (by Jayway)

• UIAutomator (by Google)

• Robolectric (by ExtremeLabs)

• Espresso (by Google)

Solutions

Page 18: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Instrumentation Framework (by Google)

• Robotium (by Jayway)

• UIAutomator (by Google)

• Robolectric (by ExtremeLabs)

• Espresso (by Google)

• Double-Espresso (by Jake Wharton)

Solutions

Page 19: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Instrumentation Framework (by Google)

• Robotium (by Jayway)

• UIAutomator (by Google)

• Robolectric (by ExtremeLabs)

• Espresso (by Google)

• Double-Espresso (by Jake Wharton)

• … AssertJ-Android, Burst, Spoon …

Solutions

Page 20: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

Robolectric

Espresso

SV

Watch a movie — http://www.imdb.com/title/tt0892782/

Page 21: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

Double Espresso

Page 22: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Battery

• Location

• Mobile network

• Multitouch

• Sensors

• …

How test Android artefacts?

Page 23: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Dagger <- currently best one solution for DI @ Android

• Dagger 2 *

• RoboGuice

• Guice

• PicoContainer

• Spring

• …

Use Dependency Injection!

Component <<interface>> Service

ServiceImplAssembler

<<create>>

Watch Introduction to Dagger — http://youtu.be/tPs1e3dQ6FU

Page 24: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

Dependency Injection

Auto Testing

&

Page 25: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Simple app for registration to #MBLTDev

• RESTful communication with backend

• Location helper for city field

• Open Source code

• End-to-end auto tests

• Just demo app, fork it on GitHub

Meet Demo App

Page 26: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Form fields behaviour

• Behaviour of auto-locate button

• Transformation of form data to request

• End-to-end user scenarios: 1. Successful registration 2. Registration is closed error 3. Network error

• Test on different devices

What we can test?

Page 27: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

Setup Double Espresso

!androidTestCompile 'com.squareup.spoon:spoon-client:1.1-r3' { exclude group: 'com.squareup.dagger' }

! defaultConfig { testInstrumentationRunner "com.google.android.apps.common.testing" + ".testrunner.GoogleInstrumentationTestRunner" } !

build.gradle

Page 28: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

public class MBLTDevDemoApp extends Application { ! @Override public void onCreate() { super.onCreate(); setModules(getStartModules()); } ! public void inject(Object component) { this.objectGraph.inject(component); } ! public Object[] getModules() { return modules.toArray(new Object[modules.size()]); } ! public void plusModule(Object module) { this.modules.add(module); this.objectGraph = objectGraph.plus(module); } ! public void setModules(Object[] modules) { this.modules = new ArrayList<Object>(Arrays.asList(modules)); this.objectGraph = ObjectGraph.create(modules); } ! protected Object[] getStartModules() { return Modules.list(this); } }

Daggerized app

Page 29: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

Daggerize test apppublic class MBLTDevDemoTestApp extends MBLTDevDemoApp { @Override protected Object[] getStartModules() { return new Object[]{new MBLTDevDemoModule(this), new MBLTDevDemoTestModule()}; } }

@Module( injects = { GetTicketActivity.class, … } ) public class MBLTDevDemoTestModule { ! @Provides @Singleton public LocationService provideLocationService() { return new TestLocationService(); } ! @Provides @Singleton public TestLocationService provideLocationService( LocationService locationService) { return locationService; } ! … }

@Module( complete = false, library = true, overrides = true, injects = { DemoTests.class} ) public class MBLTDevDemoModule { ! @Provides @Singleton public LocationService provideLocationService( Context context) { return new RealLocationService(context); } ! … }

Page 30: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

Customize TestRunnerpackage com.medlert.android.transport.env; !… !public class MBLTDevDemoTestRunner extends GoogleInstrumentationTestRunner { ! @Override public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { return Instrumentation.newApplication(MBLTDevDemoTestApp.class, context); } !} !

defaultConfig { testInstrumentationRunner “com.mbltdev.lovelyandroid.env.testrunner” } !

build.gradle

Page 31: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

DI in super testpublic class MBLTDevDemoInstrumentationTestCase2<T extends Activity> extends ActivityInstrumentationTestCase2<T> { ! private Object[] modules; ! public MBLTDevDemoInstrumentationTestCase2(Class<T> activityClass) { super(activityClass); } ! @Override protected void setUp() throws Exception { super.setUp(); this.modules = getApp().getModules(); getApp().inject(this); } ! @Override protected void tearDown() throws Exception { getApp().setModules(modules); super.tearDown(); } ! protected MBLTDevDemoApp getApp() { return (MBLTDevDemoApp) (getInstrumentation().getTargetContext().getApplicationContext()); } }

Page 32: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

First cup of coffeepublic class InitialStateTests extends ActivityInstrumentationTestCase2<GetTicketActivity> { ! public FormFieldsTests() { super(GetTicketActivity.class); } ! @Override protected void setUp() throws Exception { super.setUp(); getActivity(); } ! @SmallTest public void testFormInitialState() throws Exception { onView(withId(R.id.first_name_field)).check(matches(isDisplayed())); onView(withId(R.id.last_name_field)).check(matches(isDisplayed())); onView(withId(R.id.city_field)).check(matches(isDisplayed())); onView(withId(R.id.company_field)).check(matches(isDisplayed())); onView(withId(R.id.position_field)).check(matches(isDisplayed())); onView(withId(R.id.get_ticket)).check(matches(isDisplayed())); } !}

Page 33: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

Coffee with Dependency Injectionpublic class BehaviourTests extends ActivityInstrumentationTestCase2<GetTicketActivity> { ! @Inject TestLocationService testLocationService; @Inject TestBackendService testBackendService; @Inject @TestOperationLengthMs testOperationLengthMs; … ! @SmallTest public void testAutoLocateButton() throws Exception { testLocationService.setLocation(TestLocations.moscow()); getActivity(); onView(withId(R.id.auto_locate)).perform(click()); Thread.sleep(testOperationLengthMs); onView(withId(R.id.field_city)).check(withText(“Moscow”)); } ! @SmallTest public void testFormNetworkRequest() throws Exception { Request chuckNorrisRequest = TestRequests.chuckNorris(); onFillForm(chuckNorrisRequest); onView(withId(R.id.get_ticket)).perform(click()); assertEquals(chuckNorrisRequest, testBackendService.getLastRequest()); } !}

Page 34: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

Cup with end-to-end user scenariospublic class EndToEndTests extends ActivityInstrumentationTestCase2<GetTicketActivity> { @Inject TestBackendService testBackendService; @Inject @TestOperationLengthMs testOperationLengthMs; … ! @SmallTest public void testSuccessfulRegistration() throws Exception { testBackendService.setGetTicketResponse(Response.success()); getActivity(); onFillForm(TestRequests.chuckNorris()); onView(withId(R.id.get_ticket)).perform(click()); Thread.sleep(testOperationLengthMs); onView(withText(“Congrats! You are registered!”)).check(isDisplayed()); } ! @SmallTest public void testClosedRegistration() throws Exception { testBackendService.setGetTicketResponse(Response.alreadyClosed()); getActivity(); onFillForm(TestRequests.chuckNorris()); onView(withId(R.id.get_ticket)).perform(click()); Thread.sleep(testOperationLengthMs); onView(withText(“Oops… Registration is already closed!”)).check(isDisplayed()); } !}

Page 35: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

Run Tests!

Page 36: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

• Spoon — https://github.com/square/spoon

• SauceLabs — https://saucelabs.com/

• TestObject — https://testobject.com/

• Appurify — http://appurify.com/

• Appthwack — http://appthwack.com/

• TestDroid — http://testdroid.com

• …

Testing on different real devices

Page 37: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

Conclusions• It’s good time to start testing of your apps

• Hope, you will love it

• Select Double Espresso or Robolectric

• Dependency Injection and Test Automation are big friends

• More things is coming

• Keep your hand on a pulse!

Page 38: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

Links 101• Espresso

https://code.google.com/p/android-test-kit/wiki/Espresso

• Double Espressohttps://github.com/JakeWharton/double-espresso

• Robolectric https://github.com/robolectric/robolectric

• Dagger https://github.com/square/dagger

• Demo Apphttps://github.com/AlexKorovyansky/mbltdev-demo

Page 39: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

Watch and talk• Introduction to Espresso

http://youtu.be/T7ugmCuNxDU

• Introduction to Dagger http://youtu.be/tPs1e3dQ6FU

• GTAC 2013http://bit.ly/gtac2013

• GTAC 2014http://bit.ly/gtac2013

• Make a talk in GDG RUhttp://bit.ly/gdgru_online_talk

Page 40: #MBLTdev: Автоматическое тестирование Android приложений c любовью (Mb-Lock)

Q&A Alex Korovyansky [email protected] http://about.me/korovyansk