Upload
beitconference
View
263
Download
1
Embed Size (px)
Citation preview
Unit and
Automation
Testing
on Android
Stanislav Gatsev
Android Team Lead,
Melon Inc.
Who am I?
Stanislav Gatsev
Android Team Lead
+359 89 891 4481
http://www.melon.bg
What is Android?
o World's most popular mobile
platform
o Every day another million users
power up their Android devices for
the first time
o Using Android SDK we can develop
software for almost everything from
smartphones and tablets to
glasses, watches, TVs and even
cars.
Why we automate testing?
o We save time !!!
o We improve our code quality
o We support live documentation
o We run our regression tests
o We fight fragmentation
Our Example Project
What Can We Test?
o We can test our logic, algorithms, calculations
o We can test our UI and navigation logic
o We can test IO operations, database and network operations
o And more...
@SmallTest
public void test_addOperatorInJava() throws Exception {
Assert.assertEquals(4, 2 + 2);
Assert.assertEquals(27, 25 + 2);
}
@SmallTest
public void test_FieldsAreVisible() {
ViewAsserts.assertOnScreen(mRootView, mEmailEditText);
ViewAsserts.assertOnScreen(mRootView, mPasswordEditText);
ViewAsserts.assertOnScreen(mRootView, mLoginActionLayout);
}
How we automate testing?
o We use JUnit
o We mock our objects
o We are using activity testing framework
o We click with Robotium
JUnit and Android We can use the JUnit TestCase class to do unit testing on a class that
doesn't call Android APIs. TestCase is also the base class for
AndroidTestCase, which we can use to test Android-dependent objects.
Besides providing the JUnit framework, AndroidTestCase offers
Android-specific setup, teardown, and helper methods.
public class UtilTests extends AndroidTestCase {
@SmallTest
public void test_StringToLatLngValidValues() throws Exception {
String latLngString = "34.009555,-118.497072";
LatLng latLng = Util.stringToLatLng(latLngString);
Assert.assertEquals(Double.compare(latLng.latitude, 34.009555), 0);
Assert.assertEquals(Double.compare(latLng.longitude, -118.497072), 0);
}
@SmallTest
public void test_StringToLatLngValidInvalues() throws Exception {
String latLngString = "34.009555,-a118.497072";
LatLng latLng = Util.stringToLatLng(latLngString);
Assert.assertEquals(Double.compare(latLng.latitude, 0), 0);
Assert.assertEquals(Double.compare(latLng.longitude, 0), 0);
}
}
Why we use Mocks?
The objective of unit testing is to exercise just one method at a time, but what
happens when that method depends on other things—hard-to-control things
such as the network, or a database.
The solution is the Mock object. It is simply a debug replacement for a real-
world object.
Mockito
Mockito is the way we mock objects in Android. As its developers say:
“Mockito is a mocking framework that tastes really good. It lets you write
beautiful tests with clean & simple API. Mockito doesn't give you hangover
because the tests are very readable and they produce clean verification
errors.”
• https://code.google.com/p/dexmaker/
• System property hack
Mockito and Android
//create Mock of server communication
final WeatherServerRequest weatherServerRequest =
Mockito.mock(WeatherServerRequest.class);
//stub the actual network call and return empty object
ServerResponse serverResponse = new ServerResponse();
Mockito.when(weatherServerRequest.getResponse()).thenReturn(serverResponse);
//create mock of the refresh-able and the observers subject
IRefreshable refreshable = Mockito.mock(IRefreshable.class);
ISubject subject = Mockito.mock(ISubject.class);
runWeatherWorkerThread(refreshable, subject, weatherServerRequest);
//verify if refresh-able start callback is called
Mockito.verify(refreshable).onStartRefresh();
//verify if the observers callback is called
Mockito.verify(subject).updateData(Mockito.anyMapOf(String.class,
ServerResponse.class));
//verify if refresh-able end callback is called
Mockito.verify(refreshable).onEndRefresh();
=+
Activity tests
ActivityInstrumentationTestCase2
This is the class which helps us test our Activities. It has direct reference to the
tested activity and you have the ability to run whole test or just parts of it in the
UI Thread.
@SmallTest
public void test_viewPagerHasAllLocations() throws Throwable {
//Creates the data fetcher mock and injects it to the Activity for every test
createDataFetcherMock();
runTestOnUiThread(new Runnable() {
@Override
public void run() {
//reinitialize activity with new data fetcher
getActivity().init();
}
});
//asserts if the view pager has the same number of items the data fetcher returned
Assert.assertEquals(3, mViewPager.getAdapter().getCount());
}
Robotium
o It is a lot easier to write our automation tests
o Helpful API for executing user actions
o Flexible results assertion
o Hybrid apps are supported
o We can use it in our Activity tests
Robotium in action
@LargeTest
public void test_addNewLocation() throws Throwable {
getInstrumentation().waitForIdleSync();
moveMapToPosition();
getInstrumentation().waitForIdleSync();
//gets the root view of the Activity
View rootView = getActivity().findViewById(android.R.id.content);
//long click in the center of the screen
mSolo.clickLongOnScreen(rootView.getWidth()/2, rootView.getHeight()/2);
getInstrumentation().waitForIdleSync();
//get first weather location
WeatherDataFetcher dataFetcher = getActivity().getDataFetcher();
List<WeatherLocation> weatherLocations = dataFetcher.getLocationsList();
Assert.assertEquals(1, weatherLocations.size());
//check if the location is the right one
WeatherLocation weatherLocation = weatherLocations.get(0);
Assert.assertEquals("Santa Monica, CA", weatherLocation.getLocationName());
//clears DB
dataFetcher.removeLocation(0);
}
Thank you!
Questions?
References
o https://developer.android.com
o https://code.google.com/p/robotium/
o https://github.com/mockito/mockito
o http://blog.gfader.com/2010/10/why-are-automated-tests-so-important.html
o http://media.pragprog.com/titles/utj/mockobjects.pdf
o http://www.embedded.com/design/prototyping-and-
development/4398723/The-mock-object-approach-to-test-driven-
development