Date post: | 09-May-2015 |
Category: |
Technology |
Upload: | enrique-lopez-manas |
View: | 819 times |
Download: | 4 times |
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, whenDuring, 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+
• uiaumatorviewer • uiautomator
Tools
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 importsimport static android.test.ViewAsserts.assertRightAligned; public void testAlignment() { final int margin = 0; assertRightAligned(mMessage, mCapitalize, margin); }
View assertions assertBaselineAligned
View assertions assertBaselineAlignedassertBotomAligned
View assertions assertBaselineAlignedassertBotomAligned assertGroupContains
View assertions assertBaselineAlignedassertBotomAligned assertGroupContains assertGroupIntegrity
View assertions assertBaselineAlignedassertBotomAligned assertGroupContains assertGroupIntegrity assertGroupNotContains
View assertions assertBaselineAlignedassertBotomAligned assertGroupContains assertGroupIntegrity assertGroupNotContains assertHasScreenCoordinates
View assertions assertBaselineAlignedassertBotomAligned 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
Examplepublic 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
SummaryUsed 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