java - example - selenium webdriver python
¿Cómo puedo pedirle al Selenium-WebDriver que espere unos segundos en Java? (15)
Estoy trabajando en Java Selenium-WebDriver. yo añadí
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
y
WebElement textbox = driver.findElement(By.id("textbox"));
porque mis aplicaciones tardan unos segundos en cargar la interfaz de usuario. Así que establecí 2 segundos de espera implícita. pero no pude localizar el cuadro de texto del elemento
Luego agrego Thread.sleep(2000);
Ahora funciona bien. ¿Cuál es una mejor manera?
¿Parece que el clic está bloqueando? - Aquí hay otra manera de esperar si está usando WebDriverJS:
driver.findElement(webdriver.By.name(''mybutton'')).click().then(function(){
driver.getPageSource().then(function(source) {
console.log(source);
});
});
El código anterior espera después de que se hace clic en el botón para cargar la página siguiente y luego toma el origen de la página siguiente.
A veces, la espera implícita parece anulada y el tiempo de espera se acorta. [@ eugene.polschikov] tenía buena documentación sobre los por qué. He encontrado en mi prueba y codificación con Selenium 2 que las esperas implícitas son buenas pero ocasionalmente tienes que esperar explícitamente.
Es mejor evitar llamar directamente a un hilo para dormir, pero a veces no hay una buena forma de evitarlo. Sin embargo, hay otras opciones de espera proporcionadas por Selenium que ayudan. waitForPageToLoad y waitForFrameToLoad han demostrado ser especialmente útiles.
Bueno, hay dos tipos de espera: espera explícita e implícita. La idea de espera explícita es
WebDriverWait.until(condition-that-finds-the-element);
El concepto de espera implícita es
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
Puede obtener la diferencia en los detalles here .
En tales situaciones, preferiría usar wait explícito ( fluentWait
en particular):
public WebElement fluentWait(final By locator) {
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(locator);
}
});
return foo;
};
fluentWait
función fluentWait
devuelve el elemento web encontrado. De la documentación en fluentWait
: una implementación de la interfaz Wait que puede tener su tiempo de espera y el intervalo de sondeo configurado sobre la marcha. Cada instancia de FluentWait define la cantidad máxima de tiempo para esperar una condición, así como la frecuencia con la que se verifica la condición. Además, el usuario puede configurar la espera para ignorar tipos específicos de excepciones mientras espera, como NoSuchElementExceptions cuando busca un elemento en la página. Detalles que puedes obtener here
El uso de fluentWait
en su caso será el siguiente:
WebElement textbox = fluentWait(By.id("textbox"));
En mi opinión, esto es mejor ya que no sabes exactamente cuánto tiempo esperar y en el intervalo de sondeo puedes establecer un valor de tiempo arbitrario a través del cual se verificará la presencia del elemento. Saludos.
En ocasiones, la espera implícita falla y dice que existe un elemento pero realmente no.
La solución es evitar el uso de driver.findElement y reemplazarlo con un método personalizado que utilice una espera explícita implícitamente. Por ejemplo:
import org.openqa.selenium.NoSuchElementException;
public WebElement element(By locator){
Integer timeoutLimitSeconds = 20;
WebDriverWait wait = new WebDriverWait(driver, timeoutLimitSeconds);
try {
wait.until(ExpectedConditions.presenceOfElementLocated(locator));
}
catch(TimeoutException e){
throw new NoSuchElementException(locator.toString());
}
WebElement element = driver.findElement(locator);
return element;
}
Hay razones adicionales para evitar la espera implícita que no sean fallas esporádicas y ocasionales (consulte este link ).
Puede usar este método de "elemento" de la misma manera que driver.findElement. Por ejemplo:
driver.get("http://yoursite.html");
element(By.cssSelector("h1.logo")).click();
Si realmente desea esperar unos segundos para la solución de problemas o alguna otra ocasión rara, puede crear un método de pausa similar al que ofrece el IDE de selenio:
public void pause(Integer milliseconds){
try {
TimeUnit.MILLISECONDS.sleep(milliseconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Espera implícita: durante la espera implícita si el controlador web no puede encontrarlo inmediatamente debido a su disponibilidad, el WebDriver esperará la hora mencionada y no intentará encontrar el elemento nuevamente durante el período de tiempo especificado. Una vez que ha pasado el tiempo especificado, intentará buscar el elemento una vez más la última vez antes de lanzar la excepción. La configuración predeterminada es cero. Una vez que establecemos un horario, el Controlador Web espera el período de la instancia del objeto WebDriver.
Espera explícita: puede haber una instancia cuando un elemento en particular tarda más de un minuto en cargarse. En ese caso, definitivamente no le gustaría dedicar mucho tiempo a la espera implícita, ya que si hace esto, su navegador esperará al mismo tiempo para cada elemento. Para evitar esa situación, simplemente puede poner un tiempo por separado solo en el elemento requerido. Siguiendo esto, el tiempo de espera implícito de su navegador sería corto para cada elemento y sería grande para un elemento específico.
Espera implícitamente y Thread.sleep Both se usan solo para la sincronización ... pero la diferencia es que podemos usar Implícitamente espere todo el programa, pero Thread.sleep funcionará solo para ese código. Aquí mi sugerencia es usar Implícitamente espere una vez en el programa cuando cada vez que su página web se renueve significa usar Thread.sleep en ese momento ... será mucho mejor :)
Aquí está mi código:
package beckyOwnProjects;
import java.util.concurrent.TimeUnit;
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.interactions.Actions;
public class Flip {
public static void main(String[] args) throws InterruptedException {
WebDriver driver=new FirefoxDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(2, TimeUnit.MINUTES);
driver.get("https://www.flipkart.com");
WebElement ele=driver.findElement(By.cssSelector(".menu-text.fk-inline-block"));
Actions act=new Actions(driver);
Thread.sleep(5000);
act.moveToElement(ele).perform();
}
}
Este hilo es un poco más antiguo, pero pensé que publicaría lo que hago actualmente (trabajo en progreso).
Aunque todavía estoy en situaciones donde el sistema está bajo mucha carga y cuando hago clic en un botón de enviar (por ejemplo, login.jsp), las tres condiciones (ver a continuación) devuelven true
pero la siguiente página (por ejemplo, home.jsp) hasn ''t comenzó a cargar todavía.
Este es un método de espera genérico que toma una lista de Condicionesesperadas.
public boolean waitForPageLoad(int waitTimeInSec, ExpectedCondition<Boolean>... conditions) {
boolean isLoaded = false;
Wait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(waitTimeInSec, TimeUnit.SECONDS)
.ignoring(StaleElementReferenceException.class)
.pollingEvery(2, TimeUnit.SECONDS);
for (ExpectedCondition<Boolean> condition : conditions) {
isLoaded = wait.until(condition);
if (isLoaded == false) {
//Stop checking on first condition returning false.
break;
}
}
return isLoaded;
}
He definido varias condiciones esperadas reutilizables (tres están por debajo). En este ejemplo, las tres condiciones esperadas incluyen document.readyState = ''complete'', no hay un "wait_dialog" presente y no hay ''spinners'' (elementos que indican que se están solicitando datos asíncronos).
Solo el primero se puede aplicar genéricamente a todas las páginas web.
/**
* Returns ''true'' if the value of the ''window.document.readyState'' via
* JavaScript is ''complete''
*/
public static final ExpectedCondition<Boolean> EXPECT_DOC_READY_STATE = new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
String script = "if (typeof window != ''undefined'' && window.document) { return window.document.readyState; } else { return ''notready''; }";
Boolean result;
try {
result = ((JavascriptExecutor) driver).executeScript(script).equals("complete");
} catch (Exception ex) {
result = Boolean.FALSE;
}
return result;
}
};
/**
* Returns ''true'' if there is no ''wait_dialog'' element present on the page.
*/
public static final ExpectedCondition<Boolean> EXPECT_NOT_WAITING = new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
Boolean loaded = true;
try {
WebElement wait = driver.findElement(By.id("F"));
if (wait.isDisplayed()) {
loaded = false;
}
} catch (StaleElementReferenceException serex) {
loaded = false;
} catch (NoSuchElementException nseex) {
loaded = true;
} catch (Exception ex) {
loaded = false;
System.out.println("EXPECTED_NOT_WAITING: UNEXPECTED EXCEPTION: " + ex.getMessage());
}
return loaded;
}
};
/**
* Returns true if there are no elements with the ''spinner'' class name.
*/
public static final ExpectedCondition<Boolean> EXPECT_NO_SPINNERS = new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
Boolean loaded = true;
try {
List<WebElement> spinners = driver.findElements(By.className("spinner"));
for (WebElement spinner : spinners) {
if (spinner.isDisplayed()) {
loaded = false;
break;
}
}
}catch (Exception ex) {
loaded = false;
}
return loaded;
}
};
Dependiendo de la página, puedo usar uno o todos:
waitForPageLoad(timeoutInSec,
EXPECT_DOC_READY_STATE,
EXPECT_NOT_WAITING,
EXPECT_NO_SPINNERS
);
También hay ExpectedConditions predefinidos en la siguiente clase: org.openqa.selenium.support.ui.ExpectedConditions
Me gusta usar condiciones personalizadas. Aquí hay un código en Python:
def conditions(driver):
flag = True
ticker = driver.find_elements_by_id("textbox")
if not ticker:
flag = False
return flag
... click something to load ...
self.wait = WebDriverWait(driver, timeout)
self.wait.until(conditions)
Siempre que necesite esperar, puede hacerlo de forma explícita comprobando la existencia de un determinado elemento (tal elemento puede variar de una página a otra). find_elements_by_id
lista de devoluciones - vacía o no, solo tiene que verificar.
Prefiero el siguiente código para esperar 2 segundos.
for(int i=0; i<2 && driver.findElements(By.id("textbox")).size()==0 ; i++){
Thread.sleep(1000);
}
Si usa webdriverJs (node.js),
driver.findElement(webdriver.By.name(''btnCalculate'')).click().then(function() {
driver.sleep(5000);
});
El código anterior hace que el navegador espere 5 segundos después de hacer clic en el botón.
Usando Thread.sleep(2000);
es una espera incondicional. Si su prueba se carga más rápido, igual tendrá que esperar. Entonces, en principio, usar implicitlyWait
es la mejor solución.
Sin embargo, no veo por qué implicitlyWait
Espera no funciona en su caso. ¿ findElement
si el findElement
realidad lleva dos segundos antes de lanzar una excepción? De ser así, ¿puedes intentar usar la espera condicional de WebDriver como se describe en this respuesta?
Respuesta : espere unos segundos antes de que la visibilidad del elemento utilizando Selenium WebDriver vaya por debajo de los métodos.
implicitlyWait () : la instancia de WebDriver espera hasta la carga de la página completa. Debes usar de 30 a 60 segundos para esperar la carga de la página completa.
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
Espera explícitamente WebDriverWait () : la instancia de WebDriver espera hasta la carga de la página completa.
WebDriverWait wait = new WebDriverWait(driver, 60);
wait.until(ExpectedConditions.visibilityOf(textbox));
driver.findElement(By.id("Year")).sendKeys(allKeys);
Nota : utilice explícitamente el WebDriverWait () para manejar cualquier WebElement en particular.
Thread.sleep(1000);
es peor: al ser una espera estática, hará que el script de prueba sea más lento.
driver.manage().timeouts.implicitlyWait(10,TimeUnit.SECONDS);
esta es una espera dinámica
- es válido hasta la existencia del disco web o tiene un alcance hasta la duración del controlador
- también podemos esperar implícitamente.
Finalmente, lo que sugiero es
WebDriverWait wait = new WebDriverWait(driver,20);
wait.until(ExpectedConditions.<different canned or predefined conditions are there>);
con algunas condiciones predefinidas:
isAlertPresent();
elementToBeSelected();
visibilityOfElementLocated();
visibilityOfAllElementLocatedBy();
frameToBeAvailableAndSwitchToIt();
- También es una espera dinámica
- en esto, la espera solo será en segundos
- tenemos que usar espera explícita para un elemento web particular en el que queremos usar.
Thread.sleep(5000);
Esto sí me ayudó, pero la excepción InterruptedException necesita ser atendida. Así que mejor rodearlo con try y catch:
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
O
Agregar declaración de lanzamientos:
public class myClass {
public static void main(String[] args) throws InterruptedException
{ ... }
Preferiría el segundo ya que uno puede usar sleep()
tantas veces como lo desee y evitar la repetición de try
y catch
block cada vez que se use sleep()
.
public static void waitForElement(WebDriver driver)throws Exception {
driver.findElement(By.xpath("//table")).sendKeys //line1(org.openqa.selenium.Keys.CONTROL);
Thread.sleep(500);
}
Use este código en caso de que la página se actualice cuando cambie el control de un campo de entrada a otro campo de entrada dentro de la misma página. Pase la referencia del controlador correspondiente a este método para encontrar el elemento. Line1 se usa para hacer clic afuera que hace la actualización. Si tiene alguna consulta, publique su comentario.