I'm working on webtests at the moment, using a WebDriver to simulate a browser. This WebDriver has to find HTML elements pretty often, many of them often being the same (i.e. a certain button, form field, etc.). The WebDriver needs an object of Selenium's By
class, to use findElement()
.
I figured it would be nice for readability and adaptability, if there was an enum or interface storing configured instances of By
, which may be used to locate the element. In tests, repeatedly hard-coding findElement(By.id("elementid"))
turns into findElement(WebGui.Login.SUBMIT_BUTTON)
, where WebGui.Login.SUBMIT_BUTTON
may return an instance of By
searching for an ID, name, CSS class, etc. whatever is neccessary without concerning the test itself which just needs the element.
Question A hierarchical structure seems optimal to represent different sections of the website, however enums can't inherit anything. Which way is the most clean way and/or best practice?
Nested Enum As enums can't inherit getBy()
and the constructor, so they must be defined in every nested enum, thus being more redundant code.
public enum WebGui {
BUTTON1(By.id("button1")),
SEND_BUTTON(By.name("sendButton"));
private By searchCriteria;
WebGui(By by) {
searchCriteria = by;
}
public By getBy() {
return searchCritera;
}
private enum SubPage {
BUTTON2(By.id("button2")),
SEND_BUTTON(By.linkText("Send"));
private By searchCriteria;
WebGui(By by) {
searchCriteria = by;
}
public By getBy() {
return searchCritera;
}
}
}
Nested Interfaces/abstract classes Using this seems less "clean", doesn't provide type safety (although not too relevant here) and is often refered to as bad practice, because storing a fixed set of available constants is an enums purpose.
Edit Nested Interfaces can't be private, therefore changed outer interface
to abstract class
public abstract class WebGui {
By BUTTON1 = By.id("button1");
By SEND_BUTTON = By.name("sendButton");
private interface SubPage {
By BUTTON2 = By.id("button2");
By SEND_BUTTON = By.linkText("Send");
}
}
As nested Interfaces are much less code and its members don't need functions, using it seems to be the better choice, but how much of a bad practice is this, compared to nested enums containing redundant code.