目录(?)[-]

  1. Android automated testing
    1. 1 How to test Android applications
    2. Tip
    3. 2 Unit tests vs functional tests
    4. 3 JUnit 3
    5. 4 Running tests on a server without display
  2. Test hooks into the Android framework
    1. 1 Instrumentation
    2. 2 How the Android system executes tests
  3. Android test classes and annotations
    1. 1 Android assertion and mock classes
    2. 2 Android test classes
    3. 3 Android test groups
    4. 4 Flaky tests
  4. Android test projects and running tests
    1. 1 Android test projects
    2. Note
    3. Note
    4. 2 Running tests
  5. Activity testing
    1. 1 ActivityUnitTestCase
    2. 2 ActivityInstrumentationTestCase2
    3. 3 Testing the initial state
    4. 4 State management tests
  6. Exercise unit test for an activity
    1. 1 Create project which is tested
    2. 2 Create unit test for activity
  7. Exercise functional test for activities
  8. Exercise Run tests via Apache Ant
  9. Service testing
  10. Content provider testing
  11. User interface testing
    1. 1 Cross-component user interface testing
    2. 2 uiautomator
    3. 3 uiautomatorviewer
  12. Monkey
  13. monkeyrunner
    1. 1 Testing with monkeyrunner
    2. 2 monkeyrunner example
  14. Common Android testing requires and solution approaches
    1. 1 Common logging on a server
    2. 2 Triggering system changes via tests
  15. Robotium
  16. Robolectric
    1. 1 Overview
    2. 2 Functionality
    3. 3 Installation
    4. 4 Example
  17. RoboGuice
    1. 1 RoboGuice
    2. 2 RoboGuice and testing
  18. Thank you
  19. Questions and Discussion
  20. Links and Literature
    1. 1 Source Code
    2. 2 Android Resources
    3. 3 vogella Resources

~~【PS】~~

原文:http://blog.csdn.net/wangxingqian/article/details/8972049

出处:http://www.vogella.com/articles/AndroidTesting/article.html

Table of Contents

1. Android automated testing
1.1. How to test Android applications
1.2. Unit tests vs functional tests
1.3. JUnit 3
1.4. Running tests on a server without display
2. Test hooks into the Android framework
2.1. Instrumentation
2.2. How the Android system executes tests
3. Android test classes and annotations
3.1. Android assertion and mock classes
3.2. Android test classes
3.3. Android test groups
3.4. Flaky tests
4. Android test projects and running tests
4.1. Android test projects
4.2. Running tests
5. Activity testing
5.1. ActivityUnitTestCase
5.2. ActivityInstrumentationTestCase2
5.3. Testing the initial state
5.4. State management tests
6. Exercise: unit test for an activity
6.1. Create project which is tested
6.2. Create unit test for activity
7. Exercise: functional test for activities
8. Exercise: Run tests via Apache Ant
9. Service testing
10. Content provider testing
11. User interface testing
11.1. Cross-component user interface testing
11.2. uiautomator
11.3. uiautomatorviewer
12. Monkey
13. monkeyrunner
13.1. Testing with monkeyrunner
13.2. monkeyrunner example
14. Common Android testing requires and solution approaches
14.1. Common logging on a server
14.2. Triggering system changes via tests
15. Robotium
16. Robolectric
16.1. Overview
16.2. Functionality
16.3. Installation
16.4. Example
17. RoboGuice
17.1. RoboGuice
17.2. RoboGuice and testing
18. Thank you
19. Questions and Discussion
20. Links and Literature
20.1. Source Code
20.2. Android Resources
20.3. vogella Resources

1. Android automated testing

1.1. How to test Android applications

Android testing is based on JUnit.

Testing for Android can be classified into tests which only require the JVM and tests which require the Android system.

You can use the JUnit test framework to test Java classes directly which do not call the Android API. Android provides JUnit extensions to test Android API.

Tip

You can not use standard JUnit tests on the JVM, because all methods in the android.jar JAR file of your Android program are only placeholder. Calling them result in a RuntimeException.

This is because android.jar JAR file does not contain the Android framework code but only stubs for the type signatures, methods, types, etc. The android.jar JAR file is only used for the Java compiler before deployment on an Android device. It is not bundled with your application. Once you application is deployed on the device it will use the android.jar JAR file on the Android device.

Unfortunately this make it impossible to test the Android framework classes direct on the JVM without additional libraries.

To test Android classes you need to run them on an Android device or emulator. This unfortunately makes the execution of tests longer.

1.2. Unit tests vs functional tests

A unit test tests only the functionality of a certain component. For example if an action in an activity which starts another activity activity is tested, a unit test determine only of a the intent was issued, not if the activity was started. A functional test would also check if the activity was correctly started.

1.3. JUnit 3

Currently the Android testing API supports JUnit 3 and not JUnit 4. In JUnit 3 test methods must start with the test prefix. The setup method must be called setUp() and the final clean up method must be called tearDown().

1.4. Running tests on a server without display

To run test without a display (headless) specify the adb -no-window parameter.

2. Test hooks into the Android framework

2.1. Instrumentation

The Android testing API provides hooks into the Android component lifecycle. These hooks are called the instrumentation API and allow your tests to control the application lifecycle. .

The Android instrumentation API allows you to run the test project and the normal Android project in the same process so that the test project can call methods of the Android project directly.

For example you can call the getActivity() which starts an activity and returns the activity which is tested. . Afterwards you can call the finish() method, followed by getActivity() again and you can test if the application restored its state correctly.

2.2. How the Android system executes tests

The InstrumentationTestRunner is the base test runner for Android tests. This test runner starts and loads the test methods. Via the instrumentation API is communicates with the Android system. If you start a test for an Android application, the Android system kills any process of the application under test and then loads a new instance. It does not work the application this is done via the test methods. These test method control the lifecycle of the components of the application.

3. Android test classes and annotations

3.1. Android assertion and mock classes

The Android testing API provides in addition to the standard JUnit Assert class, the MoreAsserts and ViewAsserts class.

Mock classes allows you to isolate tests from a running system by stubbing out or overriding normal operations. Android provides mock classes for the Android framework in the android.test and android.test.mock packages.

3.2. Android test classes

The Android test framework is still based on JUnit3 hence your test needs to extend the TestCase class and all test methods must start with test.

You can use the AndroidTestCase to test Android components which have no visual parts, e.g. Applications, Services or ContentProvider.

Android provides the following test classes which extends the TestCase class.

Table 1. Test classes

Android Test class Description
AndroidTestCase Provides methods to test permissions.
ApplicationTestCase Provides methods to test the setup and teardown of Application objects.
InstrumentationTestCase Base class for using instrumentation methods.

Instrumentation allows to control a visible part of the application, e.g. an
activity. For this your testcase would extend
ActivityUnitTestCase
.

This instrumentation class allows you to start and stop
activities
, run actions on the user interface thread, send key events and more.

The ActivityInstrumentationTestCase2 class can be used to test access several
Activities. ActivityInstrumentationTestCase2 allows to use the full Android system infrastructure. .

3.3. Android test groups

You can annotate tests with the @SmallTest,
@MediumTest
and @LargeTest annotation and decide which test group you want to run.

The following screenshot shows the selection in the Run Configuration of Eclipse.

This allows you to run for example only tests which do not run very
long in Eclipse. Long running tests could than run only in the
continuous integration server.

3.4. Flaky tests

Actions in Android are sometimes time dependent. To tell Android to repeat a test once if it fails, use the
@FlakyTest annotation. Via the tolerance
attribute of this annotation you can define how often the Android test
framework should try to repeat a test before marking it as failed.

4. Android test projects and running tests

4.1. Android test projects

Android organizes tests into separate Android test projects. Instead
of Android components, an Android test application contains one or more
test classes.

Note

The application which is tested is typically called the
application under test
.

The Android development tools (ADT) provide support for the creation
of Android test projects. via a project creation wizard. This wizard can
be reached under
File → New →
Other... → Android →
Android Test Project.

Note

It is good practice to use the name of the project under test and add
Test
or .test to it. We use the
.test
notation to have the project name the same as the package name.

The project creation wizard adds the project which should be tested
as dependency to the test project. It also create a version of the
AndroidManifest.xml file which specifies that the
android.test.runner
test library should be used and it specifies an
instrumentation
.

A test project also specifies the package of the application to test in the
AndroidManifest.xml
file the under android:targetPackage attribute. The following listing shows an example
AndroidManifest.xml for a test project.

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="de.vogella.android.test.target.test"
  4. android:versionCode="1"
  5. android:versionName="1.0">
  6. <uses-sdk android:minSdkVersion="8" />
  7. <instrumentation
  8. android:targetPackage="de.vogella.android.test.target"
  9. android:name="android.test.InstrumentationTestRunner" />
  10. <application android:icon="@drawable/icon" android:label="@string/app_name">
  11.  
  12. <uses-library android:name="android.test.runner" />
  13. </application>
  14. </manifest>

4.2. Running tests

To start an test from Eclipse, right-click on the test class and select Run As → Andriod JUnit Test.

On the command line you can start test via the ant test command. This requires that you created the build.xml file for the test project with the android update test-project command.

  1. # -p path to the test project
  2. # -m path to the project under test
  3.  
  4. android update test-project -p . -m ../com.vogella.android.test.simpleactivity
  5.  
  6. # Afterwards run the tests
  7. ant test

5. Activity testing

5.1. ActivityUnitTestCase

To test an activity in isolation you can use the ActivityUnitTestCase class. This class allows you to check the layout of the activity and to check if intents are triggered as planned. The intents is not send to the Android system but you can use the getStartedActivityIntent() method to access a potential intent and validate its data.

ActivityUnitTestCase starts the activity in an IsolatedContext, i.e. mainly isolated from the Android system.

ActivityUnitTestCase can be used to test layouts and isolated methods in the activity.

As this test runs in an IsolatedContext the test must start the activity, i.e. it is not auto-started by the Android system.

  1. Intent intent = new Intent(getInstrumentation().getTargetContext(),
  2. MainActivity.class);
  3. startActivity(intent, null, null);
  4.  
  5. // After this call you can get the
  6. // Activity with getActivity()

5.2. ActivityInstrumentationTestCase2

Functional tests for an activity can be written with the ActivityInstrumentationTestCase2 class. The communication with the Android infrastructure is done via the Instrumentation class which can be access via the getInstrumentation() method. This class allows you to send keyboard and click events.

If you prefer to set values directly you need to use the runOnUiThread() of the activity. If all statements in your method interact with the UI thread you can also use the @UiThreadTest annotation on the method. In this case you are not allowed to use methods which do not run in the main UI thread.

Only an instrumentation-based test class allows you to send key events (or touch events) to the application under test.

ActivityInstrumentationTestCase2 starts the activity in the standard Android context, similar as if a user would start the application.

If you planning to have user interface interaction, e.g. via touch, you should use ActivityInstrumentationTestCase2.

If you want to send touch or key events directly via your test you have turn them off in the emulator via setActivityInitialTouchMode(false) in your setup() method of the test.

5.3. Testing the initial state

It is good practice to test the initial state of the application before the main activity start to be sure that the test conditions for the activity are fulfilled.

5.4. State management tests

You should write tests which verifies that the state of an activity remains even if it is paused or terminated by the Android system.

The ActivityInstrumentationTestCase2 class uses the Instrumentation class, which allows you to call the lifecycle hooks of the activities directly.

6. Exercise: unit test for an activity

6.1. Create project which is tested

Create a new Android project called com.vogella.android.test.simpleactivity with the activity called MainActivity.

Add a second activity called SecondActivity to your project. This activity should use a layout with at least one TextView. The id of the TextView should be "resultText" and its text should be set to "Started".

Add a button to the layout used by MainActivity. If this button is clicked the second activity should be started. Put the "http://www.vogella.com" String as extra into thecom.vogella.android.test.simpleactivity.test intent, use the key "URL" for this.

Here is some example code for the MainActivity.

  1. package com.vogella.android.test.simpleactivity;
  2.  
  3. import android.app.Activity;
  4. import android.content.Intent;
  5. import android.os.Bundle;
  6. import android.view.View;
  7.  
  8. public class MainActivity extends Activity {
  9.  
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.activity_main);
  14. }
  15.  
  16. public void onClick(View view) {
  17. Intent intent = new Intent(this, SecondActivity.class);
  18. intent.putExtra("URL", "http://www.vogella.com");
  19. startActivity(intent);
  20. }
  21. }

6.2. Create unit test for activity

Create a new test project called com.vogella.android.test.simpleactivity.test. Select com.vogella.android.test.simpleactivity as the project to test.

Create a test class called MainActivityUnitTest based on the superclass android.test.ActivityUnitTestCase. This class allows to test the activity.

  1. package com.vogella.android.test.simpleactivity.test;
  2.  
  3. import android.content.Intent;
  4. import android.test.TouchUtils;
  5. import android.test.suitebuilder.annotation.SmallTest;
  6. import android.widget.Button;
  7.  
  8. import com.vogella.android.test.simpleactivity.MainActivity;
  9.  
  10. public class MainActivityUnitTest extends
  11. android.test.ActivityUnitTestCase<MainActivity> {
  12.  
  13. private int buttonId;
  14. private MainActivity activity;
  15.  
  16. public MainActivityUnitTest() {
  17. super(MainActivity.class);
  18. }
  19. @Override
  20. protected void setUp() throws Exception {
  21. super.setUp();
  22. Intent intent = new Intent(getInstrumentation().getTargetContext(),
  23. MainActivity.class);
  24. startActivity(intent, null, null);
  25. activity = getActivity();
  26. }
  27.  
  28. @SmallTest
  29. public void testLayout() {
  30.  
  31. buttonId = com.vogella.android.test.simpleactivity.R.id.button1;
  32. assertNotNull(activity.findViewById(buttonId));
  33. Button view = (Button) activity.findViewById(buttonId);
  34. assertEquals("Incorrect label of the button", "Start", view.getText());
  35. }
  36.  
  37. @SmallTest
  38. public void testIntentTriggerViaOnClick() {
  39. buttonId = com.vogella.android.test.simpleactivity.R.id.button1;
  40. Button view = (Button) activity.findViewById(buttonId);
  41. assertNotNull("Button not allowed to be null", view);
  42.  
  43. // You would call the method directly via
  44. getActivity().onClick(view);
  45.  
  46. // TouchUtils cannot be used, only allowed in
  47. // InstrumentationTestCase or ActivityInstrumentationTestCase2
  48.  
  49. // Check the intent which was started
  50. Intent triggeredIntent = getStartedActivityIntent();
  51. assertNotNull("Intent was null", triggeredIntent);
  52. String data = triggeredIntent.getExtras().getString("URL");
  53.  
  54. assertEquals("Incorrect data passed via the intent",
  55. "http://www.vogella.com", data);
  56. }
  57.  
  58. @Override
  59. protected void tearDown() throws Exception {
  60.  
  61. super.tearDown();
  62. }
  63. }

7. Exercise: functional test for activities

Create a new test class called MainActivityFunctionalTest which allows to test across activities.

  1. package com.vogella.android.test.simpleactivity.test;
  2.  
  3. import android.app.Activity;
  4. import android.app.Instrumentation;
  5. import android.app.Instrumentation.ActivityMonitor;
  6. import android.test.ActivityInstrumentationTestCase2;
  7. import android.test.TouchUtils;
  8. import android.test.ViewAsserts;
  9. import android.view.KeyEvent;
  10. import android.view.View;
  11. import android.widget.Button;
  12. import android.widget.TextView;
  13.  
  14. import com.vogella.android.test.simpleactivity.R;
  15.  
  16. import com.vogella.android.test.simpleactivity.MainActivity;
  17. import com.vogella.android.test.simpleactivity.SecondActivity;
  18.  
  19. public class MainActivityFunctionalTest extends
  20. ActivityInstrumentationTestCase2<MainActivity> {
  21.  
  22. private MainActivity activity;
  23.  
  24. public MainActivityFunctionalTest() {
  25. super(MainActivity.class);
  26. }
  27. @Override
  28. protected void setUp() throws Exception {
  29. super.setUp();
  30. setActivityInitialTouchMode(false);
  31. activity = getActivity();
  32. }
  33.  
  34. public void testStartSecondActivity() throws Exception {
  35.  
  36. // Add monitor to check for the second activity
  37. ActivityMonitor monitor = getInstrumentation().addMonitor(SecondActivity.class.getName(), null, false);
  38.  
  39. // Find button and click it
  40. Button view = (Button) activity.findViewById(R.id.button1);
  41. TouchUtils.clickView(this, view);
  42.  
  43. // To click on a click, e.g. in a listview
  44. // listView.getChildAt(0);
  45.  
  46. // Wait 2 seconds for the start of the activity
  47. SecondActivity startedActivity = (SecondActivity) monitor
  48. .waitForActivityWithTimeout(2000);
  49. assertNotNull(startedActivity);
  50.  
  51. // Search for the textView
  52. TextView textView = (TextView) startedActivity.findViewById(R.id.resultText);
  53.  
  54. // Check that the TextView is on the screen
  55. ViewAsserts.assertOnScreen(startedActivity.getWindow().getDecorView(),
  56. textView);
  57. // Validate the text on the TextView
  58. assertEquals("Text incorrect", "Started", textView.getText().toString());
  59.  
  60. // Press back and click again
  61. this.sendKeys(KeyEvent.KEYCODE_BACK);
  62. TouchUtils.clickView(this, view);
  63.  
  64. }
  65.  
  66. }

To test the direct modification of a view, create the following test class for the SecondActivity class.

  1. package com.vogella.android.test.simpleactivity.test;
  2.  
  3. import android.app.Activity;
  4. import android.app.Instrumentation;
  5. import android.app.Instrumentation.ActivityMonitor;
  6. import android.test.ActivityInstrumentationTestCase2;
  7. import android.test.TouchUtils;
  8. import android.test.UiThreadTest;
  9. import android.test.ViewAsserts;
  10. import android.view.KeyEvent;
  11. import android.view.View;
  12. import android.widget.Button;
  13. import android.widget.TextView;
  14.  
  15. import com.vogella.android.test.simpleactivity.R;
  16.  
  17. import com.vogella.android.test.simpleactivity.MainActivity;
  18. import com.vogella.android.test.simpleactivity.SecondActivity;
  19.  
  20. public class SecondActivityFunctionalTest extends
  21. ActivityInstrumentationTestCase2<SecondActivity> {
  22.  
  23. private static final String NEW_TEXT = "new text";
  24.  
  25. public SecondActivityFunctionalTest() {
  26. super(SecondActivity.class);
  27. }
  28.  
  29. public void testSetText() throws Exception {
  30.  
  31. SecondActivity activity = getActivity();
  32.  
  33. // search for the textView
  34. final TextView textView = (TextView) activity
  35. .findViewById(R.id.resultText);
  36.  
  37. // set text
  38. getActivity().runOnUiThread(new Runnable() {
  39.  
  40. @Override
  41. public void run() {
  42. textView.setText(NEW_TEXT);
  43. }
  44. });
  45.  
  46. getInstrumentation().waitForIdleSync();
  47. assertEquals("Text incorrect", NEW_TEXT, textView.getText().toString());
  48.  
  49. }
  50.  
  51. @UiThreadTest
  52. public void testSetTextWithAnnotation() throws Exception {
  53.  
  54. SecondActivity activity = getActivity();
  55.  
  56. // search for the textView
  57. final TextView textView = (TextView) activity
  58. .findViewById(R.id.resultText);
  59.  
  60. textView.setText(NEW_TEXT);
  61. assertEquals("Text incorrect", NEW_TEXT, textView.getText().toString());
  62.  
  63. }
  64.  
  65. }

8. Exercise: Run tests via Apache Ant

Update your test project called com.vogella.android.test.simpleactivity.test to have a build.xml file.

Afterwards run the tests with the ant test command.

9. Service testing

To test an service you use the ServiceTestCase class. It provides the startService() and bindService() methods to interact with the service. The bindService() return immediately a IBinder object without callback.

Testing asynchronous processing in services is a challenge as the duration of this processing may vary.

It is good practice to test if the service handles correctly multiple calls from startService(). Only the first call of startService() triggers the onCreate() of the service but all calls trigger a call to onStartCommand() of the service.

10. Content provider testing

To test an content provider you use the ProviderTestCase2 class. ProviderTestCase2 instantiates automatically the provider under test and inserts an IsolatedContext object which is isolated from the Android system but still allows file and database access.

The usage of the IsolatedContext object ensures that your provider test does not affect the real device.

ProviderTestCase2 provides also access to a MockContentResolver via the getMockCOnktentResolver() method.

You should test all operations of the provider and also what happens if the provider is called with an invalid URI or with an invalid projection.

11. User interface testing

11.1. Cross-component user interface testing

Functional or back-box user interface testing does test the complete application and not single components of your application.

11.2. uiautomator

The Android SDK contains the uiautomator Java library for creating user interface tests and provides an engine to run these user interface tests. Both tools work only as of API 16.

uiautomator test project are standalone Java projects which the JUnit3 library and the uiautomator.jar and android.jar files from the android-sdk/platforms/api-version directory added to the build path.

uiautomator provides the UiDevice class to communicate with the device, the UiSelector class to search for elements on the screen and the UiObject which presents an user interface elements and is created based on the UiSelector class. The UiCollection class allows to select a number of user interface elements at the same time and UiScrollable allows to scroll in a view to find an element.

The following coding shows an example test from the official Android developer side. The URL for this is Testing UI example.

  1. package com.uia.example.my;
  2.  
  3. // Import the uiautomator libraries
  4. import com.android.uiautomator.core.UiObject;
  5. import com.android.uiautomator.core.UiObjectNotFoundException;
  6. import com.android.uiautomator.core.UiScrollable;
  7. import com.android.uiautomator.core.UiSelector;
  8. import com.android.uiautomator.testrunner.UiAutomatorTestCase;
  9.  
  10. public class LaunchSettings extends UiAutomatorTestCase {
  11.  
  12. public void testDemo() throws UiObjectNotFoundException {
  13.  
  14. // Simulate a short press on the HOME button.
  15. getUiDevice().pressHome();
  16.  
  17. // We???re now in the home screen. Next, we want to simulate
  18. // a user bringing up the All Apps screen.
  19. // If you use the uiautomatorviewer tool to capture a snapshot
  20. // of the Home screen, notice that the All Apps button???s
  21. // content-description property has the value ???Apps???. We can
  22. // use this property to create a UiSelector to find the button.
  23. UiObject allAppsButton = new UiObject(new UiSelector().description("Apps"));
  24.  
  25. // Simulate a click to bring up the All Apps screen.
  26. allAppsButton.clickAndWaitForNewWindow();
  27.  
  28. // In the All Apps screen, the Settings app is located in
  29. // the Apps tab. To simulate the user bringing up the Apps tab,
  30. // we create a UiSelector to find a tab with the text
  31. // label ???Apps???.
  32. UiObject appsTab = new UiObject(new UiSelector().text("Apps"));
  33.  
  34. // Simulate a click to enter the Apps tab.
  35. appsTab.click();
  36.  
  37. // Next, in the apps tabs, we can simulate a user swiping until
  38. // they come to the Settings app icon. Since the container view
  39. // is scrollable, we can use a UiScrollable object.
  40. UiScrollable appViews = new UiScrollable(new UiSelector().scrollable(true));
  41.  
  42. // Set the swiping mode to horizontal (the default is vertical)
  43. appViews.setAsHorizontalList();
  44.  
  45. // Create a UiSelector to find the Settings app and simulate
  46. // a user click to launch the app.
  47. UiObject settingsApp = appViews
  48. .getChildByText(new UiSelector()
  49. .className(android.widget.TextView.class.getName()),
  50. "Settings");
  51. settingsApp.clickAndWaitForNewWindow();
  52.  
  53. // Validate that the package name is the expected one
  54. UiObject settingsValidation = new UiObject(new UiSelector()
  55. .packageName("com.android.settings"));
  56. assertTrue("Unable to detect Settings", settingsValidation.exists());
  57. }
  58. }

You need to use Apache Ant to build and deploy the corresponding project.

  1. <android-sdk>/tools/android create uitest-project -n <name> -t 1 -p <path>
  2.  
  3. # build the test jar
  4. ant build
  5.  
  6. # push JAR to device
  7. ant push output.jar /data/local/tmp/
  8.  
  9. # Run the test
  10. adb shell uiautomator runtest LaunchSettings.jar -c com.uia.example.my.LaunchSettings

11.3. uiautomatorviewer

Android provides the uiautomatorviewer tool, which allows you to analyze the user interface of an application. You can use this tool to find the index, text or attribute of the application.

This tools allows non programmers to analyze an application and develop tests for it via the uiautomator library.

The tool is depicted in the following screenshot.

12. Monkey

Monkey is a command line tool which sends random events to your device. You can restrict Monkey to run only for a certain package and therefore instruct Monkey to test only your application.

For example the following will send 2000 random events to the application with the de.vogella.android.test.target package.

  1. adb shell monkey -p de.vogella.android.test.target -v 2000

Monkey sometimes causes problems with the adb server. Use the following commands to restart the adb server.

  1. adb kill-server
  2. adb start-server

You can use the -s [seed] parameter to ensure that the generated sequence of events is always the same.

For more info on Monkey please see Monkey description.

13. monkeyrunner

13.1. Testing with monkeyrunner

The monkeyrunner tool provides a Python API for writing programs that control an Android device or emulator from outside of Android code.

Via monkeyrunner you can complete script your test procedure. It run via the adb debug bright and allows you to install program, start them, control the flow and also take screenshots or your application.

To use monkeyrunner ensure that you have Python installed on your machine and in your path.

In monkeyrunner you have primary the following classes:

  • MonkeyRunner - allows to connect to devices

  • MonkeyDevice - allows to install and uninstall packages and to send keyboard and touch events to an application

  • MonkeyImage - allows to create screenshots, compare screenshots and save them

MonkeyImage can compare the screenshot with an existing image via the sameAs() method. A screenshot contains the Android notifcation bar, including time. You can enter a percentage as second parameter for sameAs() or use the getSubImage() method.

The API reference for monkeyrunner can be generated via the following command.

  1. # outfile is the path qualified name
  2. # of the output file
  3. monkeyrunner help.py help <outfile>

13.2. monkeyrunner example

Ensure Python is installed and in your path. Also ensure the [android-sdk]/tools folder is in your path. Create a file for example called testrunner.py

  1. from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
  2. import commands
  3. import sys
  4. import os
  5.  
  6. # starting the application and test
  7. print "Starting the monkeyrunner script"
  8.  
  9. if not os.path.exists("screenshots"):
  10. print "creating the screenshots directory"
  11. os.makedirs("screenshots")
  12.  
  13. # connection to the current device, and return a MonkeyDevice object
  14. device = MonkeyRunner.waitForConnection()
  15.  
  16. apk_path = device.shell('pm path com.vogella.android.test.simpleactivity')
  17. if apk_path.startswith('package:'):
  18. print "application installed."
  19. else:
  20. print "not installed, install APK"
  21. device.installPackage('com.vogella.android.test.simpleactivity.apk')
  22.  
  23. print "starting application...."
  24. device.startActivity(component='com.vogella.android.test.simpleactivity/[...CONTINUE]
  25. com.vogella.android.test.simpleactivity.MainActivity')
  26.  
  27. #screenshot
  28. MonkeyRunner.sleep(1)
  29. result = device.takeSnapshot()
  30. result.writeToFile('./screenshots/splash.png','png')
  31. print "screenshot taken and stored on device"
  32.  
  33. #sending an event which simulate a click on the menu button
  34. device.press('KEYCODE_MENU', MonkeyDevice.DOWN_AND_UP)
  35.  
  36. print "Finishing the test"

You run this test via the monkeyrunner testrunner.py on the console.

14. Common Android testing requires and solution approaches

14.1. Common logging on a server

Frequently the log files of the tests should be stored on a server and not on the device. A good practice it to provide a server backend and post the result via an HTTP request to this server. The server logs it centrally and provides central access to it.

14.2. Triggering system changes via tests

During tests you sometimes want to change the system status, e.g. turn WIFI of for example. This typically cannot be done via the test directly, as the test only has the permissions of the application under test.

A good practice is to install another application on the device which has the required permission and trigger it via an intent from the test.

15. Robotium

See Robotiumfor user interface testing with the Robotium framework.

16. Robolectric

16.1. Overview

Robolectric is a framework which mocks part of the Android framework contained in the android.jar file and which allows you to run Android tests directly on the JVM with the JUnit 4 framework.

If Robolectric implements a method is forwards these method calls to shadow Android objects which behave like the objects of the Android SDK. If not implemented they simply returns a default value, e.g. null or 0.

Setting up Robolectric requires the Robolectric and the JUnit 4 pars in the classpath. You also need to add the android.jar and maps.jar from your Android SDK installation directory to the classpath of the test project.

Details on using Robolectric can be found on its home page: Robolectric Homepage.

16.2. Functionality

Robolectric is designed to allow you to test Android applications on the JVM. This enables you to run your Android tests in your continuous integration environment without any additional setup.

Robolectric supports resource handling, e.g. inflation of views. You can also use the findViewById() to search in the a view.

16.3. Installation

You need to download the robolectric-X.X.X-jar-with-dependencies.jar from Roboelectric from Sonatype.

16.4. Example

Checkout the example project available at Github under the following URL: RobolectricSample sample project.

17. RoboGuice

17.1. RoboGuice

Roboguice is a dependency injection framework for Android. Using it can reduce significantly the amount of code you write. You find this framework under the following URL: Roboguice homepage..

17.2. RoboGuice and testing

Testing RoboGuice is well supported. See for example this Tutorialfor a detailed test description.

18. Thank you

Please help me to support this article:

19. Questions and Discussion

Before posting questions, please see the vogella FAQ. If you have questions or find an error in this article please use the www.vogella.com Google Group. I have created a short list how to create good questionswhich might also help you.

20. Links and Literature

20.1. Source Code

Source Code of Examples

20.3. vogella Resources

vogella TrainingAndroid and Eclipse Training from the vogella team

Android TutorialIntroduction to Android Programming

GWT TutorialProgram in Java and compile to JavaScript and HTML

Eclipse RCP TutorialCreate native applications in Java

JUnit TutorialTest your application

Git TutorialPut everything you have under distributed version control system

Android application testing with the Android test framework的更多相关文章

  1. android application plugins framework

    android插件式开发 android application plugins framework http://code.google.com/p/android-application-plug ...

  2. 【Android Api 翻译2】Android Testing(1) 浅尝Android测试的奥秘

    ------- 源自梦想.永远是你IT事业的好友.只是勇敢地说出我学到! ---------- 仅供学习和交流使用,翻译不好勿喷,请只摘除不合适的地方 Testing The Android fram ...

  3. 【Android Api 翻译1】Android Texting(2)Testing Fundamentals 测试基础篇

    Testing Fundamentals The Android testing framework, an integral part of the development environment, ...

  4. android application类的用法

    android application类的用法 Application是android系统Framework提供的一个组件,它是单例模式(singleton),即每个应用只有一个实例,用来存储系统的一 ...

  5. My First Android Application Project 第一个安卓应用

    一.前言: 安卓(Android):是一种基于Linux的自由及开放源代码的操作系统,主要用在移动设备上,如手机.平板电脑.其他的设备也有使用安卓操作系统,比如:电视机,游戏机.数码相机等等. 二.具 ...

  6. Failed to apply plugin [id 'com.android.application'] 和 Could not find com.android.tools.build:gradle:2.XX的最正确的解决方法

    发现android studio是真的可爱啊,上一秒还没问题可以build运行,下一秒就出错...好,你任性,你牛逼.. 说下今天又遇到的两个问题:Failed to apply plugin [id ...

  7. eclipse:File->New没有Android Application Project的解决办法

    我的Eclipse版本是:Kepler Service Release 1,截图: 解决步骤: 1.单击Window,选择Customize Perspective,如图: 2.勾选Android A ...

  8. Professional Android Application Development

    Professional Android Application Development 访问地址 http://docs.google.com/fileview?id=0ByVHV5sjM4fNNj ...

  9. Plugin with id 'com.android.application' not found.

    构建报错: Error:(1, 0) Plugin with id 'com.android.application' not found. <a href="openFile&quo ...

随机推荐

  1. 初识ambari

    本文地址:http://www.cnblogs.com/qiaoyihang/p/6290467.html 引用:http://blog.csdn.net/yeruby/article/details ...

  2. Digital Audio - Creating a WAV (RIFF) file

    Abstract:This tutorial covers the creation of a WAV (RIFF) audio file. It covers bit size, sample ra ...

  3. 94. Binary Tree Inorder Traversal(二叉树中序遍历)

      Given a binary tree, return the inorder traversal of its nodes' values. For example:Given binary t ...

  4. ActionScript和js交互

    新建的ActionScript项目,默认新建会在“默认包”中创建一个和项目名称相同以as结尾的文件,as项目开始执行时要new一个这样的类在类上方加入一些参数可以为生成的swf初始化一些样式 [SWF ...

  5. java zookeeper权限控制ACL(digest,IP)

    java zookeeper权限控制ACL(auth,digest,ip) 学习前请参考:https://www.cnblogs.com/zwcry/p/10407806.html zookeeper ...

  6. 利用C#查看特定服务是否安装

    需求:想通过C#代码来查看IIS服务或者MSMQ是否已经安装 分析:IIS服务和MSMQ安装完成后都会创建windows服务,所以我们只需要查看对应的服务是否存在即可. 准备工作: IIS服务名称:W ...

  7. 【Flask】Flask Restful api

    ### 安装: Flask-Restful需要在Flask 0.8以上的版本,在Python2.6或者Python3.3上运行.通过pip install flask-restful即可安装. ### ...

  8. Maven的Mirror和Repository

    今天新公司入职,项目经理让迁出项目,心想maven的阿里镜像源挺快的,干脆在配置了公司私服之后自己配置了阿里的镜像源,没成想项目屡屡报错,找不到项目依赖的公司jar包,后来才发现,同事配置mirror ...

  9. 项目中使用better-scroll实现移动端滚动,报错:Cannot read property 'children' of undefined better-scroll

    就是外面的盒子和要滚动的元素之间要有一层div, 插件挂载的元素是menuWrapper,可以滚动的元素是ul,在这两个元素之间加一个div元素即可解决问题.

  10. 【META http-equiv="Content-Type" Content="text/html; Charset=*】意义详解

    [META http-equiv="Content-Type" Content="text/html; Charset=*]意义详解 META,网页Html语言里Head ...