Sunday, December 15, 2013

Working with Menu button, Text field and Long Press menus using UiAutomator

In this post, I want to explain the following things
  • How to work with Menu buttons in UiAutomator?
  • Working with Text fields in UiAutomator?
  • How to Read text from Text filed
  • Validating the text
  • Validate long press menus
Take example of Notes Application and automate the following tests
  1. Open "Notes" Application from AppTray
  2. Click on Menu button
  3. Click on "Add Note" button from the menu
  4. Enter Text "Note 1" in the Text field
  5. Read the text entered in the text box and validate it
  6. Click on "Save" button from the menu
  7. Add another note "Note 2"
  8. long press on "Note 1" and delete the note

 Here is the implementation:

Step 1: Open "Notes" application from the AppTray



Open UiAutomatorViewer, get the properties on Notes app

From the above screenshot, we can see the Notes application properties as
  • class = android.widget.TextView
  • package = com.android.launcher
  • text = Notes
  • index = 34
Create UiObject with the above properties and click on the Notes application if it is found. Code is below

 
// Look for the Notes application
 UiObject notesApp = appView.getChildByText(new UiSelector()
  .className(android.widget.TextView.class.getName()),
  "Notes", true);

 // Open Notes application
 if (notesApp.exists()) {
  notesApp.clickAndWaitForNewWindow();

 // Validate Notebook App by it's package name
 UiObject notesValidation = new UiObject(new UiSelector()
       .packageName("com.example.android.notepad"));
 assertTrue("Notes App not launched", notesValidation.exists());



Step 2: Click on Menu button

   // Click on Menu button
   UiDevice myDevice = getUiDevice();
   myDevice.pressMenu();

Uidevice class provides 'pressmenu' method to click on the menu button

Step 3: Click on "Add Note" from the menu

To click on "Add Note" button, get the properties of the button using UiAutomatorViewer. From the above screenshot we can get the properties of 'Add Note' button as follows
  • index = 0
  • text = Add note
  • class = android.widget.TextView
  • package = com.example.android.notepad
Create UiObject with the above properties and click on the button if it is found. Code snippet is below

  // click on 'Add Note' button
  UiObject addNoteButton = new UiObject(new UiSelector()
  .className(android.widget.TextView.class.getName())
 .text("Add note").index(0));
   
  if (addNoteButton.exists())
 addNoteButton.click();

Step 4: Enter "Note 1" in the text field

Pressing on "Add Note" button opens a text box to enter the new note. Select the text box and enter the text "Note 1"

With UiAutomatorViewer get the properties of edit text field and create an UiObject. After getting the properties of the text field, enter the text using "setText()" method. Code snippet is below
 

// Edit field to enter new Text
 UiObject addNoteText = new UiObject(new UiSelector()
  .className(android.widget.EditText.class.getName()).index(0));
   // Add note button in menu
 if (addNoteText.exists())
  addNoteText.setText("Note 1");

Step 5: Read and validate the text entered
 <br/>assertEquals("Note 1", addNoteText.getText());<br/>

Step 6: Click on "Save" button
From the above screenshot, we can get the properties of save button. "Save" button can be accessed by it's text property.

 // Save button in the menu
  UiObject saveNoteButton = new UiObject(
    new UiSelector().className(
    android.widget.TextView.class.getName()).text("Save"));

   if (saveNoteButton.exists())
   saveNoteButton.clickAndWaitForNewWindow();

Step 7: Add new note "Note 2"
  //------Add Note 2--------

  // Click on Menu button
   myDevice.pressMenu(); 

  // Add note button in menu
  if (addNoteButton.exists()) { 
    addNoteButton.click();

  // Add new Note 2       
  if (addNoteText.exists())
  addNoteText.setText("Note 2");

  assertEquals("Note 2", addNoteText.getText());

  //Click on Save button
  myDevice.pressMenu();

  if (saveNoteButton.exists())
      saveNoteButton.clickAndWaitForNewWindow();

}

Step 8: Long press on 'Note 1' and delete the note

To Long press on Note 1, we have get the properties of "Note 1" from the list of available notes. Get the properties of Notes from the UiAutomatorViewer

To access the Note 1 from the list, access it as a child object. To get the child object, we have to first get the property of entire list (list view) as a parent object and then the individual list items as child objects

        //Get the list of added Notes
 UiObject notesList = new UiObject(new UiSelector().className(
  android.widget.ListView.class.getName()).index(0));

 // Select Note 2 and long press on it
 UiObject noteListItem = notesList.getChild(new UiSelector()
  .className(android.widget.TextView.class.getName())
  .text("Note 1").longClickable(true));
  
 //Check if Note 1 exists in the list
 assertEquals("Note 1", noteListItem.getText());


Long press on the Note1 and select "Delete" button
To get the 'Delete' button property get the long press menu list view as parent object and then get the individual menu items as child objects. Code snippet is below


 // Long press the menu item
 noteListItem.longClick();

       //Long press menu 
 UiObject longPressNoteMenu = new UiObject(new UiSelector().className(
   android.widget.LinearLayout.class.getName()).index(0));
        
        UiObject note1Text = longPressNoteMenu.getChild(new UiSelector()
  .className(android.widget.TextView.class.getName()).index(0));
 
        //Check if Note 1 menu is opened
 assertEquals("Note 1", note1Text.getText());
 
 //Delete button in LongPress menu
 UiObject deleteButton = new UiObject(new UiSelector().className(
   android.widget.TextView.class.getName()).text("Delete"));

 //Check if delete button exists 
 assertTrue("Delete Button not found", deleteButton.exists());
        
        //Delete the note
 deleteButton.clickAndWaitForNewWindow();


Here is the complete code,
package Notes;

import org.junit.After;
import org.junit.Before;

import android.os.RemoteException;

import com.android.uiautomator.core.UiDevice;
import com.android.uiautomator.core.UiObject;
import com.android.uiautomator.core.UiObjectNotFoundException;
import com.android.uiautomator.core.UiScrollable;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;

public class CreateNewNote extends UiAutomatorTestCase {

 // ----------------Global variables------------------------------

 // Get the device properties
 UiDevice myDevice = getUiDevice();
 // All App Tray Button
 UiObject AppTrayButton = new UiObject(new UiSelector().description("Apps"));

 // Get AppTray container
 UiScrollable appView = new UiScrollable(new UiSelector().className(
   "android.view.View").scrollable(true));
 // Apps Tab
 UiObject AppsTab = new UiObject(new UiSelector().className(
   "android.widget.TextView").description("Apps"));
 // Verify the launched application by it's Package name
 UiObject notesValidation = new UiObject(
   new UiSelector().packageName("com.example.android.notepad"));
 // Add Note menu button
 UiObject addNoteButton = new UiObject(new UiSelector()
   .className(android.widget.TextView.class.getName())
   .text("Add note").index(0));
 // Edit field to enter new Text
 UiObject addNoteText = new UiObject(new UiSelector().className(
   android.widget.EditText.class.getName()).index(0));
 // Get the list of added Notes
 UiObject notesList = new UiObject(new UiSelector().className(
   android.widget.ListView.class.getName()).index(0));
 // Save menu button
 UiObject saveNoteButton = new UiObject(new UiSelector().className(
   android.widget.TextView.class.getName()).text("Save"));
 // Long press menu
 UiObject longPressNoteMenu = new UiObject(new UiSelector().className(
   android.widget.LinearLayout.class.getName()).index(0));
 // Delete button in LongPress menu
 UiObject deleteButton = new UiObject(new UiSelector().className(
   android.widget.TextView.class.getName()).text("Delete"));

 // Actual Tests starts here

 @Before
 public void verifyNotesApp() {
  assertTrue("Notes App not launched", notesValidation.exists());
 }

 // Launch Notes Application
 public void testLaunchTestApp() throws RemoteException,
   UiObjectNotFoundException {

  // wakeup the device if the screen is Off
  if (!myDevice.isScreenOn())
   myDevice.wakeUp();
  // Press Home button
  myDevice.pressHome();

  // Launch Notes Application
  assertTrue("AppTray Button not found", AppTrayButton.exists());
  AppTrayButton.clickAndWaitForNewWindow();

  assertTrue("All Apps Tab not found", AppsTab.exists());
  // Set the swiping mode to horizontal (the default is vertical)
  appView.setAsHorizontalList();

  // Look for the Notes application
  UiObject notesApp = appView.getChildByText(new UiSelector()
    .className(android.widget.TextView.class.getName()), "Notes",
    true);

  // Validate Notebook App by it's package name
  assertTrue("Notes App not launched", notesValidation.exists());

  notesApp.clickAndWaitForNewWindow();

 }

 // Add Note1
 public void testAddNote1() throws RemoteException,
   UiObjectNotFoundException {

  // Click on Menu button
  myDevice.pressMenu();

  assertTrue("Add Note Button not found", addNoteButton.exists());
  // click on 'Add Note' button
  addNoteButton.click();

  // Add note button in menu
  assertTrue("Add note Text field is not found", addNoteText.exists());
  addNoteText.setText("Note 1");

  // Read the text enetered in Text box
  assertEquals("Note 1", addNoteText.getText());

  // Click on Menu button
  myDevice.pressMenu();

  // Save button in the menu
  assertTrue("Save Button not found", saveNoteButton.exists());
  saveNoteButton.clickAndWaitForNewWindow();

 }

 // Add Note2
 public void testAddNote2() throws UiObjectNotFoundException {
  // ------Add Note 2--------

  // Click on Menu button
  myDevice.pressMenu();

  assertTrue("Add note Button not found", addNoteButton.exists());
  addNoteButton.click();

  // Add note button in menu
  assertTrue("Add note Text field not found", addNoteText.exists());
  addNoteText.setText("Note 2");

  // Read the Text entered
  assertEquals("Note 2", addNoteText.getText());

  // Save button in the menu
  myDevice.pressMenu();

  assertTrue("Save Button not found", saveNoteButton.exists());
  saveNoteButton.clickAndWaitForNewWindow();
 }

 // Delete Note 1
 public void testDeleteNote1() throws UiObjectNotFoundException {
  // Select Note 2 and long press on it
  UiObject noteListItem = notesList.getChild(new UiSelector()
    .className(android.widget.TextView.class.getName())
    .text("Note 1").longClickable(true));

  // Check if Note 1 exists in the list
  assertEquals("Note 1", noteListItem.getText());

  // Long press the menu item
  noteListItem.longClick();

  UiObject note1Text = longPressNoteMenu.getChild(new UiSelector()
    .className(android.widget.TextView.class.getName()).index(0));

  // Check if Note 1 menu is opened
  assertEquals("Note 1", note1Text.getText());
  assertTrue("Delete Button not found", deleteButton.exists());

  deleteButton.clickAndWaitForNewWindow();
 }

 @After
 public void closeNotesApp() {
  getUiDevice().pressBack();
 }

}