androidautomatedtestingtopicalguidelines v0.0.4

29
Android Automated Testing – Topical Guidelines Document Version 0.0.2 This document is intended to explain in a more detailed manner the aspects outlined during the presentation. 1

Upload: vldandreea

Post on 11-May-2017

213 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: AndroidAutomatedTestingTopicalGuidelines v0.0.4

Android Automated Testing – Topical Guidelines

Document Version 0.0.2

This document is intended to explain in a more detailed manner the aspects outlined during the presentation.

1

Page 2: AndroidAutomatedTestingTopicalGuidelines v0.0.4

Android Automated Testing – Topical Guidelines

___________________________________Contents

1. Introduction to Android. Environment Setup and Configuration .................................................. 3

App Components ................................................................................................................................. 4

Activities ................................................................................................................................................ 4

Services ................................................................................................................................................ 4

Content providers ................................................................................................................................ 4

Broadcast receivers ............................................................................................................................ 5

Environment Setup and Configuration ............................................................................................. 5

2. Building your first Application ............................................................................................................ 7

Android Projects .................................................................................................................................. 8

3. Introduction to Automated Testing . Android Testing Fundamentals .......................................... 12

Test Projects ....................................................................................................................................... 13

JUnit ................................................................................................................................................ 14

Instrumentation .............................................................................................................................. 14

Test case classes .......................................................................................................................... 15

Running Tests .................................................................................................................................... 17

Seeing Test Results .......................................................................................................................... 18

Monkey and monkeyrunner ............................................................................................................. 18

Working with Package names ......................................................................................................... 18

W hat to Test ....................................................................................................................................... 19

Testing from Eclipse with ADT ............................................................................................................... 19

Creating a Test Project ..................................................................................................................... 19

Creating a Test Package .................................................................................................................. 20

4. Android Activity Testin g .................................................................................................................... 22

5. Android Service Testing ................................................................................................................... 27

2

Page 3: AndroidAutomatedTestingTopicalGuidelines v0.0.4

1. Introduction to Android. Environment Setup and Configuration

___________________________________Android is an operating system based on the Linux Kernel and designed primarily for touchscreen mobile devices such as smart phones and tablets. Android was unveiled in 2007 along with the founding of the Open Handset Alliance: a consortium of hardware, software, and telecommunication companies devoted to advancing open standards for mobile devices.

The user interface of Android is based on direct manipulation, using touch inputs that loosely correspond to real-world actions, like swiping, tapping, pinching and reverse pinching to manipulate on-screen objects. Internal hardware such as accelerometers, gyroscopes and proximity sensors are used by some applications to respond to additional user actions, for example adjusting the screen from portrait to landscape depending on how the device is oriented.

Android is open source and Google releases the source code under the Apache License.

Android apps are written in the Java

programming language. The Android SDK tools compile your code—along with any data and resource files—into an APK: an Android package, which is an archive file with an “.apk” suffix. One APK file contains all the contents of an Android app and is the file that Android-powered devices use to install the app.

App Components

App components are the essential building blocks of an Android app. Each component is a different point

3

Page 4: AndroidAutomatedTestingTopicalGuidelines v0.0.4

through which the system can enter your app. Not all components are actual entry points for the user and some depend on each other, but each one exists as its own entity and plays a specific role—each one is a unique building block that helps define your app's overall behavior.

There are four different types of app components. Each type serves a distinct purpose and has a distinct life cycle that defines how the component is created and destroyed.

Here are the four types of app components:

Activities

An activity represents a single screen with a user interface. For example, an email app might have one activity that shows a list of new emails, another activity to compose an email, and another activity for reading emails. Although the activities work together to form a cohesive user experience in the email app, each one is independent of the others. As such, a different app can start any one of these activities (if the email app allows it). For example, a camera app can start the activity in the email app that composes new mail, in order for the user to share a picture.

An activity is implemented as a subclass of Activity and you can learn more about it in the Activities developer guide.

Services

A service is a component that runs in the background to perform long-running operations or to perform work for remote processes. A service does not provide a user interface. For example, a service might play music in the background while the user is in a different app, or it might fetch data over the network without blocking user interaction with an activity. Another component, such as an activity, can start the service and let it run or bind to it in order to interact with it.

A service is implemented as a subclass of Service and you can learn more about it in the Services developer guide.

Content providers

A content provider manages a shared set of app data. You can store the data in the file system, a SQLite database, on the web, or any other persistent storage location your app can access. Through the content provider, other apps can query or even modify the data (if the content provider allows it). For example, the Android system provides a content provider that manages the user's contact information. As such, any app with the proper permissions can query part of the content provider (such as ContactsContract.Data) to read and write information about a particular person.

Content providers are also useful for reading and writing data that is private to your app and not shared. For example, the Note Pad sample app uses a content provider to save notes.

A content provider is implemented as a subclass of ContentProvider and must implement a standard set of APIs that enable other apps to perform transactions. For more information, see the Content Providers developer guide.

Broadcast receivers

A broadcast receiver is a component that responds to system-wide broadcast announcements. Many broadcasts originate from the system—for example, a broadcast announcing that the screen has turned off, the battery is low, or a picture was captured. Apps can also initiate broadcasts—for example, to let other apps know that some data has been downloaded to the device and is available for them to use. Although

4

Page 5: AndroidAutomatedTestingTopicalGuidelines v0.0.4

broadcast receivers don't display a user interface, they may create a status bar notification to alert the user when a broadcast event occurs. More commonly, though, a broadcast receiver is just a "gateway" to other components and is intended to do a very minimal amount of work. For instance, it might initiate a service to perform some work based on the event.

A broadcast receiver is implemented as a subclass of BroadcastReceiver and each broadcast is delivered as an Intent object. For more information, see the BroadcastReceiver class.

Before the Android system can start an app component, the system must know that the component exists by reading the app's AndroidManifest.xml file (the "manifest" file). Your app must declare all its components in this file, which must be at the root of the app project directory.

The manifest does a number of things in addition to declaring the app's components, such as:

• Identify any user permissions the app requires, such as Internet access or read-access to the user's contacts.

• Declare the minimum API Level required by the app, based on which APIs the app uses.• Declare hardware and software features used or required by the app, such as a camera, Bluetooth

services, or a multitouch screen.• API libraries the app needs to be linked against (other than the Android framework APIs), such as the

Google Maps library.• And more

Environment Setup and ConfigurationThe Android Developer Tools (ADT) plugin for Eclipse provides a professional-grade development environment for building Android apps. It's a full Java IDE with advanced features to help you build, test, debug, and package your Android apps.The ADT Bundle provides everything you need to start developing apps, including a version of the Eclipse IDE with built-in ADT (Android Developer Tools) to streamline your Android app development.

Installing the Eclipse PluginAndroid offers a custom plugin for the Eclipse IDE, called Android Development Tools (ADT). This plugin provides a powerful, integrates environment in which to develop Android apps. It extends the capabilities of Eclipse to let you quickly set up new Android projects, build app UI, debug your app, and export signed (or unsigned) app packages (APK) for distribution.To install Eclipse please see the following link : http://www.eclipse.org/downloads/

Download the ADT Plugin

1. Start Eclipse, then select Help → Install New Software.2. Click Add, in the top-right corner.3. In the Add Repository dialog that appears, enter “ADT Plugin” for the Name and the following URL for the Location: https://dl-ssl.google.com/android/eclipse/4. Click OK. If you have trouble acquiring the plugin, try using “http” in the Location URL, instead of “https” (https is preferred for security reasons).5. In the Available Software dialog, select the checkbox next to Developer Tools and click Next.6. In the next window, you'll see a list of tools to be downloaded. Click Next.7. Read and accept the license agreement then click Finish. If you get a security warning saying that the authenticity or validity of the software can't be established, click

5

Page 6: AndroidAutomatedTestingTopicalGuidelines v0.0.4

OK.8. When the installation is complete, restart Eclipse.

Configure the ADT Plugin

Once Eclipse restarts, you must specify the location of your Android SDK directory.1. In the “Welcome to Android Development” window that appears, select Use existing SDKs.2. Browse and select the location of the Android SDK directory you recently downloaded and unpacked.3. Click Next

Adding Platforms and Packages

The Android SDK separates tools, platforms, and other components into packages you can download using the Android SDK Manager. The original SDK package you've downloaded includes only the SDK Tools. To develop an Android app, you also need to download at least one Android platform and the latest SDK Platform-tools.1. Launch the SDK Manager: If you've used the Windows installer to install the SDK tools, you should already have the Android SDK Manager open. Otherwise, you can launch the Android SDK Manager in one of the following ways:

• On Windows, double-click the SDK Manager.exe file at the root of the Android SDK directory.

• On Mac or Linux, open a terminal and navigate to the tools/ directory in the Android SDK, then

execute android sdk.2. The SDK Manager shows all the SDK packages available for you to add to your Android SDK. As a minimum configuration for your SDK, we recommend you install the following:

• The latest Tools packages (check the Tools folder).

• The latest version of Android (check the first Android folder).

• The Android Support Library (open the Extras folder and check Android Support Library).

Once you've chosen your packages, click Install. The Android SDK Manager installs the selected packages into your Android SDK environment.

For more information about Installing and configuring you IDE please visit: http://developer.android.com/sdk/installing/installing-adt.html#Download

2. Building your first Application

In order to create a new Android Project we must go to File->New->Android Application Project.

6

Page 7: AndroidAutomatedTestingTopicalGuidelines v0.0.4

The next step is to choose a name for your first Activity and its

corresponding layout.

Android ProjectsAndroid projects are the projects that eventually get built into an .apk file that you install onto a device. They contain things such as application source code and resource files. Some are generated for you by default, while others should be created if required. The following directories and files comprise an Android project:

src/Contains your stub Activity file, which is stored at src/your/package/namespace/ActivityName.java. All other source code files (such as .java or .aidl files) go here as well.

bin/Output directory of the build. This is where you can find the final .apk file and other compiled resources.

jni/Contains native code sources developed using the Android NDK. For more information, see the Android NDK documentation.

gen/Contains the Java files generated by ADT, such as your R.java file and interfaces created from AIDL files.

7

Page 8: AndroidAutomatedTestingTopicalGuidelines v0.0.4

assets/This is empty. You can use it to store raw asset files. Files that you save here are compiled into an .apk file as-is, and the original filename is preserved. You can navigate this directory in the same way as a typical file system using URIs and read files as a stream of bytes using the AssetManager. For example, this is a good location for textures and game data.

res/Contains application resources, such as drawable files, layout files, and string values. See Application Resources for more information.anim/

For XML files that are compiled into animation objects. See the Animation resource type.color/

For XML files that describe colors. See the Color Values resource type.drawable/

For bitmap files (PNG, JPEG, or GIF), 9-Patch image files, and XML files that describe Drawable shapes or Drawable objects that contain multiple states (normal, pressed, or focused). See the Drawable resource type.

layout/XML files that are compiled into screen layouts (or part of a screen). See the Layout resource type.

menu/For XML files that define application menus. See the Menus resource type.

raw/For arbitrary raw asset files. Saving asset files here instead of in the assets/ directory only differs in the way that you access them. These files are processed by aapt and must be referenced from the application using a resource identifier in the R class. For example, this is a good place for media, such as MP3 or Ogg files.

values/For XML files that are compiled into many kinds of resource. Unlike other resources in the res/ directory, resources written to XML files in this folder are not referenced by the file name. Instead, the XML element type controls how the resources is defined within them are placed into the R class.

xml/For miscellaneous XML files that configure application components. For example, an XML file that defines a PreferenceScreen, AppWidgetProviderInfo, or Searchability Metadata. See Application Resources for more information about configuring these application components.

libs/Contains private libraries.

AndroidManifest.xmlThe control file that describes the nature of the application and each of its components. For instance, it describes: certain qualities about the activities, services, intent receivers, and content providers; what permissions are requested; what external libraries are needed; what device features are required, what API Levels are supported or required; and others. See the AndroidManifest.xml documentation for more information

project.propertiesThis file contains project settings, such as the build target. This file is integral to the project, so maintain it in a source revision control system. To edit project properties in Eclipse, right-click the project folder and select Properties.

local.propertiesCustomizable computer-specific properties for the build system. If you use Ant to build the project, this contains the path to the SDK installation. Because the content of the file is specific to the local installation of the SDK, the local.properties should not be maintained in a source revision control system. If you use Eclipse, this file is not used.

ant.propertiesCustomizable properties for the build system. You can edit this file to override default build settings used by Ant and also provide the location of your keystore and key alias so that the build tools can

8

Page 9: AndroidAutomatedTestingTopicalGuidelines v0.0.4

sign your application when building in release mode. This file is integral to the project, so maintain it in a source revision control system. If you use Eclipse, this file is not used.

build.xmlThe Ant build file for your project. This is only applicable for projects that you build with Ant.

App ResourcesYou should always externalize resources such as images and strings from your application code, so that you can maintain them independently. Externalizing your resources also allows you to provide alternative resources that support specific device configurations such as different languages or screen sizes, which becomes increasingly important as more Android-powered devices become available with different configurations. In order to provide

compatibility with different configurations, you must organize resources in your project's res/ directory, using various sub-directories that group resources by type and configuration.

For any type of resource, you can specify default and multiple alternative resources for your application:• Default resources are those that should be used regardless of the device configuration or when there are

no alternative resources that match the current configuration.• Alternative resources are those that you've designed for use with a specific configuration. To specify that

a group of resources are for a specific configuration, append an appropriate configuration qualifier to the directory name.

Android ManifestIt is an important part of an Android project as it is the first place where an application searches for information about the way it should run. In AndroidManifest.xml we have listed the package name, names of all activities, intents and also permissions (for example, in order to use the device’s camera or to access the internet, we must declare a specific permission within this file). Also, in this file it is mentioned the minimum Android API needed for running the application.

<?xml version=”1.0” encoding=”utf-8”?><manifest xmlns:android=”http://schemas.android.com/apk/res/android” package=”com.rinf.mobile.rotemps” android:versionCode=”1” android:versionName=”1.0” >

<uses-sdk android:minSdkVersion=”8” android:targetSdkVersion=”18” />

<application android:allowBackup=”true” android:icon=”@drawable/ic_launcher” android:label=”@string/app_name” android:theme=”@style/AppTheme” > <activity android:name=”com.rinf.mobile.rotemps.MainActivity” android:label=”@string/app_name” > <intent-filter> <action android:name=”android.intent.action.MAIN” />

<category android:name=”android.intent.category.LAUNCHER” /> </intent-filter> </activity> </application>

9

Page 10: AndroidAutomatedTestingTopicalGuidelines v0.0.4

</manifest><?xml version=”1.0” encoding=”utf-8”?><manifest xmlns:android=”http://schemas.android.com/apk/res/android” package=”com.rinf.mobile.rotemps” android:versionCode=”1” android:versionName=”1.0” >

<uses-sdk android:minSdkVersion=”8” android:targetSdkVersion=”18” />

<application android:allowBackup=”true” android:icon=”@drawable/ic_launcher” android:label=”@string/app_name” android:theme=”@style/AppTheme” > <activity android:name=”com.rinf.mobile.rotemps.MainActivity” android:label=”@string/app_name” > <intent-filter> <action android:name=”android.intent.action.MAIN” />

<category android:name=”android.intent.category.LAUNCHER” /> </intent-filter> </activity> </application></manifest>

The Layout

We can look at our layout file (activity_first_page.xml) from two perspectives: as Graphical Layout (here we can

actually see all the buttons, edit texts, and other graphical objects), or we can see the actual code behind each

element (next to Graphical Layout tab we have activity 1Y_first_page.xml tab). Here we can define the position of

the elements, their dimensions, their background and also their labels (e.g.: the text displayed on a button).

10

Page 11: AndroidAutomatedTestingTopicalGuidelines v0.0.4

3. Introduction to Automated Testing. Android Testing Fundamentals

___________________________________

Unit Testing

A unit test is a piece of code written by a developer that executes a specific functionality in the code which is tested. The percentage of code which is tested by unit tests is typically called test coverage.

A unit test targets a small unit of code, e.g. a method or a class, (local tests).Unit tests ensure that code works as intended. They are also very helpful to ensure that the code still works as intended in case you need to modify code for fixing a bug or extending functionality. Having a high test coverage of your code allows you to continue developing features without having to perform lots of manual tests.

Android testing

The test follows the flow depicted in the following diagram:

11

Page 12: AndroidAutomatedTestingTopicalGuidelines v0.0.4

Test Structure

Android's build and test tools assume that test projects are organized into a standard structure of tests, test case classes, test packages, and test projects.

Android testing is based on JUnit. In general, a JUnit test is a method whose statements test a part of the application under test. You organize test methods into classes called test cases (or test suites). Each test is an isolated test of an individual module in the application under test. Each class is a container for related test methods, although it often provides helper methods as well.

In JUnit, you build one or more test source files into a class file. Similarly, in Android you use the SDK's build tools to build one or more test source files into class files in an Android test package. In JUnit, you use a test runner to execute test classes. In Android, you use test tools to load the test package and the application under test, and the tools then execute an Android-specific test runner.

Test Projects

Tests, like Android applications, are organized into projects.

A test project is a directory or Eclipse project in which you create the source code, manifest file, and other files for a test package. The Android SDK contains tools for Eclipse with ADT and for the command line that create and update test projects for you. The tools create the directories you use for source code and resources and the manifest file for the test package. The command-line tools also create the Ant build files you need.

You should always use Android tools to create a test project. Among other benefits, the tools:

• Automatically set up your test package to use InstrumentationTestRunner as the test case runner. You must use InstrumentationTestRunner (or a subclass) to run JUnit tests.

• Create an appropriate name for the test package. If the application under test has a package name of com.mydomain.myapp, then the Android tools set the test package name to com.mydomain.myapp.test. This helps you identify their relationship, while preventing conflicts within the system.

• Automatically create the proper build files, manifest file, and directory structure for the test project. This helps you to build the test package without having to modify build files and sets up the linkage between your test package and the application under test.

You can create a test project anywhere in your file system, but the best approach is to add the test project so that its root directory tests/ is at the same level as the src/ directory of the main application's project. This helps you find the tests associated with an application. For example, if your application projec t's root directory is MyProject, then you should use the following directory structure:

MyProject/

AndroidManifest.xml

res/

... (resources for main application)

src/

... (source code for main application) ...

tests/

AndroidManifest.xml

res/

... (resources for tests)

src/

... (source code for tests)

12

Page 13: AndroidAutomatedTestingTopicalGuidelines v0.0.4

The Testing API

The Android testing API is based on the JUnit API and extended with an instrumentation framework and Android-specific testing classes.

JUnit

You 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 you can use to test Android-dependent objects. Besides providing the JUnit framework, AndroidTestCase offers Android-specific setup, teardown, and helper methods.

You use the JUnit Assert class to display test results. The assert methods compare values you expect from a test to the actual results and throw an exception if the comparison fails. Android also provides a class of assertions that extend the possible types of comparisons, and another class of assertions for testing the UI. These are described in more detail in the section Assertion classes

To learn more about JUnit, you can read the documentation on the junit.org home page. Note that the Android testing API supports JUnit 3 code style, but not JUnit 4. Also, you must use Android's instrumented test runner InstrumentationTestRunner to run your test case classes. This test runner is described in the section Running Tests.

Instrumentation

Android instrumentation is a set of control methods or "hooks" in the Android system. These hooks control an Android component independently of its normal lifecycle. They also control how Android loads applications.

Normally, an Android component runs in a lifecycle determined by the system. For example, an Activity object's lifecycle starts when the Activity is activated by an Intent. The object's onCreate() method is called, followed by onResume(). When the user starts another application, the onPause() method is called. If the Activity code calls the finish() method, the onDestroy() method is called. The Android framework API does not provide a way for your code to invoke these callback methods directly, but you can do so using instrumentation.

Also, the system runs all the components of an application into the same process. You can allow some components, such as content providers, to run in a separate process, but you can't force an application to run in the same process as another application that is already running.

With Android instrumentation, though, you can invoke callback methods in your test code. This allows you to run through the lifecycle of a component step by step, as if you were debugging the component. The following test code snippet demonstrates how to use this to test that an Activity saves and restores its state:

// Start the main activity of the application under test

mActivity = getActivity();

// Get a handle to the Activity object's main UI widget, a Spinner

mSpinner=(Spinner)mActivity.findViewById(com.android.example.spinner.R.id.Spinner01);

// Set the Spinner to a known position

mActivity.setSpinnerPosition(TEST_STATE_DESTROY_POSITION);

// Stop the activity - The onDestroy() method should save the state of the Spinner

13

Page 14: AndroidAutomatedTestingTopicalGuidelines v0.0.4

mActivity.finish();

// Re-start the Activity - the onResume() method should restore the state of the Spinner

mActivity = getActivity();

// Get the Spinner's current position

int currentPosition = mActivity.getSpinnerPosition();

// Assert that the current position is the same as the starting position

assertEquals(TEST_STATE_DESTROY_POSITION, currentPosition);

The key method used here is getActivity(), which is a part of the instrumentation API. The Activity under test is not started until you call this method. You can set up the test fixture in advance, and then call this method to start the Activity.

Also, instrumentation can load both a test package and the application under test into the same process. Since the application components and their tests are in the same process, the tests can invoke methods in the components, and modify and examine fields in the components.

Test case classesAndroid provides several test case classes that extend TestCase and Assert with Android-specific setup, teardown, and helper methods.

AndroidTestCase

A useful general test case class, especially if you are just starting out with Android testing, is AndroidTestCase. It extends both TestCase and Assert. It provides the JUnit-standard setUp() and tearDown() methods, as well as all of JUnit's Assert methods. In addition, it provides methods for testing permissions, and a method that guards against memory leaks by clearing out certain class references.

Component-specific test cases

A key feature of the Android testing framework is its component-specific test case classes. These address specific component testing needs with methods for fixture setup and teardown and component lifecycle control. They also provide methods for setting up mock objects. These classes are described in the component-specific testing topics:

• Activity Testing • Content Provider Testing • Service Testing

Android does not provide a separate test case class for BroadcastReceiver. Instead, test a BroadcastReceiver by testing the component that sends it Intent objects, to verify that the BroadcastReceiver responds correctly.

ApplicationTestCase

You use the ApplicationTestCase test case class to test the setup and teardown of Application objects. These objects maintain the global state of information that applies to all the components in an application package. The test case can be useful in verifying that the <application> element in the manifest file is correctly set up. Note, however, that this test case does not allow you to control testing of the components within your application package.

InstrumentationTestCase

If you want to use instrumentation methods in a test case class, you must use InstrumentationTestCase or one of 14

Page 15: AndroidAutomatedTestingTopicalGuidelines v0.0.4

its subclasses. The Activity test cases extend this base class with other functionality that assists in Activity testing.

Assertion classes

Because Android test case classes extend JUnit, you can use assertion methods to display the results of tests. An assertion method compares an actual value returned by a test to an expected value, and throws an AssertionException if the comparison test fails. Using assertions is more convenient than doing logging, and provides better test performance.

Besides the JUnit Assert class methods, the testing API also provides the MoreAsserts and ViewAsserts classes:

• MoreAsserts contains more powerful assertions such as assertContainsRegex(String, String), which does regular expression matching.

• ViewAsserts contains useful assertions about Views. For example it contains asse rtHasScreenCoordinates(View, View, int, int) that tests if a View has a particular X and Y position on the visible screen. These asserts simplify testing of geometry and alignment in the UI.

Mock object classes

To facilitate dependency injection in testing, Android provides classes that create mock system objects such as Context objects, ContentProvider objects, ContentResolver objects, and Service objects. Some test cases also provide mock Intent objects. You use these mocks both to isolate tests from the rest of the system and to facilitate dependency injection for testing. These classes are found in the packages android.test and android.test.mock.

Mock objects isolate tests from a running system by stubbing out or overriding normal operations. For example, a MockContentResolver replaces the normal resolver framework with its own local framework, which is isolated from the rest of the system. MockContentResolver also stubs out the notifyChange(Uri, ContentObserver, boolean) method so that observer objects outside the test environment are not accidentally triggered.

Mock object classes also facilitate dependency injection by providing a subclass of the normal object that is non-functional except for overrides you define. For example, the MockResources object provides a subclass of Resources in which all the methods throw Exceptions when called. To use it, you override only those methods that must provide information.

These are the mock object classes available in Android:

Simple mock object classes

MockApplication, MockContex t , MockContentProvider, MockCursor, MockDialogInterface, MockPackageManager, and MockResources provide a simple and useful mock strategy. They are stubbed-out versions of the corresponding system object class, and all of their methods throw an UnsupportedOperationException exception if called. To use them, you override the methods you need in order to provide mock dependencies.

Note: MockContentProvider and MockCursor are new as of API level 8.

Resolver mock objects

MockContentResolver provides isolated testing of content providers by masking out the normal system resolver framework. Instead of looking in the system to find a content provider given an authority string, MockContentResolver uses its own internal table. You must explicitly add providers to this table using addProvider(String, ContentProvider).

With this feature, you can associate a mock content provider with an authority. You can create an instance of a real provider but use test data in it. You can even set the provider for an authority to null. In effect, a MockContentResolver object isolates your test from providers that contain real data. You can control the

15

Page 16: AndroidAutomatedTestingTopicalGuidelines v0.0.4

function of the provider, and you can prevent your test from affecting real data.

Contexts for testing

Android provides two Context classes that are useful for testing:

• IsolatedContext provides an isolated Context, File, directory, and database operations that use this Context take place in a test area. Though its functionality is limited, this Context has enough stub code to respond to system calls.

This class allows you to test an application's data operations without affecting real data that may be present on the device.

• RenamingDelegatingContext provides a Context in which most functions are handled by an existing Context, but file and database operations are handled by an IsolatedContext. The isolated part uses a test directory and creates special file and directory names. You can control the naming yourself, or let the constructor determine it automatically.

This object provides a quick way to set up an isolated area for data operations, while keeping normal functionality for all other Context operations.

Running Tests

Test cases are run by a test runner class that loads the test case class, set ups, runs, and tears down each test. An Android test runner must also be instrumented, so that the system utility for starting applications can control how the test package loads test cases and the application under test. You tell the Android platform which instrumented test runner to use by setting a value in the test package's manifest file.

InstrumentationTestRunner is the primary Android test runner class. It extends the JUnit test runner framework and is also instrumented. It can run any of the test case classes provided by Android and supports all possible types of testing.

You specify InstrumentationTestRunner or a subclass in your test package's manifest file, in the <instrumentation> element. Also, InstrumentationTestRunner code resides in the shared library android.test.runner, which is not normally linked to Android code. To include it, you must specify it in a <uses-library> element. You do not have to set up these elements yourself. Both Eclipse with ADT and the android command-line tool construct them automatically and add them to your test package's manifest file.

Note: If you use a test runner other than InstrumentationTestRunner, you must change the <instrumentation> element to point to the class you want to use.

To run InstrumentationTestRunner, you use internal system classes called by Android tools. When you run a test in Eclipse with ADT, the classes are called automatically. When you run a test from the command line, you run these classes with Android Debug Bridge (adb).

The system classes load and start the test package, kill any processes that are running an instance of the application under test, and then load a new instance of the application under test. They then pass control to InstrumentationTestRunner, which runs each test case class in the test package. You can also control which test cases and methods are run using settings in Eclipse with ADT, or using flags with the command-line tools.

Neither the system classes nor InstrumentationTestRunner run the application under test. Instead, the test case does this directly. It either calls methods in the application under test, or it calls its own methods that trigger lifecycle events in the application under test. The application is under the complete control of the test case, which allows it to set up the test environment (the test fixture) before running a test. This is demonstrated in the previous code snippet that tests an Activity that displays a Spinner widget.

To learn more about running tests, please read the topics Testing from Eclipse with ADT or Testing from Other IDEs.

16

Page 17: AndroidAutomatedTestingTopicalGuidelines v0.0.4

Seeing Test Results

The Android testing framework returns test results back to the tool that started the test. If you run a test in Eclipse with ADT, the results are displayed in a new JUnit view pane. If you run a test from the command line, the results are displayed in STDOUT. In both cases, you see a test summary that displays the name of each test case and method that was run. You also see all the assertion failures that occurred. These include pointers to the line in the test code where the failure occurred. Assertion failures also list the expected value and actual value.

The test results have a format that is specific to the IDE that you are using. The test results format for Eclipse with ADT is described in Testing from Eclipse with ADT. The test results format for tests run from the command line is described in Testing from Other IDEs.

Monkey and monkeyrunner

The SDK provides two tools for functional-level application testing:

• The UI/Application Exerciser Monkey, usually called "monkey", is a command-line tool that sends pseudo-random streams of keystrokes, touches, and gestures to a device. You run it with the Android Debug Bridge (adb) tool. You use it to stress-test your application and report back errors that are encountered. You can repeat a stream of events by running the tool each time with the same random number seed.

• The monkeyrunner tool is an API and execution environment for test programs written in Python. The API includes functions for connecting to a device, installing and uninstalling packages, taking screenshots, comparing two images, and running a test package against an application. Using the API, you can write a wide range of large, powerful, and complex tests. You run programs that use the API with the monkeyrunner command-line tool.

Working with Package names

In the test environment, you work with both Android application package names and Java package identifiers. Both use the same naming format, but they represent substantially different entities. You need to know the difference to set up your tests correctly.

An Android package name is a unique system name for a .apk file, set by the "android:package" attribute of the <manifest> element in the package's manifest. The Android package name of your test package must be different from the Android package name of the application under test. By default, Android tools create the test package name by appending ".test" to the package name of the application under test.

The test package also uses an Android package name to target the application package it tests. This is set in the "android:targetPackage" attribute of the <instrumentation> element in the test package's manifest.

A Java package identifier applies to a source file. This package name reflects the directory path of the source file. It also affects the visibility of classes and members to each other.

Android tools that create test projects set up an Android test package name for you. From your input, the tools set up the test package name and the target package name for the application under test. For these tools to work, the application project must already exist.

By default, these tools set the Java package identifier for the test class to be the same as the Android package identifier. You may want to change this if you want to expose members in the application under test by giving them package visibility. If you do this, change only the Java package identifier, not the Android package names,

17

Page 18: AndroidAutomatedTestingTopicalGuidelines v0.0.4

and change only the test case source files. Do not change the Java package name of the generated R.java class in your test package, because it will then conflict with the R.java class in the application under test. Do not change the Android package name of your test package to be the same as the application it tests, because then their names will no longer be unique in the system.

What to Test

The topic What To Test describes the key functionality you should test in an Android application, and the key situations that might affect that functionality.

Most unit testing is specific to the Android component you are testing. The topics Activity Testing, Content Provider Testing, and Service Testing each have a section entitled "What To Test" that lists possible testing areas.

When possible, you should run these tests on an actual device. If this is not possible, you can use the Android Emulator with Android Virtual Devices configured for the hardware, screens, and versions you want to test.

Testing from Eclipse with ADT

This topic explains how create and run tests of Android applications in Eclipse with ADT. Before you read this topic, you should read about how to create an Android application with the basic processes for creating and running applications with ADT, as described in Managing Projects from Eclipse and Building and Running from Eclipse. You may also want to read Testing Fundamentals, which provides an overview of the Android testing framework.

ADT provides several features that help you set up and manage your testing environment effectively:

• It lets you quickly create a test project and link it to the application under test. When it creates the test

project, it automatically inserts the necessary <instrumentation> element in the test package's manifest file.

• It lets you quickly import the classes of the application under test, so that your tests can inspect them.

• It lets you create run configurations for your test package and include in them flags that are passed to the Android testing framework.

• It lets you run your test package without leaving Eclipse. ADT builds both the application under test and the test package automatically, installs them if necessary to your device or emulator, runs the test package, and displays the results in a separate window in Eclipse.

Creating a Test Project

To set up a test environment for your Android application, you must first create a separate project that holds the test code. The new project follows the directory structure used for any Android application. It includes the same types of content and files, such as source code, resources, a manifest file, and so forth. The test package you create is connected to the application under test by an <instrumentation> element in its manifest file.

The New Android Test Project dialog makes it easy for you to generate a new test project that has the proper structure, including the <instrumentation> element in the manifest file. You can use the New Android Test Project dialog to generate the test project at any time. The dialog appears just after you create a new Android main application project, but you can also run it to create a test project for a project that you created previously.

To create a test project in Eclipse with ADT:18

Page 19: AndroidAutomatedTestingTopicalGuidelines v0.0.4

1. In Eclipse, select File > New > Other. This opens the Select a Wizard dialog.2. In the dialog, in the Wizards drop-down list, find the entry for Android, then click the toggle to the left.

Select Android Test Project, then at the bottom of the dialog click Next. The New Android Test Project wizard appears.

3. Next to Test Project Name, enter a name for the project. You may use any name, but you may want to associate the name with the project name for the application under test. One way to do this is to take the application's project name, append the string "Test" to it, and then use this as the test package project name.

The name becomes part of the suggested project path, but you can change this in the next step.

4. In the Content panel, examine the suggested path to the project. If Use default location is set, then the wizard will suggest a path that is a concatenation of the workspace path and the project name you entered. For example, if your workspace path is /usr/local/workspace and your project name is MyTestApp, then the wizard will suggest /usr/local/workspace/MyTestApp. To enter your own choice for a path, unselect Use default location, then enter or browse to the path where you want your project.

To learn more about choosing the location of test projects, please read Testing Fundamentals.

5. In the Test Target panel, set An Existing Android Project, click Browse, then select your Android application from the list. You now see that the wizard has completed the Test Target Package, Application Name, and Package Name fields for you (the latter two are in the Properties panel).

6. In the Build Target panel, select the Android SDK platform that the application under test uses.7. Click Finish to complete the wizard. If Finish is disabled, look for error messages at the top of the

wizard dialog, and then fix any problems.

Creating a Test Package

Once you have created a test project, you populate it with a test package. This package does not require an Activity, although you can define one if you wish. Although your test package can combine Activity classes, test case classes, or ordinary classes, your main test case should extend one of the Android test case classes or JUnit classes, because these provide the best testing features.

Test packages do not need to have an Android GUI. When you run the package in Eclipse with ADT, its results appear in the JUnit view. Running tests and seeing the results is described in more detail in the section Running Tests.

To create a test package, start with one of Android's test case classes defined in android.test. These extend the JUnit TestCase class. The Android test classes for Activity objects also provide instrumentation for testing an Activity. To learn more about test case classes, please read the topic Testing Fundamentals.

Before you create your test package, you choose the Java package identifier you want to use for your test case classes and the Android package name you want to use. To learn more about this, please read Testing Fundamentals.

To add a test case class to your project:

1. In the Project Explorer tab, open your test project, then open the src folder.2. Find the Java package identifier set by the projection creation wizard. If you haven't added classes yet,

this node won't have any children, and its icon will not be filled in. If you want to change the identifier value, right-click the identifier and select Refactor > Rename, then enter the new name.

3. When you are ready, right-click the Java package identifier again and select New > Class. This displays the New Java Class dialog, with the Source folder and Package values already set.

4. In the Name field, enter a name for the test case class. One way to choose a class name is to append the string "Test" to the class of the component you are testing. For example, if you are testing the class MyAppActivity, your test case class name would be MyAppActivityTest. Leave the modifiers set to

19

Page 20: AndroidAutomatedTestingTopicalGuidelines v0.0.4

public.5. In the Superclass field, enter the name of the Android test case class you are extending. You can also

browse the available classes.6. In Which method stubs would you like to create?, unset all the options, then click Finish. You will set up

the constructor manually.7. Your new class appears in a new Java editor pane.

You now have to ensure that the constructor is set up correctly. Create a constructor for your class that has no arguments; this is required by JUnit. As the first statement in this constructor, add a call to the base class' constructor. Each base test case class has its own constructor signature. Refer to the class documentation in the documentation for android.test for more information.

To control your test environment, you will want to override the setUp() and tearDown() methods:

• setUp(): This method is invoked before any of the test methods in the class. Use it to set up the environment for the test (the test fixture. You can use setUp() to instantiate a new Intent with the action ACTION_MAIN. You can then use this intent to start the Activity under test.

• tearDown(): This method is invoked after all the test methods in the class. Use it to do garbage collection and to reset the test fixture.

Another useful convention is to add the method testPreconditions() to your test class. Use this method to test that the application under test is initialized correctly. If this test fails, you know that that the initial conditions were in error. When this happens, further test results are suspect, regardless of whether or not the tests succeeded.

The Resources tab contains an Activity Testing tutorial with more information about creating test classes and methods.

20

Page 21: AndroidAutomatedTestingTopicalGuidelines v0.0.4

4. Android Activity Testing

___________________________________Now that we have seen the basic elements of an Android Application Project, let’s look deeper into the matter and, for the given project RoTemps, let’s see what the application can do and then to set out testing goals.

First of all we can navigate between pages using a menu. When opening the menu, we can select Send CV and we will be taken to a second page, corresponding to a second activity, where we have several fields to fill and after all the process is complete we can submit the form by pressing Send button.

Having all these function in mind we can start planning our testing procedures. First of all we could try to select an option from the available menu and navigate to the Send CV page.

Let’s start by creating a new Test Project and afterwards find a way to simulate touching a button. For creating a new test project we must go to File->New->Other->Android Test Project.

After choosing a name for our Test Project (in this case MyFirstTestProject), one of the most important steps is choosing for which Android Project we will write the tests. In our case we only have one available project.

! Note that you can declare a Test Project for just one Android Project.

21

Page 22: AndroidAutomatedTestingTopicalGuidelines v0.0.4

As we can see in the following capture, the structure of a Test Project is similar to the structure of the Project to be tested.

Now let’s start the actual development of our JUnit test.In com.rinf.mobile.rotemps.test package we will need to have a JUnit Test Case Class, so we will create it.

Now, about the actual code we will start step by step to see how to create a JUnit Test, how to simulate a button press and how to simulate a sequence of keystrokes.

package com.rinf.mobile.rotemps.test;

import junit.framework.TestCase;

public class ActivityTesting extends TestCase {

}

This is the basic test that Java offers when creating the first Junit Test. But we have to change a few lines in order to use this class for Android Testing. The changes are highlighted below:

package com.rinf.mobile.rotemps.test;

import com.rinf.mobile.rotemps.SendCV;import android.test.ActivityInstrumentationTestCase2;

public class ActivityTesting extends ActivityInstrumentationTestCase2<SendCV> {

Solo solo;

public ActivityTesting() { // constructorsuper(SendCV.class);}

protected void setUp() throws Exception {solo = new Solo(getInstrumentation(), getActivity());

}protected void tearDown() throws Exception {

22

Page 23: AndroidAutomatedTestingTopicalGuidelines v0.0.4

solo.finishOpenedActivities();}

}

We will use a framework (Robotium) alongside with JUnit basic testing in order to simplify the access to graphical elements.

After creating the test Project we need to import robotium-solo-4.3.1.jar into our project. First it must be downloaded from the address https :// code.google.com/p/robotium/downloads/list . For this project we used version 4.3. 1.

The steps to follow when importing the jar file are the following:1. TestProjectName -> right click-> Properties -> Java Builder Path -> Add External Jar. 2. Search for the jar file and select it.3. Go to „Order and Export tab”.4. Check the box corresponding to robotium-solo-4.3.1.jar.

For any new test class there are some conventions that must be taken into consideration:1. Name of the test class must end with “Test”2. Name of the method must begin with “test”3. Return type of a test method must be void4. Test method must not throw any exception5. Test method must have any parameter

In case we need to initialize some components we must know which element corresponds to which id, we must

23

Page 24: AndroidAutomatedTestingTopicalGuidelines v0.0.4

look into the layout of the class that will be tested and search for the specific elements that we need to access.

The initialization of a certain element must be done in setUp() method.

protected void setUp() throws Exception {solo = new Solo(getInstrumentation(), getActivity());nameET = (EditText) solo.getView(com.rinf.mobile.rotemps.R.id.etName);

}

To run a test we must go to MyFirstTestProject, right click and then go to Run. The second option available is “Android JUnit Test”. This is the proper way to launch a JUnit test.

Here, we have an example of a test method. The requirements are to complete all fields, check the CheckBox and after pressing the button we must have displayed the same name as the one entered.The test has the following structure:

@SmallTestpublic void testFieldCompletion() {

solo.enterText(nameET, "my name");solo.enterText(1, " my address");solo.enterText(2, "this is my email");

24

Page 25: AndroidAutomatedTestingTopicalGuidelines v0.0.4

solo.enterText(3, "0179");solo.clickOnCheckBox(0);

solo.clickOnButton("Send");solo.clickOnButton("Yes");assertTrue(solo.searchText("my name"));

}

After running the test we have the following output:

This means everything went ok, there are no errors and also our Asserts were true.

For another assertion, such as the one below, the test will fail and we will get a red bar instead of a green one.

assertTrue(solo.searchText("nothing"));

For each test that fails, we also have information about the reasons that led to the failure.

For the last asset, we are actually searching the String “nothing” within the current view. For the case that one of the TextViews has the label “nothing”, the test method will not be able to distinguish between the String from the EditText field or the label. In case we need a more specific search the procedure must be the following: Declare the EditText element

EditText nameET;

In setUp() method, initialize the EditText with its corresponding idnameET = (EditText)

solo.getView(com.rinf.mobile.rotemps.R.id.etName); Retrieve information from EditText

String name = nameET.getText().toString();

Make the proper AssertionassertEquals("Mary", name);

For accessing different elements of the view, we have the following commands:25

Page 26: AndroidAutomatedTestingTopicalGuidelines v0.0.4

Buttonsolo.clickOnButton("Send");

EditTextsolo.enterText(nameET, "Mary"); // using the id of the elementsolo.enterText(1, " my address"); // using the position

!! The counting starts from 0 so the string “my address” will be inserted in the second EditText field found in the current view.

CheckBoxsolo.clickOnCheckBox(0);

RadioButtonsolo.clickOnRadioButton(0);

DatePicker solo.setDatePicker(0, year, month, day);

ImageButtonsolo.clickOnImageButton(0);

For a button that has no text displayed (is just an image) we have the following method of access: Declare the element as a button

Button buttonview ;

Get the corresponding id for the element (in setUp() method)

buttonview = (Button) solo.getView(com.example.finditz1_0_1.R.id.b_add_other_save);

Access the element (inside the test method)

solo.clickOnView(buttonview);

Also we can search for a specific String in the current view using solo.searchText("OK"). But as this sequence offers as output a Boolean, it is more suitable to be used for an Assertion (as in @SmallTest example).

For a Spinner, the proper way of accessing it is:solo.pressSpinnerItem(int SpinnerIndex, int ItemIndex);

Another useful command is the one that simulates Back button.solo.goBack();

26

Page 27: AndroidAutomatedTestingTopicalGuidelines v0.0.4

5. Android Service Testing

___________________________________

What is a Service?A Service is an application component without a user interface that runs in the background and can perform long- running operations. It can be started by another application component and will continue to run in the background even if the user switches to another application.A service can take two forms:Started

A service is "started" when an application component (such as an activity) starts it by calling

startService(). Once started, a service can run in the background indefinitely, even if the component that started it is destroyed. Usually, a started service performs a single operation and does not return a result to the caller.

BoundA service is "bound" when an application component binds to it by calling bindServic e() . A bound service offers a client-server interface that allows components to interact with the service, send requests, get results, and even do so across processes with interprocess communication (IPC). A bound service runs only as long as another application component is bound to it. Multiple components can bind to the service at once, but when all of them unbind, the service is destroyed.

Service Lifecycle—from when it's created to when it's destroyed—can follow two different paths:

• A started serviceThe service is created when another component calls startService(). The service then runs indefinitely and must stop itself by calling stopSelf(). Another component can also stop the service by calling stopService(). When the service is stopped, the system destroys it

• A bound serviceThe service is created when another component (a client) calls bindService(). The client then communicates with the

service through an Ibinder interface. The client can close the connection by calling unbindService(). Multiple clients can bind to the same service and when all of them unbind, the system destroys the service. (The service does not need to stop itself.)

27

Page 28: AndroidAutomatedTestingTopicalGuidelines v0.0.4

6. Content Provider Testing

___________________________________

Content providers manage access to a structured set of data. They encapsulate the data and also provide mechanisms for defining data security. Content providers are the standard interface that connects data in one process with code running in another process.

A content provider component supplies data from one application to others on request. Such requests are handled by the methods of the ContentResolver class. A content provider can use different ways to store its data and the data can be stored in a database, in files, or even over a network.

Each Android applications runs in its own process with its own permissions which keeps an application data hidden from another application. But sometimes it is required to share data across applications. This is where content providers become very useful.

In our case we need to store the information provided by the user in the Send CV Form and display it in the message that will be submitted in the following stage.

First of all I decided that the data will be stored with the use of SharedPreferences. In this case, the saving procedure is the following:mySharedPreferences = this.getActivity().getSharedPreferences("MY_PREFS",

Context.MODE_PRIVATE);SharedPreferences.Editor editor = mySharedPreferences.edit();

Here we used an editor and stored each specific information with a corresponding nameeditor.putString("name", getApplicantName);

For retrieving the stored information we need to use the following command. getApplicantName = mySharedPreferences.getString("name", null);

To test if our data is passed from one activity to another, a simple test is to actually go to the layout where we have displayed this information and visually check it. This can be done by creating a test where we insert a specific string and at the end of the test create an assert statement where we actually check out input data and the output one.

28

Page 29: AndroidAutomatedTestingTopicalGuidelines v0.0.4

7. Online Documentation

___________________________________

• http://www.vogella.com/tutorials/AndroidTesting/article.html

• http://www.fhnw.ch/technik/imvs/publikationen/vortraege-2010/android-testing

• http://agile.csc.ncsu.edu/SEMaterials/WhiteBox.pdf

• http://www.vogella.com/tutorials/JUnit/article.html

• http://developer.android.com/tools/testing/index.html

• http://junit.sourceforge.net/doc/cookbook/cookbook.htm

• https://code.google.com/p/robotium/

29