2015-11-09 21 views
5

Nienawidzę używania "podkładów" (Thread.sleep(millis)) w testach, ale bez podkładów niektóre testy kończą się niepowodzeniem.Appium + Selenium Android: Element ListView nie kliknięty bez Thread.sleep

Mam aplikację ListView w mojej aplikacji Android i chcę dotknąć pierwszego elementu na liście (ARABIA SAUDYJSKA w naszym przypadku).

Countries ListView

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(); 

Ten sam problem istnieje w Calabash/Cucumber testów (wymagane wyraźne oczekiwania).

Próbowałem różnych sposobów czeka na element, który należy kliknąć

  • driverWait.until(ExpectedConditions.visibilityOfElementLocated(By));
  • driverWait.until(ExpectedConditions.visibilityOf(WebElement));
  • driverWait.until(ExpectedConditions.elementToBeClickable(By));
  • driverWait.until(ExpectedConditions.presenceOfElementLocated(By));

i żaden działa. W chwili, gdy próbuję dotknąć pierwszego elementu ListView, istnieje ListView i wszystkie elementy listy znajdują się na ekranie.

Próbowałem znaleźć ListView pierwszy wiersz, pobierając wiersz listy XPath przy użyciu Appium Inspector. Wynik jest taki sam - widok nie zostanie kliknięty bez Thread.sleep.

Używanie w testach Thread.sleep jest naprawdę złą praktyką i powoduje, że moje testy są niestabilne. Nie mogę polegać na wynikach testów w tym przypadku, ponieważ mogą one zawieść, nawet jeśli aplikacja działa poprawnie. W testach Selenium znajduje się artykuł na temat "oczekiwania" i "uśpienia" (Selenium WebDriver wait).

  1. Jak naprawić takie problemy w testach?
  2. Jak często używane są połączenia Thread.sleep w świecie automatyki? (Jestem głównie programistą systemu Android i nie mam doświadczenia z automatyką mobilną).

UPDATE: Starałem się, aby nie mieszać się niejawne i jawne czeka, jak JeffC wspomniano, i to nie pomogło.

Oto moja próba:

@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")); 
} 

ja weryfikacji, jeśli strona jest ładowana w każdym teście. Jeśli używam tylko nieokreślonego czekania - test od czasu do czasu się nie udaje; jeśli używam tylko jawnego czekania - to jest to samo, test nie udaje się od czasu do czasu.

Znalazłem w Appium tutorial, że używają implicit w połączeniu z wyraźnymi 1, 2. Wygląda dziwnie, zgodnie z docs.

Roztwór roboczy: I zostały zmodyfikowane nieco loaded metodę

public static void loaded() { 
    driver.findElement(By.id("com.###.debug:id/countries_list_view")); 
    try { 
     Thread.sleep(1000); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
} 

uwzględniając, że sen przynosi „stabilność”, aby przetestować i mogę znaleźć elementy i naciśnij na nich czeka jawnych lub bez nich.

Czy to oznacza, że ​​powinienem dodać "sen" po uruchomieniu nowego Activity (jedyne działające rozwiązanie dla mnie)? Czy czekam na inicjalizację działania w niewłaściwy sposób?

+0

'driverWait.until (ExpectedConditions.elementToBeClickable (element));' powinno to być 'elementToBeClickable (kraj)' zamiast? – AdamMc331

+0

nie. Proszę sprawdzić link "Selenium WebDriver czekać" z postu o wyraźnych czeka. –

+0

Dobra, tylko sprawdzam. Nie używałem selenu, ale zrobiłem kilka automatycznych testów używając Espresso dla Androida i pamiętam, że zalecane jest wyłączenie animacji na urządzeniu, aby testy zadziałały. Animacje mogą powodować problemy z klikaniem elementów listy. Czy próbowałeś tego? – AdamMc331

Odpowiedz

0

Można spróbować to:

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

lub

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

myślę Thread.sleep połączenia są w porządku do korzystania (i niemal konieczne, jeśli badanie obejmuje taktowanie), ale w większości przypadków jest lepszy sposoby radzenia sobie z większością rzeczy, w których będą wykorzystywane.

Nadzieja to pomaga,

Liam

+0

Używam warunkowego oczekiwania w moim przykładzie, i tak nie działa. –

+0

OK, możesz użyć metody 'isDisplayed', aby wymusić test, dopóki element nie zostanie wyświetlony. Odpowiedź została zaktualizowana na przykład: –

+0

Próbowałem czekać na element używając 'while'-solution, a test czasami się nie udaje. Zanim kliknę element, wydrukowałem jego własność "isDisplayed" i jest to prawda przez cały czas, ale test kończy się niepowodzeniem bez dotykania elementu :( –