Agenda:

-Intro
-Android Testing
-Creating a project
-JUnit Testing
-Mock Objects + UI Testing
-Integration and acceptance test
-Performance and system testing
-Advance assertions
-TDD
-Real App Dev
!
Agenda:

-Tools
-Continuous Integration
!
Ego slide

Mobile Developer @ Sixt
M. Sc. UCM/RWTH
CS Teacher at Alcalá University
!
!
!

+EnriqueLópezMañas
@eenriquelopez
Ego slide

Mobile Developer @ Sixt
M.Sc. Politehnica Timisoara
!
!
!

+ami.antoch
Keywords

Continuous Integration
TDD
JUnit / Unit Testing
Instrumentation
Behavior Driven Development
Performance Testing
Profiling
What you need

• Java SE Version 1.6
• Android SDK Tools
• Eclipse IDE for Java Developers
• ADT
• (Android Bundle)
Testing

• Develop
• Finding
• Correcting
Is about productivity!

$59.5 billion annually
!

1/3 could be saved
!

(National Institute of Standards and
Technology (USA))
Why, what, how, when

During, before
!

Continuous Integration
!

Classes, methods, lines, basic
blocks..
Activity lifecycle
Activity lifecycle
Databases and filesystem operations
Activity lifecycle
Databases and filesystem operations
Physical characteristics of the device
Activity lifecycle
Databases and filesystem operations
Physical characteristics of the device
(AVD and Genymotion)
UnitTests

Written by programmers for programmers
JUnit
Elements of a test

The fixture
Method setUp()
Method tearDown()
Test preconditions (retrospection vs. annotations)
Assertions

• assertEquals()
• assertFalse()
• assertNotNull()
• assertNotSame()
• assertNull()
• assertSame()
• assertTrue()
• fail()
Mock objects

Mimic objects
• MockApplication
• MockContentProvider
• MockContentResolver
• MockContext
• MockCursor
• MockDialogInterface
• MockPackageManager
• MockResources
UI Tests

Annotation @UIThreadTest
Class TouchUtils
• Click
• Drag
• LongClick
• Scroll
• Tap
• Touch
Environments

Eclipse…

…but also IntelliJ!
…and Netbeans!
Instrumentation

Foundation
Control application under test and permit
injection
Project Test

MyProject
MyProjectTest
Testing Target

Device
AVD Machines
GenyMotion
Summary
Android Testing

Best practice: test should live in a separate
correlated project
• Stripped (not included in main)
• Easier to run in Emulator
• Takes less time
• Encourages code reusability
Create project
AVD
Genymotion
DDMS
TestAnnotations

@SmallTest
@MediumTest
@LargeTest
@Smoke
@FlakyTest (tolerance=4)
@UIThreadTest
@Suppress
Running Test

From Eclipse
Running Single Test
Running from the emulator
Running from the command line
Running from the command line
• All
• From an specific test case
• Specific test by name
• By category
• (create custom annotations)
Debug bugs
Summary

• Created first Android project
• Followed best practice creating companion project
• Simple test class
• Eclipse
• Command line options
Mockup

• All Mock implementations
• All methods non functional
• Throw UnsupportedOperationExceiption
UI Testing

• Android SDK Tools, 21+
• API 16+
Tools
• uiaumatorviewer
• uiautomator
Integration tests

Individual components work jointly
Integration tests

Individual components work jointly

Acceptance tests

QA, Business language
Performance tests

Performance behavior

System test

• GUI Test
• Smoke Tests
• Performance
• Installation
Benchmarking

• Traditional logging statement methods
• Creating Android performance tests
• Using profiling tools
• Microbenchmarks using Caliper
Benchmarking

/* (non-Javadoc)
* @see android.text.TextWatcher#onTextChanged(
* java.lang.CharSequence, int, int, int)
*/
public void onTextChanged(CharSequence s, int start,
int before, int count) {
if (!mDest.hasWindowFocus() || mDest.hasFocus() ||
s == null ) {
return; }
final String str = s.toString();
if ( "".equals(str) ) {
mDest.setText("");
return;
}
final long t0;
if ( BENCHMARK_TEMPERATURE_CONVERSION ) {
t0 = System.currentTimeMillis();
}

!
Benchmarking


try {
final double temp = Double.parseDouble(str);
final double result = (mOp == OP.C2F) ?

TemperatureConverter.celsiusToFarenheit(temp);
TemperatureConverter.fahrenheitToCelsius(temp);
final String resultString = String.format("%.2f", result);
mDest.setNumber(result);
mDest.setSelection(resultString.length());
} catch (NumberFormatException e) {
// WARNING
// this is generated while a number is entered,
// for example just a '-'
// so we don't want to show the error
} catch (Exception e) {
mSource.setError("ERROR: " + e.getLocalizedMessage());
}
if ( BENCHMARK_TEMPERATURE_CONVERSION ) {
long t = System.currentTimeMillis() - t0;
Log.i(TAG, "TemperatureConversion took " + t +
" ms to complete.");
}
}
Android performance tests

Classes hidden only for System
apps :(
Assertions in depth

• assertEquals
• assertFalse
• assertNotNull
• assertNotSame
• assertNull
• assertSame
• assertTrue
• assertFail
Assertions in depth

public void testNotImplementedYet() {
fail("Not implemented yet");
}
Assertions in depth

}

public void testShouldThrowException() {
try {
MyFirstProjectActivity.methodThatShouldThrowException();
fail("Exception was not thrown");
} catch ( Exception ex ) {
// do nothing
}
Custom messages

public void testMax() {

final int a = 1;

final int b = 2;

final int expected = b;

final int actual = Math.max(a, b);

assertEquals("Expection " + expected + " but was " + actual,
expected, actual);
}
Static imports

public void testAlignment() {
final int margin = 0;
...
android.test.ViewAsserts.assertRightAligned(
mMessage, mCapitalize, margin);

!

}
Static imports

import static android.test.ViewAsserts.assertRightAligned;
public void testAlignment() {

final int margin = 0;

assertRightAligned(mMessage, mCapitalize, margin);
}
View assertions

assertBaselineAligned
View assertions

assertBaselineAligned

assertBotomAligned
View assertions

assertBaselineAligned

assertBotomAligned
assertGroupContains
View assertions

assertBaselineAligned

assertBotomAligned
assertGroupContains
assertGroupIntegrity
View assertions

assertBaselineAligned

assertBotomAligned
assertGroupContains
assertGroupIntegrity
assertGroupNotContains
View assertions

assertBaselineAligned

assertBotomAligned
assertGroupContains
assertGroupIntegrity
assertGroupNotContains
assertHasScreenCoordinates
View assertions

assertBaselineAligned

assertBotomAligned
assertGroupContains
assertGroupIntegrity
assertGroupNotContains
assertHasScreenCoordinates
assertHorizontalCenterAligned
View assertions

assertLeftAligned
View assertions

assertLeftAligned
assertOffScreenAbove
View assertions

assertLeftAligned
assertOffScreenAbove
assertOffScreenBelow
View assertions

assertLeftAligned
assertOffScreenAbove
assertOffScreenBelow
assertOnScreen
View assertions

assertLeftAligned
assertOffScreenAbove
assertOffScreenBelow
assertOnScreen
assertRightAligned
View assertions

assertLeftAligned
assertOffScreenAbove
assertOffScreenBelow
assertOnScreen
assertRightAligned
assertTopAligned
View assertions

assertLeftAligned
assertOffScreenAbove
assertOffScreenBelow
assertOnScreen
assertRightAligned
assertTopAligned
assertVerticalCenterAligned
Example

public void testUserInterfaceLayout() {

final int margin = 0;

final View origin = mActivity.getWindow().getDecorView(); 
assertOnScreen(origin, mMessage); 
assertOnScreen(origin, mCapitalize);
assertRightAligned(mMessage, mCapitalize, margin);
}
Even more 

assertions

assertAssignableFrom
Even more 

assertions

assertAssignableFrom
assertContainsRegex
Even more 

assertions

assertAssignableFrom
assertContainsRegex
assertContainsInAnyOrder
Even more 

assertions

assertAssignableFrom
assertContainsRegex
assertContainsInAnyOrder
assertContainsInOrder
Even more 

assertions

assertAssignableFrom
assertContainsRegex
assertContainsInAnyOrder
assertContainsInOrder
assertEmpty
Even more 

assertions

assertAssignableFrom
assertContainsRegex
assertContainsInAnyOrder
assertContainsInOrder
assertEmpty
assertEquals
Even more 

assertions

assertMatchesRegex
Even more 

assertions

assertMatchesRegex
assertNotContainsRegex
Even more 

assertions

assertMatchesRegex
assertNotContainsRegex
assertNotEmpty
Even more 

assertions

assertMatchesRegex
assertNotContainsRegex
assertNotEmpty
assertNotMatchesRegex
Even more 

assertions

assertMatchesRegex
assertNotContainsRegex
assertNotEmpty
assertNotMatchesRegex
checkEqualsAndHashCodeMethods
Example
@UiThreadTest
public void testNoErrorInCapitalization() {
final String msg = "this is a sample";
mMessage.setText(msg);
mCapitalize.performClick();
final String actual = mMessage.getText().toString(); 
final String notExpectedRegexp = “(?i:ERROR)";
assertNotContainsRegex("Capitalization found error:",
notExpectedRegexp, actual);
}
assertActivityRequiresPermission














public void testActivityPermission() {
final String PKG = "com.example.aatg.myfirstproject";
final String ACTIVITY = PKG + ".MyFirstProjectActivity";
final String PERMISSION = android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
assertActivityRequiresPermission(PKG, ACTIVITY, PERMISSION);
}
assertReadingContentUriRequiresPermission

}

public void testReadingContacts() {
final Uri URI = ContactsContract.AUTHORITY_URI;
final String PERMISSION =
android.Manifest.permission.READ_CONTACTS;
assertReadingContentUriRequiresPermission(URI, PERMISSION);
assertWritingContentUriRequiresPermission

public void testWritingContacts() {
final Uri URI = ContactsContract.AUTHORITY_URI;
final String PERMISSION =
android.Manifest.permission.WRITE_CONTACTS;
assertWritingContentUriRequiresPermission(URI, PERMISSION);
}
ActivityMonitor

}

public void testFollowLink() {
final Instrumentation inst = getInstrumentation();
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_VIEW);
intentFilter.addDataScheme("http");
intentFilter.addCategory(Intent.CATEGORY_BROWSABLE);
ActivityMonitor monitor = inst.addMonitor(intentFilter, null, false); 
assertEquals(0, monitor.getHits()); 
TouchUtils.clickView(this, mLink); 
monitor.waitForActivityWithTimeout(5000); 
assertEquals(1, monitor.getHits()); 
inst.removeMonitor(monitor);
Example project
Summary

Used several types of assertion
Explained mock objects
Exemplified different tests
Test Driven Development
Test Driven Development
Test Driven Development

• Difficult to divert code
• Focus

NO SILVER BULLET
Example project - temperature converter
Requirements:

• Application convert from Celsius to F.
• … and viceversa
• Two fields to input data
• When temperature is entered, other field updates
• Error displayed
• Some space reserved keyboard
• Entry fields start empty
• Digits right aligned
• Last entered values retained after onPause()
Concept design
Create projects
From requirement to tests
AVD and Emulator Options
Headless emulator
emulator -avd test -no-window -no-audio -no-boot-anim -port 5580 &
Monkeyrunner
Building with ant

android update project —path .
Jenkins
Testing recipes
Thank you !

+ Enrique López Mañas
@eenriquelopez

Android Building, Testing and reversing