From 2ef3952d8e62b71baca176b3e17315a37facd34a Mon Sep 17 00:00:00 2001 From: quddusc Date: Fri, 21 Jun 2013 16:49:46 -0700 Subject: cherrypick from jb-mr2-docs docs: Android training for Activity testing. Change-Id: I7167732c849d5a4a36c808cc852ddfcdc8e60bd7 Change-Id: Idce540108d048d76fc2c4bc37ecf2118b82588c5 --- docs/downloads/training/AndroidTestingFun.zip | Bin 0 -> 475029 bytes .../lesson2_MyFirstTestActivityTest_result.png | Bin 0 -> 12854 bytes .../activity-testing/activity-basic-testing.jd | 227 +++++++++++++++++++++ .../activity-functional-testing.jd | 166 +++++++++++++++ .../activity-testing/activity-ui-testing.jd | 216 ++++++++++++++++++++ .../activity-testing/activity-unit-testing.jd | 134 ++++++++++++ docs/html/training/activity-testing/index.jd | 68 ++++++ .../activity-testing/preparing-activity-testing.jd | 95 +++++++++ docs/html/training/testing.jd | 7 + docs/html/training/training_toc.cs | 39 ++++ 10 files changed, 952 insertions(+) create mode 100644 docs/downloads/training/AndroidTestingFun.zip create mode 100644 docs/html/images/training/lesson2_MyFirstTestActivityTest_result.png create mode 100644 docs/html/training/activity-testing/activity-basic-testing.jd create mode 100644 docs/html/training/activity-testing/activity-functional-testing.jd create mode 100644 docs/html/training/activity-testing/activity-ui-testing.jd create mode 100644 docs/html/training/activity-testing/activity-unit-testing.jd create mode 100644 docs/html/training/activity-testing/index.jd create mode 100644 docs/html/training/activity-testing/preparing-activity-testing.jd create mode 100644 docs/html/training/testing.jd diff --git a/docs/downloads/training/AndroidTestingFun.zip b/docs/downloads/training/AndroidTestingFun.zip new file mode 100644 index 000000000000..dca5812893df Binary files /dev/null and b/docs/downloads/training/AndroidTestingFun.zip differ diff --git a/docs/html/images/training/lesson2_MyFirstTestActivityTest_result.png b/docs/html/images/training/lesson2_MyFirstTestActivityTest_result.png new file mode 100644 index 000000000000..e0e869bcf132 Binary files /dev/null and b/docs/html/images/training/lesson2_MyFirstTestActivityTest_result.png differ diff --git a/docs/html/training/activity-testing/activity-basic-testing.jd b/docs/html/training/activity-testing/activity-basic-testing.jd new file mode 100644 index 000000000000..016289d94bdd --- /dev/null +++ b/docs/html/training/activity-testing/activity-basic-testing.jd @@ -0,0 +1,227 @@ +page.title=Creating and Running a Test Case +trainingnavtop=true + +@jd:body + + +
+ +
+

In order to verify that there are no regressions in the layout design and +functional behavior in your application, it's important to +create a test for each {@link android.app.Activity} in your application. For +each test, you need to create the individual parts of a test case, including +the test fixture, preconditions test method, and {@link android.app.Activity} +test methods. You can then run your test to get a test report. If any test +method fails, this might indicate a potential defect in your code.

+

Note: In the Test-Driven Development (TDD) +approach, instead of writing most or all of your app code up-front and then +running tests later in the development cycle, you would progressively write +just enough production code to satisfy your test dependencies, update your +test cases to reflect new functional requirements, and iterate repeatedly this +way.

+ +

Create a Test Case

+

{@link android.app.Activity} tests are written in a structured way. +Make sure to put your tests in a separate package, distinct from the code under +test.

+

By convention, your test package name should follow the same name as the +application package, suffixed with ".tests". In the test package +you created, add the Java class for your test case. By convention, your test case +name should also follow the same name as the Java or Android class that you +want to test, but suffixed with “Test”.

+

To create a new test case in Eclipse:

+
    +
  1. In the Package Explorer, right-click on the {@code /src} directory for +your test project and select New > Package.
  2. +
  3. Set the Name field to +{@code <your_app_package_name>.tests} (for example, +{@code com.example.android.testingfun.tests}) and click +Finish.
  4. +
  5. Right-click on the test package you created, and select +New > Class.
  6. +
  7. Set the Name field to +{@code <your_app_activity_name>Test} (for example, +{@code MyFirstTestActivityTest}) and click Finish.
  8. +
+ +

Set Up Your Test Fixture

+

A test fixture consists of objects that must be initialized for +running one or more tests. To set up the test fixture, you can override the +{@link junit.framework.TestCase#setUp()} and +{@link junit.framework.TestCase#tearDown()} methods in your test. The +test runner automatically runs {@link junit.framework.TestCase#setUp()} before +running any other test methods, and {@link junit.framework.TestCase#tearDown()} +at the end of each test method execution. You can use these methods to keep +the code for test initialization and clean up separate from the tests methods. +

+

To set up your test fixture in Eclipse:

+
    +
  1. In the Package Explorer, double-click on the test case that you created +earlier to bring up the Eclipse Java editor, then modify your test case class +to extend one of the sub-classes of {@link android.test.ActivityTestCase}. +

    For example:

    +
    +public class MyFirstTestActivityTest
    +        extends ActivityInstrumentationTestCase2<MyFirstTestActivity> {
    +
    +
  2. +
  3. Next, add the constructor and {@link junit.framework.TestCase#setUp()} +methods to your test case, and add variable declarations for the +{@link android.app.Activity} that you want to test.

    +

    For example:

    +
    +public class MyFirstTestActivityTest
    +        extends ActivityInstrumentationTestCase2<MyFirstTestActivity> {
    +
    +    private MyFirstTestActivity mFirstTestActivity;
    +    private TextView mFirstTestText;
    +
    +    public MyFirstTestActivityTest() {
    +        super(MyFirstTestActivity.class);
    +    }
    +
    +    @Override
    +    protected void setUp() throws Exception {
    +        super.setUp();
    +        mFirstTestActivity = getActivity();
    +        mFirstTestText =
    +                (TextView) mFirstTestActivity
    +                .findViewById(R.id.my_first_test_text_view);
    +    }
    +}
    +
    +

    The constructor is invoked by the test runner to instantiate the test +class, while the {@link junit.framework.TestCase#setUp()} method is invoked by +the test runner before it runs any tests in the test class.

    +
  4. +
+ +

Typically, in the {@link junit.framework.TestCase#setUp()} method, you +should:

+ + +

You can use the +{@link android.test.ActivityInstrumentationTestCase2#getActivity()} method to +get a reference to the {@link android.app.Activity} under test.

+ +

Add Test Preconditions

+

As a sanity check, it is good practice to verify that the test fixture has +been set up correctly, and the objects that you want to test have been correctly +instantiated or initialized. That way, you won’t have to see +tests failing because something was wrong with the setup of your test fixture. +By convention, the method for verifying your test fixture is called +{@code testPreconditions()}.

+ +

For example, you might want to add a {@code testPreconditons()} method like +this to your test case:

+ +
+public void testPreconditions() {
+    assertNotNull(“mFirstTestActivity is null”, mFirstTestActivity);
+    assertNotNull(“mFirstTestText is null”, mFirstTestText);
+}
+
+ +

The assertion methods are from the JUnit {@link junit.framework.Assert} +class. Generally, you can use assertions to +verify if a specific condition that you want to test is true. +

+

In both cases, the test runner proceeds to run the other test methods in the +test case.

+ +

Add Test Methods to Verify Your Activity

+

Next, add one or more test methods to verify the layout and functional +behavior of your {@link android.app.Activity}.

+

For example, if your {@link android.app.Activity} includes a +{@link android.widget.TextView}, you can add a test method like this to check +that it has the correct label text:

+
+public void testMyFirstTestTextView_labelText() {
+    final String expected =
+            mFirstTestActivity.getString(R.string.my_first_test);
+    final String actual = mFirstTestText.getText().toString();
+    assertEquals(expected, actual);
+}
+
+ +

The {@code testMyFirstTestTextView_labelText()} method simply checks that the +default text of the {@link android.widget.TextView} that is set by the layout +is the same as the expected text defined in the {@code strings.xml} resource.

+

Note: When naming test methods, you can use +an underscore to separate what is being tested from the specific case being +tested. This style makes it easier to see exactly what cases are being tested.

+

When doing this type of string value comparison, it’s good practice to read +the expected string from your resources, instead of hardcoding the string in +your comparison code. This prevents your test from easily breaking whenever the +string definitions are modified in the resource file.

+

To perform the comparison, pass both the expected and actual strings as +arguments to the +{@link junit.framework.Assert#assertEquals(java.lang.String, java.lang.String) assertEquals()} +method. If the values are not the same, the assertion will throw an +{@link junit.framework.AssertionFailedError} exception.

+

If you added a {@code testPreconditions()} method, put your test methods +after the {@code testPreconditions()} definition in your Java class.

+

For a complete test case example, take a look at +{@code MyFirstTestActivityTest.java} in the sample app.

+ +

Build and Run Your Test

+

You can build and run your test easily from the Package Explorer in +Eclipse.

+

To build and run your test:

+
    +
  1. Connect an Android device to your machine. On the device or emulator, open +the Settings menu, select Developer options +and make sure that USB debugging is enabled.
  2. +
  3. In the Project Explorer, right-click on the test class that you created +earlier and select Run As > Android Junit Test.
  4. +
  5. In the Android Device Chooser dialog, select the device that you just +connected, then click OK.
  6. +
  7. In the JUnit view, verify that the test passes with no errors or failures.
  8. +
+

For example, if the test case passes with no errors, the result should look +like this:

+ +

+ Figure 1. Result of a test with no errors. +

+ + + diff --git a/docs/html/training/activity-testing/activity-functional-testing.jd b/docs/html/training/activity-testing/activity-functional-testing.jd new file mode 100644 index 000000000000..7c8ff1d7bdd7 --- /dev/null +++ b/docs/html/training/activity-testing/activity-functional-testing.jd @@ -0,0 +1,166 @@ +page.title=Creating Functional Tests +trainingnavtop=true +@jd:body + + +
+
+ +

This lesson teaches you to

+
    +
  1. Add Test Method to Validate Functional Behavior +
      +
    1. Set Up an ActivityMonitor
    2. +
    3. Send Keyboard Input Using Instrumentation
    4. +
    +
  2. +
+ +

Try it out

+
+ Download the demo +

AndroidTestingFun.zip

+
+ +
+
+

Functional testing involves verifying that individual application +components work together as expected by the user. For example, you can create a +functional test to verify that an {@link android.app.Activity} correctly +launches a target {@link android.app.Activity} when the user performs a UI +interaction.

+ +

To create a functional test for your {@link android.app.Activity}, your test +class should extend {@link android.test.ActivityInstrumentationTestCase2}. +Unlike {@link android.test.ActivityUnitTestCase}, +tests in {@link android.test.ActivityInstrumentationTestCase2} can +communicate with the Android system and send keyboard input and click events to +the UI.

+ +

For a complete test case example, take a look at +{@code SenderActivityTest.java} in the sample app.

+ +

Add Test Method to Validate Functional Behavior

+

Your functional testing goals might include:

+ +

You might implement your test method like this:

+ +
+@MediumTest
+public void testSendMessageToReceiverActivity() {
+    final Button sendToReceiverButton = (Button) 
+            mSenderActivity.findViewById(R.id.send_message_button);
+
+    final EditText senderMessageEditText = (EditText) 
+            mSenderActivity.findViewById(R.id.message_input_edit_text);
+
+    // Set up an ActivityMonitor
+    ...
+
+    // Send string input value
+    ...
+
+    // Validate that ReceiverActivity is started
+    ...
+
+    // Validate that ReceiverActivity has the correct data
+    ...
+
+    // Remove the ActivityMonitor
+    ...
+}
+
+

The test waits for an {@link android.app.Activity} that matches this monitor, +otherwise returns null after a timeout elapses. If {@code ReceiverActivity} was +started, the {@link android.app.Instrumentation.ActivityMonitor ActivityMonitor} +that you set +up earlier receives a hit. You can use the assertion methods to verify that +the {@code ReceiverActivity} is indeed started, and that the hit count on the +{@link android.app.Instrumentation.ActivityMonitor ActivityMonitor} incremented +as expected.

+ +

Set up an ActivityMonitor

+

To monitor a single {@link android.app.Activity} in your application, you +can register an {@link android.app.Instrumentation.ActivityMonitor ActivityMonitor}. +The {@link android.app.Instrumentation.ActivityMonitor ActivityMonitor} is +notified by the system whenever an {@link android.app.Activity} that matches your criteria is started. +If a match is found, the monitor’s hit count is updated.

+

Generally, to use an +{@link android.app.Instrumentation.ActivityMonitor ActivityMonitor}, you should:

+
    +
  1. Retrieve the {@link android.app.Instrumentation} instance for your test +case by using the +{@link android.test.InstrumentationTestCase#getInstrumentation()} method.
  2. +
  3. Add an instance of {@link android.app.Instrumentation.ActivityMonitor} to +the current instrumentation using one of the {@link android.app.Instrumentation} +{@code addMonitor()} methods. The match criteria can be specified as an +{@link android.content.IntentFilter} or a class name string.
  4. +
  5. Wait for the {@link android.app.Activity} to start.
  6. +
  7. Verify that the monitor hits were incremented.
  8. +
  9. Remove the monitor.
  10. +
+

For example:

+
+// Set up an ActivityMonitor
+ActivityMonitor receiverActivityMonitor =
+        getInstrumentation().addMonitor(ReceiverActivity.class.getName(),
+        null, false);
+
+// Validate that ReceiverActivity is started
+TouchUtils.clickView(this, sendToReceiverButton);
+ReceiverActivity receiverActivity = (ReceiverActivity) 
+        receiverActivityMonitor.waitForActivityWithTimeout(TIMEOUT_IN_MS);
+assertNotNull("ReceiverActivity is null", receiverActivity);
+assertEquals("Monitor for ReceiverActivity has not been called",
+        1, receiverActivityMonitor.getHits());
+assertEquals("Activity is of wrong type",
+        ReceiverActivity.class, receiverActivity.getClass());
+
+// Remove the ActivityMonitor
+getInstrumentation().removeMonitor(receiverActivityMonitor);
+
+ +

Send Keyboard Input Using Instrumentation

+

If your {@link android.app.Activity} has an {@link android.widget.EditText} +field, you might want to test that users can enter values into the +{@link android.widget.EditText} object.

+

Generally, to send a string input value to an {@link android.widget.EditText} +object in {@link android.test.ActivityInstrumentationTestCase2}, you should:

+
    +
  1. Use the {@link android.app.Instrumentation#runOnMainSync(java.lang.Runnable) runOnMainSync()} +method to run the {@link android.view.View#requestFocus()} call synchronously +in a loop. This way, the UI thread is blocked until focus is received.
  2. +
  3. Call {@link android.app.Instrumentation#waitForIdleSync()} method to wait +for the main thread to become idle (that is, have no more events to process).
  4. +
  5. Send a text string to the {@link android.widget.EditText} by calling +{@link android.app.Instrumentation#sendStringSync(java.lang.String) +sendStringSync()} and pass your input string as the parameter.

    +
+

For example:

+
+// Send string input value
+getInstrumentation().runOnMainSync(new Runnable() {
+    @Override
+    public void run() {
+        senderMessageEditText.requestFocus();
+    }
+});
+getInstrumentation().waitForIdleSync();
+getInstrumentation().sendStringSync("Hello Android!");
+getInstrumentation().waitForIdleSync();
+
+ + + + + + + + diff --git a/docs/html/training/activity-testing/activity-ui-testing.jd b/docs/html/training/activity-testing/activity-ui-testing.jd new file mode 100644 index 000000000000..644f3ca51513 --- /dev/null +++ b/docs/html/training/activity-testing/activity-ui-testing.jd @@ -0,0 +1,216 @@ +page.title=Testing UI Components +trainingnavtop=true + +@jd:body + + +
+ +
+ +

Typically, your {@link android.app.Activity} includes user interface +components (such as buttons, editable text fields, checkboxes, and pickers) to +allow users to interact with your Android application. This lesson shows how +you can test an {@link android.app.Activity} with a simple push-button UI. You +can use the same general steps to test other, more sophisticated types of UI +components.

+ +

Note: The type of UI testing in this lesson is +called white-box testing because you have the +source code for the application that you want to test. The Android +Instrumentation +framework is suitable for creating white-box tests for UI components within an +application. An alternative type of UI testing is black-box testing, +where you may not have access to the application source. This type of testing +is useful when you want to test how your app interacts with other apps or with +the system. Black-box testing is not covered in this training. To learn more +about how to perform black-box testing on your Android apps, see the +UI Testing guide. +

For a complete test case example, take a look at +{@code ClickFunActivityTest.java} in the sample app.

+ +

Create a Test Case for UI Testing with Instrumentation

+

When testing an {@link android.app.Activity} that has a user interface (UI), +the {@link android.app.Activity} under test runs in the UI thread. However, the +test application itself runs in a separate thread in the same process as the +application under test. This means that your test app can reference objects +from the UI thread, but if it attempts to change properties on those objects or +send events to the UI thread, you will usually get a {@code WrongThreadException} +error.

+

To safely inject {@link android.content.Intent} objects into your +{@link android.app.Activity} or run test methods on the UI thread, you can +extend your test class to use {@link android.test.ActivityInstrumentationTestCase2}. +To learn more about how to run test methods on the UI thread, see +Testing +on the UI thread.

+ +

Set Up Your Test Fixture

+

When setting up the test fixture for UI testing, you should specify the +touch mode +in your {@link junit.framework.TestCase#setUp()} method. Setting the touch mode +to {@code true} prevents the UI control from taking focus when you click it +programmatically in the test method later (for example, a button UI will just +fire its on-click listener). Make sure that you call +{@link android.test.ActivityInstrumentationTestCase2#setActivityInitialTouchMode(boolean) setActivityInitialTouchMode()} +before calling {@link android.test.ActivityInstrumentationTestCase2#getActivity()}. +

+

For example: +

+public class ClickFunActivityTest
+        extends ActivityInstrumentationTestCase2 {
+    ...
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        setActivityInitialTouchMode(true);
+
+        mClickFunActivity = getActivity();
+        mClickMeButton = (Button) 
+                mClickFunActivity
+                .findViewById(R.id.launch_next_activity_button);
+        mInfoTextView = (TextView) 
+                mClickFunActivity.findViewById(R.id.info_text_view);
+    }
+}
+
+ +

Add Test Methods to Validate UI Behavior

+

Your UI testing goals might include:

+ +

The following section demonstrates how you can implement test methods +to perform these verifications.

+ +

Verify Button Layout Parameters

+

You might add a test method like this to verify that a button is displayed +correctly in your {@link android.app.Activity}:

+
+@MediumTest
+public void testClickMeButton_layout() {
+    final View decorView = mClickFunActivity.getWindow().getDecorView();
+
+    ViewAsserts.assertOnScreen(decorView, mClickMeButton);
+
+    final ViewGroup.LayoutParams layoutParams =
+            mClickMeButton.getLayoutParams();
+    assertNotNull(layoutParams);
+    assertEquals(layoutParams.width, WindowManager.LayoutParams.MATCH_PARENT);
+    assertEquals(layoutParams.height, WindowManager.LayoutParams.WRAP_CONTENT);
+}
+
+ +

In the {@link android.test.ViewAsserts#assertOnScreen(android.view.View,android.view.View) assertOnScreen()} +method call, you should pass in the root view and the view that you are +expecting to be present on the screen. If the expected view is not found in the +root view, the assertion method throws an {@link junit.framework.AssertionFailedError} +exception, otherwise the test passes.

+

You can also verify that the layout of a {@link android.widget.Button} is +correct by getting a reference to its {@link android.view.ViewGroup.LayoutParams} +object, then call assertion methods to verify that the +{@link android.widget.Button} object's width and height attributes match the +expected values.

+

The {@code @MediumTest} annotation specifies how the test is categorized, +relative to its absolute execution time. To learn more about using test size +annotations, see Apply Test Annotations.

+ +

Verify TextView Layout Parameters

+

You might add a test method like this to verify that a +{@link android.widget.TextView} initially appears hidden in +your {@link android.app.Activity}:

+
+@MediumTest
+public void testInfoTextView_layout() {
+    final View decorView = mClickFunActivity.getWindow().getDecorView();
+    ViewAsserts.assertOnScreen(decorView, mInfoTextView);
+    assertTrue(View.GONE == mInfoTextView.getVisibility());
+}
+
+

You can call {@link android.view.Window#getDecorView()} to get a reference +to the decor view for the {@link android.app.Activity}. The decor view is the +top-level ViewGroup ({@link android.widget.FrameLayout}) view in the layout +hierarchy.

+ +

Verify Button Behavior

+

You can use a test method like this to verify that a +{@link android.widget.TextView} becomes visible when a +{@link android.widget.Button} is pushed:

+ +
+@MediumTest
+public void testClickMeButton_clickButtonAndExpectInfoText() {
+    String expectedInfoText = mClickFunActivity.getString(R.string.info_text);
+    TouchUtils.clickView(this, mClickMeButton);
+    assertTrue(View.VISIBLE == mInfoTextView.getVisibility());
+    assertEquals(expectedInfoText, mInfoTextView.getText());
+}
+
+ +

To programmatically click a {@link android.widget.Button} in your +test, call {@link android.test.TouchUtils#clickView(android.test.InstrumentationTestCase,android.view.View) clickView()}. +You must pass in a reference to the test case that is being run and a reference +to the {@link android.widget.Button} to manipulate.

+ +

Note: The {@link android.test.TouchUtils} +helper class provides convenience methods for simulating touch interactions +with your application. You can use these methods to simulate clicking, tapping, +and dragging of Views or the application screen.

+

Caution: The {@link android.test.TouchUtils} +methods are designed to send events to the UI thread safely from the test thread. +You should not run {@link android.test.TouchUtils} directly in the UI thread or +any test method annotated with {@code @UIThread}. Doing so might +raise the {@code WrongThreadException}.

+ +

Apply Test Annotations

+

The following annotations can be applied to indicate the size of a test +method:

+
+
{@link +android.test.suitebuilder.annotation.SmallTest @SmallTest}
+
Marks a test that should run as part of the small tests.
+
{@link +android.test.suitebuilder.annotation.MediumTest @MediumTest}
+
Marks a test that should run as part of the medium tests.
+
{@link android.test.suitebuilder.annotation.LargeTest @LargeTest}
+
Marks a test that should run as part of the large tests.
+
+

Typically, a short running test that take only a few milliseconds should be +marked as a {@code @SmallTest}. Longer running tests (100 milliseconds or +more) are usually marked as {@code @MediumTest}s or {@code @LargeTest}s, +depending on whether the test accesses resources on the local system only or +remote resources over a network. For guidance on using test size annotations, +see this Android Tools Protip.

+

You can mark up your test methods with other test annotations to control +how the tests are organized and run. For more information on other annotations, +see the {@link java.lang.annotation.Annotation} class reference.

+ + + + diff --git a/docs/html/training/activity-testing/activity-unit-testing.jd b/docs/html/training/activity-testing/activity-unit-testing.jd new file mode 100644 index 000000000000..74dcda90b18d --- /dev/null +++ b/docs/html/training/activity-testing/activity-unit-testing.jd @@ -0,0 +1,134 @@ +page.title=Creating Unit Tests +trainingnavtop=true +@jd:body + + +
+
+ +

This lesson teaches you to

+
    +
  1. Create a Test Case for Activity Unit Testing +
  2. Validate Launch of Another Activity +
+ +

Try it out

+
+ Download the demo +

AndroidTestingFun.zip

+
+ +
+
+ +

An {@link android.app.Activity} unit test is an excellent way to quickly +verify the state of an {@link android.app.Activity} and its interactions with +other components in isolation (that is, disconnected from the rest of the +system). A unit test generally tests the smallest possible unit of code +(which could be a method, class, or component), without dependencies on system +or network resources. For example, you can write a unit test to check +that an {@link android.app.Activity} has the correct layout or that it +triggers an {@link android.content.Intent} object correctly.

+

Unit tests are generally not suitable for testing complex UI interaction +events with the system. Instead, you should use +the {@link android.test.ActivityInstrumentationTestCase2} class, as described +in Testing UI Components.

+

This lesson shows how you can write a unit test to verify that an +{@link android.content.Intent} is triggered to launch another +{@link android.app.Activity}. +Since the test runs in an isolated environment, the +{@link android.content.Intent} +is not actually sent to the Android system, but you can inspect that the +{@link android.content.Intent} object's payload data is accurate.

+

For a complete test case example, take a look at +{@code LaunchActivityTest.java} in the sample app.

+ +

Note: To test against system or external +dependencies, you can use mock objects from a mocking +framework and inject them into your unit tests. To learn more about the mocking +framework provided by Android, see +Mock +Object Classes.

+ +

Create a Test Case for Activity Unit Testing

+

The {@link android.test.ActivityUnitTestCase} class provides support for +isolated testing of a single {@link android.app.Activity}. To create a unit +test for your {@link android.app.Activity}, your test class should extend +{@link android.test.ActivityUnitTestCase}.

+ +

The {@link android.app.Activity} in an {@link android.test.ActivityUnitTestCase} +is not automatically started by Android Instrumentation. To start the +{@link android.app.Activity} in isolation, you need to explicitly call the +{@link android.test.ActivityUnitTestCase#startActivity(android.content.Intent, android.os.Bundle, java.lang.Object) startActivity()} +method, and pass in the {@link android.content.Intent} to +launch your target {@link android.app.Activity}.

+ +

For example:

+
+public class LaunchActivityTest
+        extends ActivityUnitTestCase<LaunchActivity> {
+    ...
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mLaunchIntent = new Intent(getInstrumentation()
+                .getTargetContext(), LaunchActivity.class);
+        startActivity(mLaunchIntent, null, null);
+        final Button launchNextButton =
+                (Button) getActivity()
+                .findViewById(R.id.launch_next_activity_button);
+    }
+}
+
+ +

Validate Launch of Another Activity

+

Your unit testing goals might include:

+ + +

To verify if an {@link android.content.Intent} was triggered +following the {@link android.widget.Button} click, you can use the +{@link android.test.ActivityUnitTestCase#getStartedActivityIntent()} method. +By using assertion methods, you can verify that the returned +{@link android.content.Intent} is not null, and that it contains the expected +string value to launch the next {@link android.app.Activity}. If both assertions +evaluate to {@code true}, you've successfully verified that the +{@link android.content.Intent} was correctly sent by your +{@link android.app.Activity}.

+ +

You might implement your test method like this:

+
+@MediumTest
+public void testNextActivityWasLaunchedWithIntent() {
+    startActivity(mLaunchIntent, null, null);
+    final Button launchNextButton =
+            (Button) getActivity()
+            .findViewById(R.id.launch_next_activity_button);
+    launchNextButton.performClick();
+
+    final Intent launchIntent = getStartedActivityIntent();
+    assertNotNull("Intent was null", launchIntent);
+    assertTrue(isFinishCalled());
+
+    final String payload =
+            launchIntent.getStringExtra(NextActivity.EXTRAS_PAYLOAD_KEY);
+    assertEquals("Payload is empty", LaunchActivity.STRING_PAYLOAD, payload);
+}
+
+

Because {@code LaunchActivity} runs in isolation, you cannot use the +{@link android.test.TouchUtils} library to manipulate UI controls. To directly +click a {@link android.widget.Button}, you can call the +{@link android.view.View#performClick()} method instead.

+ + + + + + + diff --git a/docs/html/training/activity-testing/index.jd b/docs/html/training/activity-testing/index.jd new file mode 100644 index 000000000000..ddede712d83e --- /dev/null +++ b/docs/html/training/activity-testing/index.jd @@ -0,0 +1,68 @@ +page.title=Testing Your Android Activity +page.tags="testing" + +trainingnavtop=true +startpage=true + +@jd:body + +
+
+ + +

Dependencies and prerequisites

+
    +
  • Android 2.2 (API Level 8) or higher.
  • +
+ +

You Should Also Read

+ + +
+
+ +

You should be writing and running tests as part of your Android application +development cycle. Well-written tests can help you to catch bugs early in +development and give you confidence in your code.

+ +

A test case defines a set of objects and methods to run multiple +tests independently from each other. Test cases can be organized into +test suites and run programmatically, in a repeatable manner, with +a test runner provided by a testing framework.

+ +

The lessons in this class teaches you how to use the Android's custom +testing framework that is based on the popular JUnit framework. You can +write test cases to verify specific behavior in your application, and check for +consistency across different Android devices. Your test cases also serve as a +form of internal code documentation by describing the expected behavior of +app components.

+ +

Lessons

+ + + +
+
Setting Up Your Test +Environment
+
Learn how to create your test project.
+
Creating and Running a Test +Case
+
Learn how to write test cases to verify the +expected properties of your {@link android.app.Activity}, and run the test +cases with the {@code Instrumentation} test runner provided by the Android +framework.
+
Testing UI Components
+
Learn how to test the behavior of specific UI +components in your {@link android.app.Activity}.
+
Creating Unit Tests
+
Learn how to how to perform unit testing to +verify the behavior of an Activity in isolation.
+
Creating Functional Tests
+
Learn how to perform functional testing to +verify the interaction of multiple Activities.
+ diff --git a/docs/html/training/activity-testing/preparing-activity-testing.jd b/docs/html/training/activity-testing/preparing-activity-testing.jd new file mode 100644 index 000000000000..c43c9ed4a304 --- /dev/null +++ b/docs/html/training/activity-testing/preparing-activity-testing.jd @@ -0,0 +1,95 @@ +page.title=Setting Up Your Test Environment +trainingnavtop=true + +@jd:body + + +
+
+ +

This lesson teaches you to

+
    +
  1. Set Up Eclipse for Testing
  2. +
  3. Set Up the Command Line Interface for Testing
  4. +
+ +

You should also read

+ + +

Try it out

+
+ Download the demo +

AndroidTestingFun.zip

+
+ +
+
+ +

Before you start writing and running your tests, you should set up your test +development environment. This lesson teaches you how to set up the Eclipse +IDE to build and run tests, and how to +build and run tests with the Gradle framework by using the command line +interface.

+ +

Note: To help you get started, the lessons are +based on Eclipse with the ADT plugin. However, for your own test development, you +are free to use the IDE of your choice or the command-line.

+ +

Set Up Eclipse for Testing

+

Eclipse with the Android Developer Tools (ADT) plugin provides an integrated +development environment for you to create, build, and run Android application +test cases from a graphical user interface (GUI). A convenient feature that +Eclipse provides is the ability to auto-generate a new test project that +corresponds with your Android application project. + +

To set up your test environment in Eclipse:

+ +
    +
  1. Download and install the +Eclipse ADT plugin, if you haven’t installed it yet.
  2. +
  3. Import or create the Android application project that you want to test +against.
  4. +
  5. Generate a test project that corresponds to the application project under +test. To generate a test project for the app project that you imported:

    +
      +
    1. In the Package Explorer, right-click on your app project, then +select Android Tools > New Test Project.
    2. +
    3. In the New Android Test Project wizard, set the property +values for your test project then click Finish.
    4. +
    +
  6. +
+

You should now be able to create, build, and run test +cases from your Eclipse environment. To learn how to perform these tasks in +Eclipse, proceed to Creating and Running +a Test Case.

+ +

Set Up the Command Line Interface for Testing

+

If you are using Gradle version 1.6 or higher as your build environment, you +can build and run your Android application tests from the command line by using +the Gradle Wrapper. Make sure that in your {@code gradle.build} file, the +minSdkVersion +attribute in the {@code defaultConfig} section is set to 8 or higher. You can +refer to the sample {@code gradle.build} file that is +included in the download bundle for this training class.

+

To run your tests with the Gradle Wrapper:

+
    +
  1. Connect a physical Android device to your machine or launch the Android +Emulator.
  2. +
  3. Run the following command from your project directory: +
    ./gradlew build connectedCheck
    +
  4. +
+

To learn more about using Gradle for Android testing, see the +Gradle Plugin User Guide.

+

To learn more about using command line tools other than Gradle for test +development, see +Testing from Other IDEs.

+ diff --git a/docs/html/training/testing.jd b/docs/html/training/testing.jd new file mode 100644 index 000000000000..c55370db0b0f --- /dev/null +++ b/docs/html/training/testing.jd @@ -0,0 +1,7 @@ +page.title=Best Practices for Testing +page.trainingcourse=true + +@jd:body + +

These classes and articles provide information about how to +test your Android application.

diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs index 40c170edd845..b884620916cf 100644 --- a/docs/html/training/training_toc.cs +++ b/docs/html/training/training_toc.cs @@ -1205,6 +1205,45 @@ include the action bar on devices running Android 2.1 or higher." + +