Home | History | Annotate | Download | only in test
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.example.spinner.test;
     18 
     19 import com.android.example.spinner.SpinnerActivity;
     20 
     21 import android.app.Instrumentation;
     22 import android.test.ActivityInstrumentationTestCase2;
     23 import android.test.UiThreadTest;
     24 import android.view.KeyEvent;
     25 import android.widget.Spinner;
     26 import android.widget.SpinnerAdapter;
     27 import android.widget.TextView;
     28 
     29 /*
     30  * Tests the example application Spinner. Uses the instrumentation test class
     31  * ActivityInstrumentationTestCase2 as its base class. The tests include
     32  *   - test initial conditions
     33  *   - test the UI
     34  *   - state management - preserving state after the app is shut down and restarted, preserving
     35  *     state after the app is hidden (paused) and re-displayed (resumed)
     36  *
     37  * Demonstrates the use of JUnit setUp() and assert() methods.
     38  */
     39 public class SpinnerActivityTest extends ActivityInstrumentationTestCase2<SpinnerActivity> {
     40 
     41     // Number of items in the spinner's backing mLocalAdapter
     42 
     43     public static final int ADAPTER_COUNT = 9;
     44 
     45     // The location of Saturn in the backing mLocalAdapter array (0-based)
     46 
     47     public static final int TEST_POSITION = 5;
     48 
     49     // Set the initial position of the spinner to zero
     50 
     51     public static final int INITIAL_POSITION = 0;
     52 
     53     // The initial position corresponds to Mercury
     54 
     55     public static final String INITIAL_SELECTION = "Mercury";
     56 
     57     // Test values of position and selection for the testStateDestroy test
     58 
     59     public static final int TEST_STATE_DESTROY_POSITION = 2;
     60     public static final String TEST_STATE_DESTROY_SELECTION = "Earth";
     61 
     62     // Test values of position and selection for the testStatePause test
     63 
     64     public static final int TEST_STATE_PAUSE_POSITION = 4;
     65     public static final String TEST_STATE_PAUSE_SELECTION = "Jupiter";
     66 
     67     // The Application object for the application under test
     68 
     69     private SpinnerActivity mActivity;
     70 
     71     // String displayed in the spinner in the app under test
     72 
     73     private String mSelection;
     74 
     75     // The currently selected position in the spinner in the app under test
     76 
     77     private int mPos;
     78 
     79     /*
     80      *  The Spinner object in the app under test. Used with instrumentation to control the
     81      *  app under test.
     82      */
     83 
     84     private Spinner mSpinner;
     85 
     86     /*
     87      * The data backing the Spinner in the app under test.
     88      */
     89 
     90     private SpinnerAdapter mPlanetData;
     91 
     92     /*
     93      * Constructor for the test class. Required by Android test classes. The constructor
     94      * must call the super constructor, providing the Android package name of the app under test
     95      * and the Java class name of the activity in that application that handles the MAIN intent.
     96      */
     97     public SpinnerActivityTest() {
     98 
     99         super("com.android.example.spinner", SpinnerActivity.class);
    100     }
    101 
    102     /*
    103      * Sets up the test environment before each test.
    104      * @see android.test.ActivityInstrumentationTestCase2#setUp()
    105      */
    106     @Override
    107     protected void setUp() throws Exception {
    108 
    109         /*
    110          * Call the super constructor (required by JUnit)
    111          */
    112 
    113         super.setUp();
    114 
    115         /*
    116          * prepare to send key events to the app under test by turning off touch mode.
    117          * Must be done before the first call to getActivity()
    118          */
    119 
    120         setActivityInitialTouchMode(false);
    121 
    122         /*
    123          * Start the app under test by starting its main activity. The test runner already knows
    124          * which activity this is from the call to the super constructor, as mentioned
    125          * previously. The tests can now use instrumentation to directly access the main
    126          * activity through mActivity.
    127          */
    128         mActivity = getActivity();
    129 
    130         /*
    131          * Get references to objects in the application under test. These are
    132          * tested to ensure that the app under test has initialized correctly.
    133          */
    134 
    135         mSpinner = (Spinner)mActivity.findViewById(com.android.example.spinner.R.id.Spinner01);
    136 
    137         mPlanetData = mSpinner.getAdapter();
    138 
    139     }
    140 
    141     /*
    142      * Tests the initial values of key objects in the app under test, to ensure the initial
    143      * conditions make sense. If one of these is not initialized correctly, then subsequent
    144      * tests are suspect and should be ignored.
    145      */
    146 
    147     public void testPreconditions() {
    148 
    149         /*
    150          *  An example of an initialization test. Assert that the item select listener in
    151          *  the main Activity is not null (has been set to a valid callback)
    152          */
    153         assertTrue(mSpinner.getOnItemSelectedListener() != null);
    154 
    155         /*
    156          * Test that the spinner's backing mLocalAdapter was initialized correctly.
    157          */
    158 
    159         assertTrue(mPlanetData != null);
    160 
    161         /*
    162          *  Also ensure that the backing mLocalAdapter has the correct number of entries.
    163          */
    164 
    165         assertEquals(mPlanetData.getCount(), ADAPTER_COUNT);
    166     }
    167 
    168     /*
    169      * Tests the UI of the main activity. Sends key events (keystrokes) to the UI, then checks
    170      * if the resulting spinner state is consistent with the attempted selection.
    171      */
    172     public void testSpinnerUI() {
    173 
    174         /*
    175          * Request focus for the spinner widget in the application under test,
    176          * and set its initial position. This code interacts with the app's View
    177          *  so it has to run on the app's thread not the test's thread.
    178          *
    179          * To do this, pass the necessary code to the application with
    180          * runOnUiThread(). The parameter is an anonymous Runnable object that
    181          * contains the Java statements put in it by its run() method.
    182          */
    183         mActivity.runOnUiThread(
    184             new Runnable() {
    185                 public void run() {
    186                     mSpinner.requestFocus();
    187                     mSpinner.setSelection(INITIAL_POSITION);
    188                 }
    189             }
    190         );
    191 
    192         // Activate the spinner by clicking the center keypad key
    193 
    194         this.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
    195 
    196         // send 5 down arrow keys to the spinner
    197 
    198         for (int i = 1; i <= TEST_POSITION; i++) {
    199 
    200             this.sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
    201         }
    202 
    203         // select the item at the current spinner position
    204 
    205         this.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
    206 
    207         // get the position of the selected item
    208 
    209         mPos = mSpinner.getSelectedItemPosition();
    210 
    211         /*
    212          * from the spinner's data mLocalAdapter, get the object at the selected position
    213          * (this is a String value)
    214          */
    215 
    216         mSelection = (String)mSpinner.getItemAtPosition(mPos);
    217 
    218         /*
    219          * Get the TextView widget that displays the result of selecting an item from the spinner
    220          */
    221 
    222         TextView resultView =
    223                 (TextView) mActivity.findViewById(com.android.example.spinner.R.id.SpinnerResult);
    224 
    225         // Get the String value in the EditText object
    226 
    227         String resultText = (String) resultView.getText();
    228 
    229         /*
    230          * Confirm that the EditText contains the same value as the data in the mLocalAdapter
    231          */
    232 
    233         assertEquals(resultText,mSelection);
    234     }
    235 
    236     /*
    237      *  Tests that the activity under test maintains the spinner state when the activity halts
    238      *  and then restarts (for example, if the device reboots). Sets the spinner to a
    239      *  certain state, calls finish() on the activity, restarts the activity, and then
    240      *  checks that the spinner has the same state.
    241      *
    242      */
    243 
    244     public void testStateDestroy() {
    245 
    246         /*
    247          * Set the position and value of the spinner in the Activity. The test runner's
    248          * instrumentation enables this by running the test app and the main app in the same
    249          * process.
    250          */
    251 
    252 
    253         mActivity.setSpinnerPosition(TEST_STATE_DESTROY_POSITION);
    254 
    255         mActivity.setSpinnerSelection(TEST_STATE_DESTROY_SELECTION);
    256 
    257         // Halt the Activity by calling Activity.finish() on it
    258 
    259         mActivity.finish();
    260 
    261         // Restart the activity by calling ActivityInstrumentationTestCase2.getActivity()
    262 
    263         mActivity = this.getActivity();
    264 
    265         /*
    266          * Get the current position and selection from the activity.
    267          */
    268 
    269         int currentPosition = mActivity.getSpinnerPosition();
    270         String currentSelection = mActivity.getSpinnerSelection();
    271 
    272         // test that they are the same.
    273 
    274         assertEquals(TEST_STATE_DESTROY_POSITION, currentPosition);
    275 
    276         assertEquals(TEST_STATE_DESTROY_SELECTION, currentSelection);
    277     }
    278 
    279     /*
    280      * Tests that the activity under test maintains the spinner's state when the activity is
    281      * paused and then resumed.
    282      *
    283      * Calls the activity's onResume() method. Changes the spinner's state by
    284      * altering the activity's View. This means the test must run
    285      * on the UI Thread. All the statements in the test method may be run on
    286      * that thread, so instead of using the runOnUiThread() method, the
    287      * @UiThreadTest is used.
    288      */
    289     @UiThreadTest
    290 
    291     public void testStatePause() {
    292 
    293         /*
    294          * Get the instrumentation object for this application. This object
    295          * does all the instrumentation work for the test runner
    296          */
    297 
    298         Instrumentation instr = this.getInstrumentation();
    299 
    300         /*
    301          * Set the activity's fields for the position and value of the spinner
    302          */
    303 
    304         mActivity.setSpinnerPosition(TEST_STATE_PAUSE_POSITION);
    305 
    306         mActivity.setSpinnerSelection(TEST_STATE_PAUSE_SELECTION);
    307 
    308         /*
    309          *  Use the instrumentation to onPause() on the currently running Activity.
    310          *  This analogous to calling finish() in the testStateDestroy() method.
    311          *  This way demonstrates using the test class' instrumentation.
    312          */
    313 
    314         instr.callActivityOnPause(mActivity);
    315 
    316         /*
    317          * Set the spinner to a test position
    318          */
    319 
    320         mActivity.setSpinnerPosition(0);
    321 
    322         mActivity.setSpinnerSelection("");
    323 
    324         /*
    325          * Call the activity's onResume() method. This forces the activity
    326          * to restore its state.
    327          */
    328 
    329         instr.callActivityOnResume(mActivity);
    330 
    331         /*
    332          * Get the current state of the spinner
    333          */
    334 
    335         int currentPosition = mActivity.getSpinnerPosition();
    336 
    337         String currentSelection = mActivity.getSpinnerSelection();
    338 
    339         assertEquals(TEST_STATE_PAUSE_POSITION,currentPosition);
    340         assertEquals(TEST_STATE_PAUSE_SELECTION,currentSelection);
    341   }
    342 
    343 }
    344