Appium + Selenium Android:没有Thread.sleep时没有点击ListView项目

时间:2015-11-09 14:40:31

标签: android selenium selenium-webdriver automated-tests appium

我讨厌使用"睡眠者" AAAA)在测试中,但没有睡眠者,一些测试失败了。

我的(Thread.sleep(millis)应用程序中有ListView,我想点击列表中的第一项(在我们的案例中是沙特阿拉伯)。

Countries ListView

Android

public AndroidDriver androidDriver; ... androidDriver = new AndroidDriver(serverAddress, capabilities); androidDriver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); driverWait = new WebDriverWait(androidDriver, 30); // at this moment everything is initialized and working properly, // Appium server is up and running driverWait.until(ExpectedConditions.visibilityOfElementLocated(By.id("com.###.debug:id/countries_list_view"))); WebElement countriesList = driver.findElement(By.id("com.###.debug:id/countries_list_view")); List<WebElement> countries = countriesList.findElements(By.id("com.###.debug:id/list_item_container")); WebElement country = countries.get(0); // country isn't null, and it corresponds to a real ListView row driverWait.until(ExpectedConditions.elementToBeClickable(country)); Thread.sleep(1000); // <---- country isn't clicked without this country.click(); 测试中存在同样的问题(需要显式等待)。

我尝试了不同的方法来等待应该点击的元素

  • Calabash/Cucumber
  • driverWait.until(ExpectedConditions.visibilityOfElementLocated(By));
  • driverWait.until(ExpectedConditions.visibilityOf(WebElement));
  • driverWait.until(ExpectedConditions.elementToBeClickable(By));

并且没有一个正在运作。在我尝试点击driverWait.until(ExpectedConditions.presenceOfElementLocated(By));第一项时,ListView存在,并且所有列表元素都在屏幕上。

我试图通过使用ListView获取列表行ListView来查找XPath第1行。结果是相同的 - 没有Appium Inspector点击视图。

在测试中使用Thread.sleep是非常糟糕的做法,并使我的测试不稳定。在这种情况下,我不能依赖测试结果,因为即使应用程序正常工作,它们也可能会失败。有一篇关于&#34;等待&#34;的文章。和&#34;睡觉&#34;在Selenium测试中使用(Selenium WebDriver wait)。

  1. 如何在测试中解决此类问题?
  2. 自动化世界中Thread.sleep次调用的频率是多少? (我主要是Android开发人员,而不是移动自动化方面的经验。)
  3. 更新 我试图不要像JeffC提到的那样混淆隐式和明确的等待,而且它没有帮助。

    这是我的测试:

    Thread.sleep

    我正在验证每个测试中是否加载了该页面。如果我只使用隐式等待 - 测试会不时失败;如果我只使用明确的等待 - 它是相同的,测试会不时失败。

    我在Appium tutorial中发现他们将implicit与明确的12结合使用。根据{{​​3}},它看起来很奇怪。

    工作解决方案:我修改了一点@Test public void selectCountryLanguageAndStartApplication() throws Exception { countryLanguagePage.loaded(); countryLanguagePage.selectFirstCountry(); countryLanguagePage.pleaseSelectCountryTextIsHidden(); countryLanguagePage.startClick(); } ... /** * Verify the page has loaded */ public static void loaded() { driver.findElement(By.id("com.###.debug:id/countries_list_view")); } 方法

    loaded

    睡眠带来了稳定性&#34;测试,我可以找到元素并按明确等待或没有它们按下它们。

    这是否意味着,我应该添加&#34; sleep&#34;当新的public static void loaded() { driver.findElement(By.id("com.###.debug:id/countries_list_view")); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } 启动时(我唯一的解决方案)?或者我正在以错误的方式等待活动初始化?

2 个答案:

答案 0 :(得分:0)

你可以试试这个:

  WebDriverWait wait = new WebDriverWait(driver, 30); 
  wait.until(ExpectedConditions.elementToBeClickable(By));

while(!driver.findElement(By).isDisplayed())
{
  //Thread.sleep(10);
}

我认为Thread.sleep调用可以正常使用(如果你的测试涉及时间安排几乎是必要的),但在大多数情况下,有更好的方法来处理它们将用于的大多数事情。

希望这有帮助,

利安

答案 1 :(得分:0)

我尝试编写一个方法来等待一个元素。希望它适用于您的情况。

import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class Utility {
    public static AndroidElement element;
    public  static  boolean isElementPresent;
    public static boolean waitForPresence(AndroidDriver driver, int timeLimitInSeconds, String targetResourceId){

        try{
            element =  (AndroidElement) driver.findElementByAndroidUIAutomator("new UiSelector().resourceId(\""+targetResourceId+"\")");
            WebDriverWait wait = new WebDriverWait(driver, timeLimitInSeconds);
            wait.until(ExpectedConditions.visibilityOf(element));
            isElementPresent = element.isDisplayed();
            return isElementPresent;
        }catch(Exception e){
            isElementPresent = false;
            System.out.println(e.getMessage());
            return isElementPresent;
        }
    }
}