Pourquoi devrais-je utiliser @FindBy
vs driver.findElement()
?
@FindBy
m'oblige à déplacer toutes mes variables au niveau de la classe (lorsque la plupart d'entre elles doivent seulement être au niveau de la méthode). La seule chose qui me semble acheter, c’est que je peux appeler PageFactory.initElements()
, qui gère pour moi l’initialisation paresseuse.
Qu'est-ce que je rate?
Grosso modo, @FindBy
n’est qu’un moyen alternatif de rechercher des éléments (la "manière habituelle" étant driver.findElement()
comme vous l’avez dit).
Le gros avantage de cette annotation n'est cependant pas en soi. Il est préférable de prendre en charge le PageObject pattern.
En quelques mots, le modèle PageObject vous indique de créer une classe pour chaque page du système que vous essayez d'utiliser/test.
Donc, au lieu d’avoir (le code driver.findElement()
habituel):
public class TestClass {
public void testSearch() {
WebDriver driver = new HtmlUnitDriver();
driver.get("http://www.google.com/");
Element searchBox = driver.findElement(By.name("q"));
searchBox.sendKeys("stringToSearch");
searchBox.submit();
// some assertions here
}
}
Vous définiriez une classe pour la page (avec l'annotation @FindBy
pour les éléments utilisés):
public class GooglePage {
@FindBy(how = How.NAME, using = "q")
private WebElement searchBox;
public void searchFor(String text) {
searchBox.sendKeys(text);
searchBox.submit();
}
}
Et utilisez-le comme:
public class TestClass {
public void testSearch() {
WebDriver driver = new HtmlUnitDriver();
driver.get("http://www.google.com/");
GooglePage page = PageFactory.initElements(driver, GooglePage.class);
page.searchFor("stringToSearch");
// some assertions here
}
}
Maintenant, je sais que cela peut sembler verbeux au début, mais laissez-le un instant et pensez à avoir plusieurs cas de test pour cette page. Et si le nom de la variable searchBox
change? (Du name
"q"
à un id
, dites query
?)
Dans quel code il y aurait plus de changements pour le faire fonctionner à nouveau? Celui avec ou celui sans les objets de page (et @FindBy
)? Si une page change beaucoup de structure, en quel code la maintenance serait plus facile?
Il existe d'autres avantages, tels que des annotations supplémentaires telles que:
@FindBy(name = "q")
@CacheLookup
private WebElement searchBox;
Ce @CacheLookup
rend la recherche de l'élément effectuée une seule fois. Après cela, il sera mis en cache dans la variable et accessible beaucoup plus rapidement.
J'espère que cela t'aides. Pour plus de détails, assurez-vous de vérifier PageFactory et le PageObject pattern.
Je n'aime pas les annotations @FindBy car, dans ce cas, IntelliJ ne détecte plus si cette variable est utilisée, ce qui rend le nettoyage difficile.
import org.openqa.Selenium.WebElement;
import org.openqa.Selenium.support.FindBy;
public class CommonPageForStudent {
@FindBy(name="usname")
private WebElement Studentusername;
@FindBy(name="pass")
private WebElement Studentpassword;
@FindBy(xpath="//button[@type='submit']")
private WebElement StudentLetmein;
@FindBy(id="logoutLink")
private WebElement StudentlogoutLnk;
public void loginToStudent(String username , String password ){
Studentusername.sendKeys(username);
Studentpassword.sendKeys(password);
StudentLetmein.click();
}
//when you call this methods from another class write this 2 line code that class
//CommonPageForStudent page = PageFactory.initElements(driver, CommonPageForStudent.class);
// page.loginToStudent("","");
public void logOut(){
StudentlogoutLnk.click();
}
//page.logOut(); method call
}`
L’un des avantages de l’utilisation de Page Factory est qu’elle permet d’éviter les StaleElementException . Veuillez consulter le lien ci-dessous:
Comment le modèle d'objet de page résout une exception StaleElementReferenceException?
Extraits du lien ci-dessus:
Vous constaterez que les programmes fonctionnent correctement lorsque nous utilisons le modèle de conception d’objet de page . Vous n'obtiendrez jamais d'exception de référence d'élément obsolète. Lorsque nous utilisons FindBy annotation dans POM, webdriver localise l’élément et le met à jour référence à chaque fois avant d'effectuer toute action sur cela. Vous pouvez utiliser élément Web sans déplacer aucun où. Ceci est un avantage majeur de Utilisation du modèle d'objet de page .
Comment se battre et éviter les éléments obsolètes.
Extraits du lien ci-dessus:
Comment combattre et éviter les éléments périmés
Il existe de nombreuses façons de traiter l’exception d’éléments obsolètes sur le Web. Ici, j'ai rassemblé ceux que je trouve personnellement les plus utiles.
Une bonne pratique consiste à utiliser l'annotation @FindBy en raison de Lazy Initialisation De cette façon, les éléments seront initialisés juste avant utilisation réelle. Exemple: @FindBy (xpath = "someXpath") WebElement public someElement;
Utilisez des méthodes d'attente pour JavaScript, Ajax, Jquery, etc. Cela résoudra le problème La «condition de concurrence» à l'origine de cette exception.
En termes simples, @FindBy
et driver.findElement()
sont des approches différentes pour localiser un ou plusieurs éléments à travers différentes stratégies de localisateur .
Lors de l'utilisation de PageFactory, nous pouvons utiliser le Type d'annotation FindBy . Les annotations FindBy nous aident à supprimer le code boiler-plate que nous utilisons généralement sous la forme de findElement()
et findElements()
lors de la recherche d'éléments.
Par exemple:
WebElement element = driver.findElement(By.name("q"));
element.click();
devient:
element.click();
Vous pouvez trouver les commentaires de @Simon Stewart sur le même sujet dans la discussion Comment utiliser les attentes explicites avec les champs PageFactory et le modèle PageObject }