You should start writing and launching tests as part of your Android application development cycle. Well-written tests can help you find bugs earlier and give you confidence in your code.
A test case defines a collection of objects and methods used to launch various independent tests. Test cases can be organized into test suites and startup programming, with repeatable rules. The testing framework provides the means for test startup.
This tutorial will teach you how to use android’s custom testing framework (based on the popular Junit framework). You can write your test cases to verify the behavior specified in your application and to check consistency across different Android devices. Your test cases can also serve as internal code documents describing the expected behavior of application components.
course
-
- configurationYour test environment
- Learn how to create test projects.
- createAnd start a test case
- Learn how to write test cases to verify the Activity’s desired properties and use the andorID framework’s own
Instrumentation
Test the initiator to start it. - testUI components
- Learn how to test the behavior of specific UI components in your Activity.
- createUnit testing
- Learn how to perform unit tests to verify the behavior of a quarantined activity.
- Creating functional tests
- Learn how to perform functional tests to verify interactions between multiple activities.
Configure your test environment
Before you start writing and launching your tests, you should configure your test environment. This lesson teaches you how to configure Eclipse to write and launch tests, and how to build and launch tests using the Gradle framework from the command prompt line.
Note: To help you get started, this course is based on Eclipse and the ADT plug-in. However, for the sake of your personal testing environment, you are free to choose either the IDE or the command prompt.
Configure the Eclipse test environment
Eclipse and the ADT plug-in provide an integrated development environment that allows you to create, build, and launch graphical interfaces for test cases of Android applications. Eclipse provides a useful feature that automatically generates a suitable new test project for your Android application project. .
Configuration steps:
-
Download and install the ADT plugin if you haven’t already.
-
Import or create an Android project that you want to create.
-
To generate a test project that fits your project, you need to create (generate) a test project for your project:
- In the Package Explorer on the left, right-click your Project and choose Android Tools > New Test Project.
- In the Create Project dialog box (New Android Test Project), set the value of the corresponding property for your Project and click Finish.
You should now be able to create, build, and run test cases from your Eclipse environment. Read More about Creating and Running a Test Case.
Configure the test environment in command prompt mode
If you are using Gradle Version 1.6 or higher as your build environment, you can configure your test environment using Gradle Wrapper. Make sure that in your gradle.build file, the minSdkVersion property in defaultConfig is set to 8 or higher. You can refer to the sample sampleGradle.build file from the training course included in the download file.
Start the test using Gradle Wrapper:
-
Connect a physical device to your machine, or start an emulator.
-
In your project folder, execute the following command:
./gradlew build connectedCheck Copy the code
To learn more about using Gradle for Android testing, see the Gradle Plugin User Guide.
Using Command line tools other than Gradle for test development, see Testing from other IDEs
Creating and Running a Test Case
To verify that no fallback occurs in your layout design and underlying behavior, it is important to add test cases for each activity in your application. In each test, you need to create a unique part of each use case, including test fixtures, pre-prepared test methods, and Activity test methods (functions, methods). You can start your tests to get a test report. If some tests fail, this is an indication that there may be a defect in your code.
Note: In test-driven development (TDD), Equally important, instead of writing more or all of the program code and launching tests late in the development cycle, you can progressively write enough code to satisfy your needs and progressively update your test cases to reflect new functional needs, And iterate (iterate) this way.
Create a Test Case
Activity tests are written in a structured way. Be sure to place your tests in a separate package from the test code below.
In general, the package name of your tests should be similar to the package name of your application, with the suffix “.tests”. Add a Java class to the package you created. Often, your Test case is named after the class you want to Test, with the suffix “Test”.
To create test cases in Eclipse:
- In the Package Explorer, right-click on the
/src
directory for your test project and select New > Package. - Set the Name field to
<your_app_package_name>.tests
(for example,com.example.android.testingfun.tests
) and click Finish. - Right-click on the test package you created, and select New > Class.
- Set the Name field to
<your_app_activity_name>Test
(for example,MyFirstTestActivityTest
) and click Finish.
Set Up Your Test Fixture
A test fixture consists of many objects that must be initialized to start one or more tests. To setUp the test setUp, you can override the setUp() and tearDown() methods. The test launcher automatically runs the setUp() method before starting any other test methods and executes the tearDown() method after each method completes execution. You can use these two methods to initialize and clean up operations to distinguish them from other test methods.
To set up your test setup in Eclipse:
-
In the Package Explorer, double-click on the class of the test case you created last time to open the file in the Eclipse Java Editor, and modify your class so that it integrates with ActivityTestCase.
For example:
public class MyFirstTestActivityTest extends ActivityInstrumentationTestCase2<MyFirstTestActivity> { Copy the code
-
Go ahead, add the constructor and setUp() method, and add variable declarations for the Activity 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); }}Copy the code
The constructor will be called by the test initiator to initialize the test class, and setUp() will be called before any other test methods run.
Typically, in setUp(), you can:
-
Call the subclass’s construction for setUp(), which is required in JUnit. Invoke the superclass constructor for setUp(), which is required by JUnit. Initialize your test fixture state by: Initialize your test fixture state
- Defines the instance variable that stores the state of the test fixture.
- Create and store one that you want to test
Activity
A reference to an instance of. - Get the one you want to test
Activity
A variable reference to the UI component.
You can use the getActivity() method to get a reference to the Activity you want to test.
Add Test Preconditions
As a sanity check, it is a good practice to verify that the test fixture is properly configured and that the object you are testing is properly instantiated and initialized. You don’t want your test to fail because the test setup is incorrectly configured. In general, the name of the method used to verify the test device is testPreconditions();
For example, you might want to add a testPreconditons() method like this:
Public void testPreconditions() {assertNotNull(" mFirstTestActivity is NULL ", mFirstTestActivity); AssertNotNull (" mFirstTestText is null, "mFirstTestText); }Copy the code
The Assertion method comes from the JUnit Assert class. In general, you can use assertions to verify that a given expression is true.
- If the condition is false, the assertion method throws
AssertionFailedError
Exception, which is a typical report for testing an initiator. You can provide a string as the first argument to the assertion method to provide more detailed context information in the event of a failure. - If the condition is true, the test passes.
In both cases, the test initiator continues to execute the other test methods in the test case.
Add Test Methods to Verify Your Activity
Continuing, add one or more test methods to verify the Activity’s layout and functional behavior.
For example, if your Activity contains a TextView, you can add a test method to verify that its text (Lable) is correct, like this:
public void testMyFirstTestTextView_labelText() { final String expected = mFirstTestActivity.getString(R.string.my_first_test); final String actual = mFirstTestText.getText().toString(); assertEquals(expected, actual); }
Copy the code
The testMyFirstTestTextView_labelText() method simply checks whether the default text of the TextView set in the layout file matches the expected text defined in strings.xml.
Note: When you name a test method, you can use an underscore to distinguish between the object being tested and the situation being tested. This style makes it easier to see the specific objects being tested.
When performing such a string type comparison, it is a good practice to read it from your resource file instead of encoding it (written directly in code). This prevents your tests from being easily interrupted after you change to this.
To perform, pass in the expected and actual values of two strings as arguments to assertEquals(). If the values are different, the assertion will raise an AssertionFailedError exception.
If you add a testPreconditions() method, place other test methods after testPreconditions() in your code.
To live a complete test cases, please read MyFirstTestActivityTest. In the example Java.
Build and Run Your tests
You can easily build and launch your tests in EclipseYou’s Package Explorer.
To build and launch your tests:
- Connect your Android device to your machine (computer), and from the device or emulator, open the Settings menu, select Developer Mode, and make sure USB debug is turned on.
- In Project Explorer, right-click the Test class you just created and select Run As > Android Junit Test.
- In the Device selection dialog box, select the device you just created and click OK.
- In the JUnit View, verify that the test passed or failed.
For example, if there were no errors, the result would look something like this:
[Picture missing]
Testing UI Components
Typically, your Activity contains user interface components such as buttons, text boxes, check boxes, pickers, and so on. It allows users to interact with your Android application. This tutorial describes how to test a UI with simple buttons. You can use these general steps to test more complex types of UI components.
Note: The type of UI testing described in this lesson is called white-box testing, because you must use the application’s source code here. The Android Instrumentation Framework is suitable for creating white box tests within an application. Another alternative type is black box testing, where you don’t have access to the application source code. It can be useful in testing how programs interact with other programs or systems. We’re not going to do black box tests in this class. To learn more about black box Testing, read the UI Testing Guide.
To obtain the complete example, please read the sample code ClickFunActivityTest. Java
Use Instrumentation to create test cases for UI testing
When testing an Activity that contains a UI component, the Activity under test runs on a UI thread. However, the test application itself runs in another thread in the same process as the test application. This means that your test program can refer to a view object, but if it tries to change the properties of those objects or send events to the UI thread, you will usually receive a WrongThreadException error.
To safely inject Intent objects into your Activity, or execute test methods in the UI thread. You can inherit from ActivityInstrumentationTestCase2 class.
To learn more, read Testing on the UI Thread.
Set Up Your Test Fixture
When you setUp a test device for UI testing, you need to set touch mode to true in your setUp() method to prevent the UI control from only getting focus after you programmatically click it in the test method (e.g., A button will trigger its click listener). Make sure you call getActivity () before calling setActivityInitialTouchMode () method. .
Such as:
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); }}Copy the code
Add Test Methods to Validate UI Behavior
Your goals may include the following:
- When an Activity starts, verify that a button is displayed correctly.
- Verify that a TextView is initially hidden.
- When a button is pressed, verify that a TextView correctly displays the desired string.
The following demonstrates how to implement these methods
Verify Button Layout Parameters
You can add a test method to verify that the button is displayed correctly, like the following:
@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); }
Copy the code
When calling assertOnScreen(), you pass in the root view object and the view object you want to display on screen. If the desired view is not found in the root view, an AssertionFailedError exception is raised or the test passes.
You can also verify that the layout of the Button object is correct by getting a reference from its viewGroup.layoutParams object, and then calling the assertion method to verify that the width and height properties of the Button object are the expected values.
The @mediumTest annotation indicates how the test is grouped relative to its absolute runtime. To learn more about how to use Annotations for Test dimensions, read: Apply Test Annotations.
Verify TextView Layout Parameters
You can verify that a TextView is hidden when initialized like this:
@MediumTest public void testInfoTextView_layout() { final View decorView = mClickFunActivity.getWindow().getDecorView(); ViewAsserts.assertOnScreen(decorView, mInfoTextView); assertTrue(View.GONE == mInfoTextView.getVisibility()); }Copy the code
You can call the getDecorView() method to get a reference to the Activity’s decor view. This decorator view is the top-level ViewGroup (FrameLayout) object in the local inheritance hierarchy.
Verify Button Behavior
You can verify that a TextView becomes visible when a button is pressed, for example:
@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()); }
Copy the code
To program, click a button in the test, Call clickView().To programmatically click a Button in your test, call clickView(). You must pass in a reference to the test case that is being run and a reference to the Button to Manipulate.
Note: The TouchUtils helper class is a handy way to simulate touch interaction with applications. You can use these methods to simulate clicking, sliding, dragging and dropping view controls or screen behavior.
Warning: The TouchUtils method is designed to send events safely to the UI thread from the test thread. You cannot execute the TouchUtils method directly on the UI thread or on a method that uses the @uithRead. Annotation, which raises the WrongThreadException.
Using Apply Test Annotations
The following comments indicate the size of the test method:
-
@SmallTest
- Marks a test run in a small test.
@MediumTest
- Marks a test to run in intermediate tests.
@LargeTest
- Marks a test run against a larger test.
Typically, a SmallTest takes a few milliseconds and is labeled @smalltest. Longer ones (100 milliseconds or more) are usually labeled @mediumTest or @largeTests, depending on whether local resources are accessed or remote network resources are accessed. For more guidance on testing sizing annotations, see Android Tools Protip.
You can use other test annotations to mark your test methods and control how tests are organized and run. Extended reading: Annotation class.
Creating Unit Tests
A unit test of an Activity is a good way to verify the state of an Activity or its interaction with other independent components (that is, disconnected from the rest of the system). A unit test usually tests the smallest possible unit of code (possibly a method, class, component, etc.), independent of the system or resources played. For example, you can write a unit test to check that a acitivity has the correct layout or that it fires an Intent object correctly.
Unit testing is generally not appropriate for testing complex UI interaction events with the system. To do this, you can use the ActivityInstrumentationTestCase2 class, please refer to: Testing the UI Components.
This lesson shows how to write a unit test area to verify that an Intent is triggered to start another Activity. Since the test runs in a separate environment, the Intent is not actually delivered to the Android chest, but you can check that “the data loaded by the Intent object is correct.”
For a complete example, read the launchActivityTest.java in the sample code.
Note: You can inject mock objects into your unit tests by using mocking Objects in the Mocking Framework instead of system or external dependencies. To learn more about the simulation frameworks provided by Android, read Mock Object Classes.
Create a unit test to unit test the Activity
The ActivityUnitTestCase class provides isolated tests for individual activities. To create it, your test class needs to integrate from ActivityUnitTestCase.
A **Activity integrated with **ActivityUnitTestCase will not be automatically started by the Android Instrumentation framework. To start an Activity independently, you need to explicitly call the startActivity() method and pass in the Intent parameter to start your target Acitivity.
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); }}Copy the code
Verify the initiation of other Acitivity
The goals of your unit tests may include:
- Verify that when a button is pressed, an Intent starts a Acitivity.
- Verify that a started Activity loads the correct data.
To verify that an Intent is triggered when a button is pressed, use the getStartedActivityIntent() method. By using the assertion method, you can verify that the returned value is not empty and contains the desired string for the Activity to start. If both of these items are true, you have successfully verified that your Activity correctly sent an Intent.
For example, you can 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); }
Copy the code
Since LaunchActivity is launched independently, you cannot use the TouchUtils library to manipulate UI components. If you want to click a button, you can call the performClick() method.
Creating Functional Tests
Functional testing involves verifying that individual program components work as expected. For example, you can create a functional test to verify that an Activity correctly starts the target Activity when the user manipulates the interface.
To create functional test for your Activity, your test class must be inherited from ActivityInstrumentationTestCase2. Unlike ActivityUnitTestCase, in ActivityInstrumentationTestCase2 test can communication and the Android system, and can send the keyboard input events and UI view click event.
For a complete example, read senderActivityTest.java in the sample program.
Add Test Method to Validate Functional Behavior
The purpose of your functional test may include the following:
- Verify that the target Activity is started when a UI control is pressed in a sender Activity.
- The validation target Acitivyt displays the correct data based on what the user entered in the sender Activity.
You might implement your 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 ... }
Copy the code
The test waits for an Activity that matches the monitor, or returns NULL after a timeout. If the receiver Activity is started, the Activity monitor you just set up is hit. You can use the assertion method to verify that the recipient Activity was actually started and that the total number of hits in the ActivityMonitor increased to your desired number. .
Set up an ActivityMonitor
To monitor a separate Activity in your application summary, you can register an Activity monitor. Whenever an Activity that matches your criteria is started, the Activity monitor receives a system notification. If a match is reached, the total count for the monitor changes.
In general, you can use the Activity monitor like this:
- through
getInstrumentation()
Method to obtain a test instrument for your test scenario (Instrumentation
). - through
One of the Instrumentation
AddMonitor () method adds a test monitor (Instrumentation. ActivityMonitor) instance. Matching conditions can be specified through an Inent filter or a class name string.
- Awaiting designation
Activity
Be started. - Verification test monitor hit count increased.
- Remove the monitor.
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);
Copy the code
Send Keyboard Input Using Instrumentation
If your Activity has an EditText field, you might want to test whether the user can type content into the text box.
Usually to send strings in ActivityInstrumentationTestCase2 input values into a text box, you can:
-
Use the runOnMainSync() method to start the requestFocus() method to get focus for synchronous invocation in the message loop. In this way, the UI scene is blocked until focus is gained.
-
Call the waitForIdleSync() method and wait for the UI main thread to become idle. This way, there are no more events to handle.
-
Send a text string to the EditText by calling the sendStringSync() method and passing in your input string as an argument
For example:
// Send string input value
getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { senderMessageEditText.requestFocus(); } }); getInstrumentation().waitForIdleSync(); getInstrumentation().sendStringSync("Hello Android!"); getInstrumentation().waitForIdleSync();
Copy the code