Performing Automated Testing

Collecting application information and building automated tests can help you build a better, more bulletproof application. The Android SDK provides a number of packages related to code diagnostics. Application diagnostics fall into two categories:

► Logging application information for performance or usage statistics

► Automated test suites based on the JUnit framework

Logging Application Information

At the beginning of this book, you learned how to leverage the built-in logging class Log (android.util.Log) to implement different levels of diagnostic logging. You can monitor the output of log information from within Eclipse or by using the LogCat utility provided with the Android SDK.

Don't forget to strip any diagnostic information, such as logging information, from the application before publication. Logging information and diagnostics can negatively affect application performance.

Automated Testing with JUnit and Eclipse

The Android SDK includes extensions to the JUnit framework for testing Android applications. Automated testing is accomplished by creating test cases, in Java code, that verify that the application works the way you designed it. This automated testing can be done for both unit testing and functional testing, including user interface testing.

This discussion is not meant to provide full documentation for writing JUnit test cases. For that, look to online resources, such as http://www.junit.org, or books on the subject.

Did you Know?

Some people follow a paradigm of creating the test cases first, and then writing code that causes the test cases to pass. This method can work well in an environment where all application results and behavior are known before coding begins and will change little or not at all.

Automated testing for Android involves just a few straightforward steps:

1. Create a test project.

2. Add test cases to the new project.

3. Run the test project.

The following sections walk you through how to perform each of these steps to test a specific feature of the Been There, Done That! settings screen.

Creating the Test Project

Recall from Hour 1, "Getting Started with Android," when you first created a project using Eclipse, that the wizard has an option for creating a test project. You're now going to leverage that option to get up and running quickly with creating test cases.

Conveniently, the option for creating a test project is also available after a project already exists. To create a test project for an existing Android project in Eclipse, follow these steps:

1. Choose File, New, Project.

2. Under the Android option, choose Android Test Project.

3. In the section labeled Test Target, choose An Existing Android Project and click the Browse button.

4. Find the project you want to test and select it. The wizard fills in the rest of the fields with reasonable default values, as shown in Figure 22.2.

FIGURE 22.2

Test Application Project Wizard defaults in Eclipse.

5. Click Finish. Your new test project is created.

Creating a Test Case

When you have your test project in place, you can write test cases. You will now create a test case that tests the behavior of the Nickname field of the settings screen controlled by the QuizSettingsActivity class. To do this, first follow these steps to create the empty test case file:

1. Right-click the package name within the src folder of your test project.

2. Choose New, JUnit Test Case.

3. Modify the Name field to say QuizSettingsActivityTests.

4. Modify the Superclass field to say android.test.ActivityInstrumentation TestCase2<QuizSettingsActivity>. (Ignore the warning that says "Superclass does not exist.")

5. Modify Class Under Test to say com.androidbook.triviaquiz22. QuizSettingsActivity.

6. Click Finish.

7. In the newly created file, manually add an import statement for QuizSettingsActivity (or organize your imports).

8. Finally, add the following constructor to the newly created class:

public QuizSettingsActivityTests() {

super("com.androidbook.triviaquiz22", QuizSettingsActivity.class);

Now that your test case file is ready, you can test the Nickname field and make sure it matches the value of the nickname in SharedPreferences and that it updates after a new string is entered. You first need to modify the setUp() method to perform some common behavior. You get the nickname EditText object for use in the other two tests. The following code does just that: @Override protected void setUp() throws Exception { super.setUp();

final QuizSettingsActivity settingsActivity = getActivity(); nickname =

(EditText) settingsActivity.findViewById(R.id.EditText_Nickname);

The method call for getActivity() retrieves the activity being tested. Within the ActivityInstrumentationTestCase2 class, the activity is created as it would normally be when the activity is launched.

Normally, you would also override the tearDown() method. However, for these tests, you have no lingering items that need to be cleaned up.

JUnit tests must begin with the word test. So, to write specific tests, you need to create methods that begin with the word test, followed by what you are testing. First, make sure the displayed Nickname field is consistent with the stored value in SharedPreferences. Add the following code to QuizSettingsActivityTests to implement this test:

public void testNicknameFieldConsistency() { SharedPreferences settings =

getActivity().getSharedPreferences(QuizActivity. GAME_PREFERENCES, Context. MODE_PRIVATE); String fromPrefs =

settings.getString(QuizActivity.GAME_PREFERENCES_NICKNAME, ""); String fromField = nickname.getText().toString(); assertTrue("Field should equal prefs value", fromPrefs.equals(fromField));

The first few lines are all standard Android code that you should be familiar with. By using the Android testing framework, you are enabling using the various Android objects within the testing code. The last line, however, is where the real test is performed. The assertTrue() method verifies that the second parameter actually is true. If it's not, the string is output in the results. In this case, the two strings are compared. They should be equal.

The next test is to verify that editing the field actually updates the Shared Preferences value. Add the following code to QuizSettingsActivity to test that this is true:

private static final String TESTNICK_KEY_PRESSES = "T E S T N I C K ENTER"; // ...

public void testUpdateNickname() { Log. w(DEBUG_TAG, "Warning: " +

"If nickname was previously 'testnick' this test is invalid."); getActivity().runOnUiThread(new Runnable() { public void run() {

nickname.setText(""); nickname.requestFocus();

sendKeys(TESTNICK_KEY_PRESSES); SharedPreferences settings =

getActivity().getSharedPreferences(QuizActivity.GAME_PREFERENCES, Context. MODE_PRIVATE); String fromPrefs =

settings.getString(QuizActivity.GAME_PREFERENCES_NICKNAME, ""); assertTrue("Prefs should be testnick", fromPrefs .equalsIgnoreCase("testnick"));

As before, most of this is standard Android code that you should be familiar with. However, notice that this code is performing a couple calls on the UI thread. This is required for these particular calls; if you remove those calls from the UI thread, the test case fails.

To run an entire test method on the UI thread, add the @UiThreadTest annotation before your method implementation. But note that this won't work in the example shown here because the sendKeys() method can't be run on the main thread. (You get the "This method cannot be called from the main application thread" exception error.) Instead, just portions of the test can be run on the UI thread, as shown.

Running Automated Tests

Now that your tests are written, you need to run them to test your code. There are two ways of doing this. The first method is the most straightforward and provides easy-to-read results right in Eclipse: You simply select Debug, Debug As, Android JUnit Test. The Console view of Eclipse shows the typical installation progress for both the test application and the application being tested (see Figure 22.3).

FIGURE 22.3

Eclipse console output while running JUnit tests on Android.

If the test project is not selected, Eclipse may try to run a regular application as a JUnit test application, resulting in a bunch of warnings and errors. To avoid this problem, right-click on the project name in the Package Explorer pane of Eclipse, choose Debug As, and then choose Android JUnit Test. Alternately, you can go to the Debug Configurations menu, double-click on Android JUnit Test to create a new test configuration, and then fill in the details.

With the LogCat view, you see the normal Android debug output as well as new output for the tests that are performed. In this way, you can better debug problems or errors that result from failures, or even find new failures that should be tested for.

The JUnit view, though, may be the most useful. It summarizes all the tests run and how long each one takes, and it includes a stack trace for any failures found. Figure 22.4 shows what this looks like in Eclipse.

FIGURE 22.4

Eclipse JUnit view running Android tests.

FIGURE 22.4

Eclipse JUnit view running Android tests.

The second way of running the tests is available only in the emulator. To use this method, launch the Dev Tools app and then choose Instrumentation. If you've followed along and don't have any other tests installed, you'll likely see android.test.InstrumentationTestRunner as the only item shown. Clicking this launches the tests. When you use this method, the only way to see results (other than a visual indication during user interface tests) is to watch the LogCat output.

The description of the item in the list can be changed. In the AndroidManifest.xml file of the test app, in the instrumentation section, modify it to read as follows:

instrumentation android:targetPackage="com.androidbook.triviaquiz22' android:name="android.test.InstrumentationTestRunner" android:label="TriviaQuiz22 Tests" />

Now when you launch Dev Tools and go to the Instrumentation section, you see the text of the label rather than the name.

Adding More Tests

Now you have all the tools you need to add more unit tests to your application. The Android SDK includes a variety of classes that can be implemented for performing a wide range of tests specific to Android. Among these are the following:

► ActivityUnitTestCase—Similar to the example testing in the preceding section in that it tests on Activity, but at a lower level. This class can be used to unit test specific aspects of an activity, such as how it handles onPause(), when it has called onFinished(), and so on. This is a great way to test the life cycle of an activity.

► ApplicationTestCase—Like ActivityUnitTestCase, this class allows testing of Application classes in a fully controlled environment.

► ProviderTestCase2—Performs isolated testing on a content provider.

► ServiceTestCase—Performs isolated testing on a service.

In addition to these test case objects, there are helper classes for providing mock objects (that is, objects that aren't the real ones but can be used to better trace calls to the real objects), helper classes for simulating touch screen events, and other such utilities. You can find full documentation on these classes in the android.test package.

0 0

Post a comment