2016-11-29 4 views
1

Ich versuche, Elemente in Firefox unter Verwendung von Xpath und Namen Werte in Selen Webdriver zu identifizieren, aber es funktioniert nicht. This is link to the web page which I want to automate. Alle Eingabefelder auf dieser Seite sehen für mich komisch aus und ich verstehe nicht, wie man sie füllt.Selenium Webdriver findelement ich sendKeys() verhält sich nicht wie erwartet

driver.findElement(By.name("sender-postCode")).sendKeys("02791"); 
driver.findElement(By.xpath(".//*[@id='stepOneForm']/div[2]/div[4]/div[1]/div[1]/div[1]/input")).sendKeys("02791"); 

Dies ist mein Code:

package SalesBar; 
import org.openqa.selenium.By; 
import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.WebElement; 
import org.openqa.selenium.firefox.FirefoxDriver; 
import org.openqa.selenium.firefox.FirefoxProfile; 
import org.openqa.selenium.firefox.internal.ProfilesIni; 
public class Salesbar { 
public static void main(String[] args) throws Exception { 
    // TODO Auto-generated method stub 
    System.setProperty("webdriver.gecko.driver", "C:/Users/User/Documents/SeleniumWebDriver/geckodriver.exe"); 
    ProfilesIni profil = new ProfilesIni(); 
    FirefoxProfile myprofile = profil.getProfile("default"); 

    WebDriver driver; 
    driver = new FirefoxDriver(myprofile); 

    driver.get("https://wwwuat.dpdpickup.pl/Wycen-i-nadaj-Online"); 
    driver.findElement(By.xpath(".//*[@id='contentWrapper']/div/div/div[2]/div[1]/a")).click(); 
    Thread.sleep(3000); 
    driver.findElement(By.xpath(".//*[@id='stepOneForm']/div[2]/div[3]/span[2]/label/span")).click(); 
    Thread.sleep(3000); 
    driver.findElement(By.name("parcels-1-weight")).sendKeys("5"); 
    } 

Bitte lassen Sie mich wissen, ob es eine Standardmethode in WebDriver ist diese Felder zu finden und zu füllen.

Antwort

0

Ein Problem bei allen Testautomatisierungswerkzeugen ist, dass die Seite DOM nicht geladen hat, wenn das Automatisierungstool ausgeführt wird. Es gibt verschiedene Ebenen der Verfeinerung, die verwendet werden können, um dies zu 100% zuverlässig zu machen. Die erste Verteidigungslinie besteht darin, ExpectedConditions zu verwenden. Also für Ihr erstes Beispiel,

WebDriver webDrive = ... // You have to initialize to a browser instance and navigate to your web page 
By bySenderPostCode = By.name("sender-postCode"); 
Wait<WebDriver> wait_element = new WebDriverWait(webDriver, 40); // Wait up to 40 seconds 
WebElement senderPostalCodeElement = wait_element.until(ExpectedConditions.visibilityOfElementLocated(bySenderPostCode)); 
senderPostalCodeElement.sendKeys("02791"); 

Komplexe Seiten mit vielen Ausführen von JavaScript kann ein Schmerz sein. Ich benutze Routinen, die ich geschrieben habe, für AngularJS zu warten, bis die Ausführung abgeschlossen ist, warten Sie, eine Lade Spinner zu vervollständigen, und schließlich für Seite Readystate gleich komplett:

waitForAngularToLoad(webDriver, 40); 
wait_element.until((WebDriver dr1) -> (webDriver.findElement(mySpinner).getAttribute("class").contains("ng-hide"))); 
waitForBrowserReadystateComplete(webDriver); 

Diese für die Umwelt werden gezwickt haben, dass Sie müssen warten. Das Warten auf jQuery ist anders als das Warten auf AngularJs. Aber was ich dir gegeben habe, sollte dich zum Laufen bringen. Lassen Sie mich wissen, wie es sich entwickelt.

EDIT

Ich weiß, dass Sie über meine Routinen zu sagen, dass ich warten verwenden, aber nicht den Code-Sharing war sinnlos. Der Ladespinner hängt vollständig von der Implementierung ab. Es gibt keinen Weg, der garantiert überall funktioniert, aber ich habe Ihnen die allgemeine Form gegeben, die für AngularJs-Implementierungen üblich ist.

Hier sind die andere:

public void waitForBrowserReadystateComplete(WebDriver webDriver) { 
    for (int a=0; a<20; a++) { 
     JavascriptExecutor javascriptExecutor = (JavascriptExecutor) webDriver; 
     if (javascriptExecutor.executeScript("return document.readyState") 
       .toString().equals("complete")) { 
      break; 
     } 
     sleepResponsibly(500); 
    } 
} 

public void sleepResponsibly(int timeMillisecond){ 
    try{ 
     Thread.sleep(timeMillisecond); 
    } catch (InterruptedException ex) { 
     Thread.currentThread().interrupt(); 
     throw new RuntimeException(ex); 
    } 
} 

public boolean waitForAngularToLoad(WebDriver driver, int timeout) { 
    driver.manage().timeouts().setScriptTimeout(timeout, TimeUnit.SECONDS); 
    WebDriverWait wait = new WebDriverWait(driver, timeout, 500L); 
    return wait.until(angularHasFinishedProcessing()); 
} 


public static ExpectedCondition<Boolean> angularHasFinishedProcessing() { 
    return new ExpectedCondition<Boolean>() { 
     @Override 
     public Boolean apply(WebDriver driver) { 
      String hasAngularFinishedScript = "var callback = arguments[arguments.length - 1];\n" + 
        "var el = document.querySelector('html');\n" + 
        "if (!window.angular) {\n" + 
        " callback('false')\n" + 
        "}\n" + 
        "if (angular.getTestability) {\n" + 
        " angular.getTestability(el).whenStable(function(){callback('true')});\n" + 
        "} else {\n" + 
        " if (!angular.element(el).injector()) {\n" + 
        "  callback('false')\n" + 
        " }\n" + 
        " var browser = angular.element(el).injector().get('$browser');\n" + 
        " browser.notifyWhenNoOutstandingRequests(function(){callback('true')});\n" + 
        "}"; 

      JavascriptExecutor javascriptExecutor = (JavascriptExecutor) driver; 
      String isProcessingFinished = javascriptExecutor.executeAsyncScript(hasAngularFinishedScript).toString(); 

      return Boolean.valueOf(isProcessingFinished); 
     } 
    }; 
} 

Denken Sie daran, die Winkel die nur funktionieren, wenn Ihr System Under Test gebaut AngularJS verwenden.

EDIT 2 Finding Elemente

Ich verwende den Google Chrome Browser-Elemente zu "finden". Öffnen Sie Ihre Webseite unter Chrome. Klicken Sie mit der rechten Maustaste auf das angezeigte Element. Wählen Sie Inspect -> Copy -> Copy Selector | Kopiere XPath. Sie können dies auch unter Firefox tun. Chrome ist nur eine Angewohnheit.

EDIT3

jQuery

public boolean waitForJquery(WebDriver driver, int timeout) { 
    return waitFor(driver, "return jQuery.active;", "0", timeout); 
} 

public boolean waitFor(WebDriver driver, final String javascriptString, final String targetString, int timeout) { 
    WebDriverWait wait = new WebDriverWait(driver, timeout, 500L); 

    /* 
    * If you are curious about what follows see: 
\ * http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/support/ui/ExpectedCondition.html 
    * 
    * We are creating an anonymous class that inherits from ExpectedCondition and then implements interface 
    * method apply(...) 
    */ 
    ExpectedCondition<Boolean> isLoaded = new ExpectedCondition<Boolean>() { 

     public Boolean apply(WebDriver driver) { 
     String jsReturnedValue = ""; 

     try { 
      jsReturnedValue = String.valueOf(((JavascriptExecutor)driver).executeScript(javascriptString)); 
      return (jsReturnedValue.equals(targetString)); 
     } catch (Exception e) { 
      log.info("Looking for: " + javascriptString + ", e.message: " + e.getMessage()); 
      return true; // If Javascript not found then don't wait for it 
     } 
     } 
    }; // Terminates statement started by ExpectedCondition<Boolean> isLoaded = ... 

    return wait.until(isLoaded); 
} 

Und es nur abzurunden, Ajax

public boolean waitForPrototypeAjax(WebDriver driver, int timeout) { 
    return waitFor(driver, "return Ajax.activeRequestCount;", "0", timeout); 
}  
+0

Hallo Mike, wie ich weiß, dass die Anwendung jquery nicht AngularJS verwendet. Also habe ich dein erstes Beispiel benutzt. Und es hat nicht funktioniert. Hast du den Link, den ich angehängt habe, geöffnet? Wenn Sie auf die Radionknöpfe klicken, sehen Sie das Formular.Ich habe geändert 'Wait wait_element = new WebDriverWait (webDriver, 40);' zu 'Warten auf wait_element = new WebDriverWait (driver, 40)'; weil es markiert wurde (webDriver kann nicht in eine Variable aufgelöst werden) –

+0

Können Sie genauer über "nicht funktioniert" sein? Bitte posten Sie den aktualisierten Code, den Sie ausgeführt haben. Bitte beachten Sie, dass [Marionette und Geckodriver noch nicht vollständig sind. Dies bedeutet, dass es noch keine vollständige Konformität mit dem WebDriver-Standard oder vollständige Kompatibilität mit Selenium bietet.] (Https://github.com/mozilla/geckodriver). Also benutze ich selen-java v2.53.1 und firefox v47.0. – MikeJRamsey56

+0

Ich bin zu Chrome Webdriver und Selenium-Java v2.53 gewechselt und das hat meine Probleme gelöst. Danke Mike. –

Verwandte Themen