2013-07-23 7 views
5

Da un po 'di tempo utilizzo @FindBy e adoro il fatto che l'elemento non venga individuato finché non è necessario (non in istanza).Come restituire un elemento web dinamico istanziato pigramente

Tuttavia, la pagina web può avere ovunque 2-10 di un certo elemento, e l'ID del sugli elementi sono numerati (in modo che il primo elemento ha un ID di "elemento1" e così via)

lo farei piace scrivere una funzione in cui posso passare un intero, e restituirà un WebElement con l'ID appropriato, E viene istanziato pigramente. Questo significa avere una funzione come la seguente non funziona:

public WebElement getElement(int numOnPage){ 
    return driver.findElement(By.id("element"+numOnPage)); 
} 

Perché l'istante che io chiamo che funziona il WebElement ottiene trova. (Il motivo per cui non può essere istanziato è perché ho una funzione che aspetta fino a quando l'elemento esiste chiamando ripetutamente isDisplayed() sopra, prendendo NoSuchElementException s).

Mi rendo anche conto che potrei creare un List<WebElement> che seleziona tramite CSS ogni elemento il cui ID inizia con "elemento" ma ho avuto altri casi in cui ho voluto restituire un elemento generato dinamicamente e ho dovuto usare una soluzione alternativa anche lì.

Grazie!

risposta

1

In primo luogo, non capisco perché sia ​​assolutamente necessario ottenere un riferimento WebElement prima che l'elemento si trovi realmente nella pagina. In un caso normale, è possibile controllare che la pagina sia stata caricata completamente e quindi cercare un WebElement. In primo luogo sarebbe in genere fatto con un ciclo e una cattura per NoSuchElementException come hai menzionato.

Tuttavia, se è necessario un riferimento per un WebElement prima che non possa essere trovato nella pagina, vorrei semplicemente creare un proxy che carica pigramente (solo quando è necessario per la prima volta) l'istanza reale WebElement. Qualcosa di simile a questo:

public WebElement getElement(final int numOnPage) { 
     return (WebElement) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class<?>[] { WebElement.class }, new InvocationHandler() { 
      // Lazy initialized instance of WebElement 
      private WebElement webElement; 

      public Object invoke(Object proxy, Method method, Object[] args) 
        throws Throwable { 
       if (webElement == null) { 
        webElement = driver.findElement(By.id("element" + numOnPage)); 
       } 
       return method.invoke(webElement, args); 
      } 
     }); 
    } 

Chiamando getElement, si recupera un oggetto di tipo WebElement. Non appena chiami uno dei suoi metodi, verrà recuperato usando WebDriver.findElement. Si noti che, se si chiama un metodo sull'istanza proxy, l'elemento deve trovarsi nella pagina altrimenti si ottiene ovviamente un NoSuchElementException.

+0

La causa era che ho una funzione in cui chiamo isDisplayed() (con un try/catch) più e più volte ... ma se passo l'elemento restituito da getElement(), e l'elemento non esiste ancora, getElement() lancia l'eccezione prima che colpisca mai la funzione che sta aspettando che esista. Grazie! –

1

Se sto capendo correttamente la domanda, non è possibile farlo con l'annotazione @FindBy. Il problema è che le annotazioni in Java vengono elaborati durante la fase di compilazione e di conseguenza non si possono modificare al volo:

http://docs.oracle.com/javase/tutorial/java/annotations/

Ha, tuttavia suona come il problema potrebbe essere facilmente risolto utilizzando un'attesa esplicito:

public WebElement getElement(int numOnPage){ 
    WebDriverWait waiting= new WebDriverWait(driver, 15, 100); 
    return waiting.until(ExpectedConditions.visibilityOfElementLocated(By.id("element"+numOnPage))); 
} 

Questa sarebbe la scansione della pagina in attesa che l'elemento di esistere e di essere visibili e quando si tratta di restituire un WebElement a voi.

Problemi correlati