Nicholas Mansfield
Nicholas Mansfield

Reputation: 140

Appium cannot find an element by content-description/accessibilityID

I have been trying to get Appium testing setup with Java to test on Android. To verify my elements, I have been using AndroidUiAutomator. In the UI Automator Viewer, I can see that the accessibility Label has been propagated (see attached image). When I use findElement(By.name|By.AccessibilityId|etc it usually just times out and the Appium server terminal console must be restarted to run the test. I get similar results using FindByXPath. I tried waiting using a timeout and a waitdriver to ensure that the elements are loaded, but it was to no avail. I've tried pretty much everything listed in the code below.

        /**
        * Created by appium on 12/6/16.
        */
     import io.appium.java_client.AppiumDriver;
    import io.appium.java_client.android.AndroidDriver;
    import io.appium.java_client.MobileElement;
    import io.appium.java_client.android.AndroidElement;
    import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.WebDriver;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.Select;
import java.util.*;



import java.net.URL;

public class FirstTest {
    AndroidDriver   driver;

    @Before
    public void setUp() throws Exception {

        DesiredCapabilities capabilities = new DesiredCapabilities();


        capabilities.setCapability("deviceName", "Android Emulator");
        capabilities.setCapability("BROWSER_NAME", "Android");
        capabilities.setCapability("app", apkloc);


        capabilities.setCapability("VERSION", "5.0.0");
        capabilities.setCapability("platformName", "Android");

        driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
        // Thread.sleep(100);
        //driver.manage().timeouts().implicitlyWait(100000, TimeUnit.SECONDS);

        System.out.println("driver1=" + driver);


    }




    @Test
    public void login() throws InterruptedException {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        MobileElement mo = (MobileElement) driver.findElementByAndroidUIAutomator("new UiSelector().text(\"username\")");
        WebDriverWait wait = new WebDriverWait(driver, 1000);
        System.out.println("driver4=" + driver);
        WebElement element = driver.findElement(By.xpath("//EditText[@text='username']"));
        WebElement  elly = driver.findElementByXPath("//[@id=wutitdo]");
        System.out.println("olly-mint: "+elly);

        WebElement element2 = driver.findElementByName("password");
        //WebElement element3 = driver.findElementByXPath("//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.webkit.WebView[1]/android.view.View[4]");
        //WebElement element4 = driver.findElementByName("");

        //WebElement element3 = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.webkit.WebView[1]/android.view.View[4]")));
        // WebElement exp = (WebElement) (new WebDriverWait(driver, 15)).until(ExpectedConditions.presenceOfElementLocated(By.name("Trip")));
        System.out.println("dr" + driver);
        //element.click();
        //WebDriverWait wait = new WebDriverWait(driver, 10);
       // element2.click();
        Thread.sleep(1000);
        //element3.click();

        //WebElement current = (new WebDriverWait(driver,100)).until(ExpectedConditions.presenceOfElementLocated(By.name("username")));
        //current.sendKeys();
       // WebElement dropdown = driver.findElement(By.xpath("//*[@id='wrapper']/table[2]/tbody/tr[24]/td[3]/select[1]"));

        //WebElement dropdown = driver.findElement(By.xpath("//*[@id='wrapper']/table[2]/tbody/tr[24]/td[3]/select[1]"));


        //Select listbox = new Select(driver.findElement(By.xpath("//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.webkit.WebView[1]/android.view.View[1]/android.view.View[0]")));
        //listbox.selectByIndex(0);
        //listbox.selectByIndex(3);
        //driver.findElement(By.xpath("//android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.webkit.WebView[1]/android.view.View[1]/android.view.View[3]")).click();
        //Thread.sleep(2000);

        //element4.click();
        //Thread.sleep(1000);
    }



    @After
    public void tearDown() throws Exception {


        System.out.println("driver3=" + driver);
        driver.quit();


    }

}


[![enter image description here][1]][1]


  [1]: https://i.sstatic.net/JPegT.png

Upvotes: 2

Views: 3433

Answers (3)

Muzzamil
Muzzamil

Reputation: 2881

You are not using default timeout so appium server can get time to search an element if locator is correct. You should use explicit wait to load element properly.

Add timeout in capabilities.

capabilities.setCapability("newCommandTimeout", 50);

Use these explicit wait functions based on element type if element is clickable try wait for clickable and if element is not clickable try with element’s visibility only

WebDriverWait wait = new WebDriverWait(driver, 30);

public void waitForMobileElementVisible(MobileElement element)
    {
           wait.until(ExpectedConditions.visibilityOf(element));

     }



    public void waitForMobileElementClickable(By by)
    {
            wait.until(ExpectedConditions.elementToBeClickable(by));
     }

Upvotes: 1

Mark Han
Mark Han

Reputation: 3145

@AndroidFindBy(accessibility = "Error Message")
private MobileElement ERROR_MESSAGE;

I suggest using the Annotations provided by Appium's Java Client for finding an element by Content Description. There are a few benefits of this:

1) Speed -- Finds before you need it to reduce time before clicking

2) Customization -- No need to have parity with iOS because you can use an @iOSXCUITFindBy(id = "Accessibility ID") on top of the other annotation

3) Lazily Finds Elements -- Only finds the element when you need them!

Upvotes: 0

Sergio Lima
Sergio Lima

Reputation: 114

To use the find by content description on Android you have to use something like:

public WebElement getByContentDescription(String string){
    return driver.findElement(By.ByXPath("//*[@content-desc='"+string+"']");
}

Upvotes: 0

Related Questions