Android provides a series of powerful testing tools. It extends the industry-standard JUnit testing framework for the android environment. Although you can use JUnit to test the android project, the android tool allows you to perform more complex tests for all aspects of the application, including the unit and framework layers.
Main features of the android testing environment include:
L can access Android objects.
L The instrumentation framework can control and test applications.
L simulated version of common android objects.
L a tool that runs a single test or test suite with or without instrumentation.
L supports managing the test and test projects using the eclipse ADT plug-in and command line.
This article briefly introduces the android testing environment and testing methods, and assumes that you already have some experience in Android Application Programming and JUnit testing.
Summary
The core of the android testing environment is an instrumentation framework. Under this framework, your testing application can precisely control the application. With instrumentation, you can create simulated system objects, such as context, control multiple lifecycles of applications, and send UI events to applications before the main program starts; check the program status during execution. The instrumentation framework implements these functions by running the main program and the test program in the same process.
Add the <instrumentation> element to the manifest file of the test project to specify the application to be tested. The feature of this element specifies the name of the application package to be tested and shows Android how to run the test program. More details are provided in the inustrumentation testrunner chapter.
The following figure outlines the android testing environment:
In Android, the test program is also an android program. Therefore, it has many similarities with the writing method of the tested program. The SDK helps you create the main program project and its test project at the same time. You can run the android test through the eclipse ADT plug-in or command line. Eclipse's ADT provides a large number of tools to create test cases, run and view results.
Testing API
Android provides a testing API Based on the JUnit testing framework to write test cases and programs. In addition, Android provides a powerful instrumentation framework that allows test cases to Access Program states and runtime objects.
The following sections describe the main test APIs available in Android.
JUnit testcase class
The testcase inherited from JUnit cannot use the instrumentation framework. However, these classes contain methods for accessing system objects (such as context. With context, you can browse resources, files, databases, and so on. The base class is androidtestcase, which is generally a subclass of it and is associated with a specific component.
Subclass:
L applicationtestcase -- test the entire application class. It allows you to inject a simulated context into the application, initialize the test parameters before the application starts, and check the application before it is destroyed after the application ends.
L providertestcase2 -- test the class of a single contentprovider. Because mockcontentresolver is required and an isolatedcontext is injected, provider testing is isolated from OS.
L servicetestcase -- test the class of a single service. You can inject a simulated context or simulated application (or both), or let Android provide context and mockapplication for you.
Instrumentation testcase class
It inherits from the JUnit testcase class and can use the instrumentation framework to test the activity. With instrumentation, android can send events to the program for automatic UI testing, precisely control the startup of the activity, and monitor the status of the activity lifecycle.
The base class is instrumentationtestcase. All its sub-classes can send buttons or touch events to the UI. Subclass can also inject a simulated intent.
Subclass:
L activitytestcase -- base class of the activity test class.
L singlelaunchactivitytestcase -- test the class of a single activity. It can trigger setup () and teardown () once, instead of triggering each method call. If your testing method is for the same activity, use it.
L syncbaseinstrumentation -- test the synchronization class of the content provider. It uses instrumentation to cancel existing synchronization objects before starting the test synchronization.
L activityunittestcase-a class for a single test on a single activity. Using it, You can inject the simulated context or application, or both. It is used to perform unit tests on the activity.
Unlike other instrumentation classes, this test class cannot be injected with a simulated intent.
L activityinstrumentationtestcase2 -- test the class of a single activity in a normal system environment. You cannot inject a simulated context, but you can inject a simulated intent. In addition, you can run the test method in the UI thread (the main thread of the Application), and send buttons and touch events to the application UI.
Assert class
Android also inherits the assert class of JUnit, which has two sub-classes: moreasserts and viewasserts:
L The moreasserts class contains more powerful asserted methods, such as assertcontainsregex (string, string), which can be used for regular expression matching.
L The viewasserts class contains useful assertions about Android view, such as asserthasscreencoordinates (view, view, Int, INT). You can test the specific x and y positions of the view in the visible area. These assert simplifies the test of ry and alignment in the UI.
Mock object class
Android has some classes to easily create simulated system objects, such as application, context, content Resolver and resource. Android also provides some methods in some test classes to create a simulated intent. Because these simulated objects are easier to use than actual objects, using them can simplify dependency injection. You can find these classes in Android. Test and Android. Test. Mock.
They are:
L isolatedcontext -- simulate a context so that the application can run in isolation. At the same time, there is a lot of code to help us complete communication with context. This class is useful in unit testing.
L renamingdelegatingcontext -- when modifying the default file and database name, you can delegate most functions to an existing and common context. Use this class to test operations between files and databases and normal System context.
L mockapplication, mockcontentresolver, mockcontext, mockdialoginterface, mockpackagemanager, mockresources -- class for creating Simulated System Objects. They only expose methods that are useful for object management. The default implementation of these methods only throws an exception. You need to inherit these classes and override these methods.
Instrumentation testrunner
Android provides a custom class for running test cases, called instrumentationtestrunner. This class controls the application to be in a test environment, run the test program and main program in the same process, and output the test results to the appropriate place. The key to intrumentationtestrunner's control over the entire test environment during runtime is the use of instrumentation. Note that if your test class does not use instrumentation, you can also use this testrunner.
When you run a test program, a system tool called activity manager is first run. Activity Manager uses the instrumentation framework to start and control testrunner. This testrunner, in turn, uses intrumentation to close instances of any main program, and then starts the test program and main program (in the same process ). This ensures direct interaction between the test program and the main program.
Work in testing environment
Tests on Android programs are included in a test program. It is also an Android Application. The test program exists as a separate Android project and has the same files and folders as normal Android programs. The test project specifies the application to be tested in the manifest file.
Each test program contains one or more test cases for specific types of components. The test case defines the Testing Method for certain parts of the test application. When you run the test program, Android will load the main program in the same process, and then trigger the test method in each test case.
Test Project
To start testing an android program, you must use the android tool to create a test project. The tool creates project folders, files, and required subfolders. The tool also creates a manifest file to specify the application to be tested.
Test Cases
A test program contains one or more test cases inherited from the android testcase class. Selecting a test case class depends on the type of the android component you want to test and what kind of test you want to perform. A test program can test different components, but each test case class can only test a single type of components.
Some Android components have multiple associated test case classes. In this case, you need to determine the type of test to be performed between the selectable classes. For example, you have two options for activity: activityinstrumentationtestcase2 and activityunittestcase.
Activityinstrumentationtestcase2 is designed for some functional tests. Therefore, it tests activity in a normal system environment. You can inject a simulated intent, but not a simulated context. Generally, you cannot simulate the dependency between activities.
Activityunittestcase is designed for unit testing, so it tests activity in an isolated system environment. In other words, when you use this test class, the activity cannot interact with other activities.
As an empirical rule, if you want to test the interaction between activity and Android, use activityinstrumentationtestcase2. To perform a regression test on an activity, use activityunittestcase.
Test Method
Each test case class provides a way to establish a test environment and control applications. For example, all test case classes provide the setup () method of JUnit to build the test environment. In addition, you can add methods to define separate tests. Each added method runs once when you run the test program. If you override the setup () method, it runs before each method is run. Similarly, the teardown () method runs after each method.
The test case class provides a large number of methods for starting and stopping components. For this reason, before running the test, you need to explicitly tell android to start a component. For example, you can use getactivity () to start an activity. During the entire test case, you can only call this method once, or each test method once. You can even call its Finishing () in a single test method to destroy the activity, and then call getactivity () to restart the activity.
Run the test and view the result
After compiling the test project, you can use the system tool activity manager to run the test program. You provide the activity manager with the testrunner name (usually instrumentationtestrunner, specified in the Program). The name includes the package name and testrunner name of the tested program. Activity manager loads and starts your test program, kills any instance of the main program, loads the main program in the same process of the test program, and then passes the first test case of the test program. At this time, testrunner takes over these test cases and runs each test method until all the methods have finished running.
If you use eclipse, the result is displayed on the JUnit panel. If you use the command line, it will be output to stdout.
Test what?
In addition to some functional tests, here are some content you should consider for testing:
L Activity lifecycle events: You should test the correctness of activity processing lifecycle events. For example, an activity should save its status during a pause or destroy event. Remember that changes in the screen direction will also lead to the destruction of the current activity. Therefore, you need to test this occasional situation to ensure that the application status will not be lost.
L database operations: You should ensure that database operations can correctly handle changes in application status. Use the simulated object in Android. Test. Mock.
L screen size and resolution: Before releasing a program, ensure that the test passes on all screen sizes and resolutions to be run. You can use AVD for testing, or use a real target device for testing.
Additional: Ui Test
The following sections provide some tips for testing the application UI, especially to help you handle actions, touch screen and button events, and lock the screen in the UI thread.
Testing in the UI thread
The activity runs in the UI thread of the program. Once the UI is initialized, for example, after the oncreate () method of the activity, all interactions with the UI must run in the UI thread. When you run the program normally, it has the permission to access this thread, and nothing special happens.
This change occurs when you run the test program. In a class with instrumentation, You can trigger the method to run in the UI thread. This is not allowed for other test case classes. To run a complete test method in the UI thread, you can use @ uithreadtest to declare the thread. Note that all statements in the method will be run in the UI thread. This is not allowed for methods that do not interact with the UI. For example, you cannot trigger instrumentation. waitforidlesync ().
If you want some code in the method to run in the UI thread, create an anonymous runnable object, put the code in the run () method, and then pass the object to the appactivity. runonuithread (). Here, appactivity is the app object you want to test.
For example, the following code instantiates an activity to be tested, serves as the request focus of the spinner, and then sends a key to it. Note: waitforidlesync and sendkeys cannot be run in the UI thread:
Private myactivity mactivity; // myactivity is the class name of the app under test
Private spinner mspinner;
...
Protected void setup () throws exception {
Super. Setup ();
Minstrumentation = getinstrumentation ();
Mactivity = getactivity (); // get a references to the app under test
/*
* Get a reference to the main widget of the app under test, a spinner
*/
Mspinner = (spinner) mactivity. findviewbyid (COM. Android. Demo. myactivity. R. Id. spinner01 );
...
Public void atest (){
/*
* Request focus for the spinner, so that the test can send key events to it
* This request must be run on the UI thread. To do this, use the runonuithread Method
* And pass it a runnable that contains a call to requestfocus on the spinner.
*/
Mactivity. runonuithread (New runnable (){
Public void run (){
Mspinner. requestfocus ();
}
});
Minstrumentation. waitforidlesync ();
This. sendkeys (keyevent. keycode_dpad_center );
Turn Off Touch Screen mode
To control the button events sent from the test program to the simulator or device, you must turn off the touch screen mode. If you do not do this, the button event will be ignored.
To disable the touch mode, you must call activityinstrumentationtestcase2.setactivitytouchmode (false) before calling getactivity () to start the activity ). You must run this call in a non-UI thread. For this reason, you cannot declare a test method call with @ uithread. It can be called in setup.
Unlock a simulator or device
You may have discovered that if the keyboard protection mode of the simulator or device makes the home screen unavailable, the UI test will not work properly. This is because the application cannot receive sendkeys () events. The best way to avoid this is to disable the keyboard protection mode when the simulator or device is started.
You can also explicitly disable keyboard protection. This requires adding a permission to the manifest file, and then you can disable keyboard protection in the program. Note: You must remove this feature before releasing the program or disable it in the released program.
Add <uses-Permission Android: Name = "androd. Permission. disable_keyguard"/> under the <manifest> element. To disable keyboard protection, add the following code to the oncreate () method of the activity you are testing:
Mkeyguardmanager = (keyguardmanager) getsystemservice (keyguard_service );
Mlock = mkeyguardmanager. newkeyguardlock ("activity_classname ");
Mlock. disablekeyguard ();
Activity_classname is the name of the activity class.
Introduction to Instrumentation)