Recently I needed to increase the information the NoSuchElementException contained when using Selenium’s @FindBy annotation. During this I stumbled across a way to get access to the By class created from the @FindBy.
For example say we have the following PageObject
public class testPageObject { @FindBy(css = "h1[name='test']") WebElement testElement1; @FindBy(xpath = "//*[class='test']") WebElement testElement2; @FindBy(id = "test") WebElement testElement3; public testPageObject() { //Cache the WebElements using a 5 second wait PageFactory.initElements(new AjaxElementLocatorFactory(driver, 5), this); } public void printBy() { By testElement1 = getBy("testElement1"); By testElement2 = getBy("testElement2"); By testElement3 = getBy("testElement3"); System.out.println(testElement1); System.out.println(testElement2); System.out.println(testElement3); } private By getBy(String fieldName) { try { return new Annotations(this.getClass().getDeclaredField(fieldName)).buildBy(); } catch (NoSuchFieldException e) { return null; } } }
The solution is to use Selenium’s built in Annotations class which takes a field and call buildBy() to return the By class for that field.
The output of the printBy() function:
By.selector: h1[name=’test’]
By.xpath: //*[class=’test’]
By.id: test