This guide will help you migrate from WebTester v1.x to WebTester 2.x. There are a lot of breaking changes. Most of them on a conceptual level, following features introduced by Java 8.
The main difference between v1.x and v2.x is the move away from classes to a
more declarative approach based on interfaces. In addition the concept of
PageObject
was split into two different concepts: Page
and PageFragment
.
Preparing technical preconditions
If you did’nt already consider the switch to WebTester 2.x due to upgrading to JDK8, please make sure you have JDK8+ and compile to language level 8+.
Further following dependencies have to be adjusted:
-
If you upgrade to WebTester 2.1 or above you have to remove the browser module dependencies, as they are baked into the core from 2.1 onward. This change necessitates the re-import of the browser factories which no reside in
info.novatec.testit.webtester.browser.factories
. -
If you also switch from Junit 4 to Junit 5 you have to include the Junit-5-support-module instead.
@IdentifyUsing / @FindBy
The @IdentifyUsing
annotation has changed significantly:
-
The default
value
interpretation has changed fromID
toCSS Selector
. -
Instead of setting a
Method
enumeration value for themethod
attribute, you now set a class reference to aByProducer
implementing class on thehow
attribute. -
The
elementname
attribute was moved into the new@Named
annotation.
The Selenium annotation @FindBy
is no longer supported in WebTester v2.x
since it can’t be used on methods.
Pages
In WebTester v2.x
Pages
represent the context of the whole currently displayed
page. In v1.x
these were the root Page Objects
.
WebTester v1.x
page model represented as a PageObject
:
public class LoginPage extends PageObject {
@IdentifyUsing ( "username" )
TextField usernameField;
@IdentifyUsing ( "password" )
PasswordField passwordField;
@IdentifyUsing ( "login" )
Button loginButton;
@PostConstruct
void assertThatCorrectPageIsDisplayed () {
assertThat(getBrowser().getPageTitle(), is("TestApp: Login"));
}
public LoginPage setUsername (String username) {
this.usernameField.setText(username);
return this;
}
public LoginPage setPassword (String password) {
this.passwordField.setText(password);
return this;
}
public WelcomePage clickLogin () {
this.loginButton.click();
return create(WelcomePage.class);
}
}
WebTester v2.x
page model represented as a Page
:
public interface LoginPage extends Page {
@IdentifyUsing("#username")
TextField usernameField();
@IdentifyUsing("#password")
PasswordField passwordField();
@IdentifyUsing("#login")
Button loginButton();
default LoginPage setUsername (String username) {
this.usernameField().setText(username);
return this;
}
default LoginPage setPassword (String password) {
this.passwordField().setText(password);
return this;
}
default WelcomePage clickLogin () {
this.loginButton().click();
return create(WelcomePage.class);
}
}
Migration Steps:
-
Change all page
classes
tointerfaces
. -
Instead of extending
PageObject
they should extend thePage
interface. -
Change
fields
tomethods
. (e.g.TextField usernameField;
toTextField usernameField();
) -
Change all simple
@IdentifyUsing("some-id")
annotation values to@IdentifyUsing("#some-id")
. (Inv1.x
the default interpretation was as anID
, inv2.x
it is interpreted as aCSS Selctor
) -
Change
public
methods todefault
interface methods.
Page Fragments
In WebTester v2.x
Page Fragments
represent the context of a part of the currently
displayed page. This might be a whole section consisting of multiple HTML elements
or just a simple Button
. In v1.x
these were all non-root Page Objects
.
WebTester v1.x
<img>
model represented as a PageObject
:
@Mapping(tag = "img")
public class Image extends PageObject {
public String getSourcePath() {
return StringUtils.defaultString(getAttribute("src"));
}
public Image click() {
getWebElement().click();
return this;
}
}
WebTester v2.x
<img>
model represented as a PageFragment
:
@Mapping(tag = "img")
public interface Image extends PageFragment, Clickable<Image> {
@Attribute("src")
Optional<String> getSourcePath();
}
Migration Steps:
-
Change all page
classes
tointerfaces
. -
Instead of extending
PageObject
they should extend thePageFragment
interface. -
Attribute data getter methods can be simplified to an annotation based method without a body.
-
Common trades, like being
Clickable
can be inherited by also extending that interface. -
Wrapper
Page Fragments
(a page fragment containing several other page fragments) can be designed like the abovePage
example by replacing fields with method declarations. -
Change
public
methods todefault
interface methods.
Browser
The Browser
abstraction was refactored by splitting related functionality into own classes accessible
through methods of a Browser
.
Taking a Screenshot with WebTester v1.x
:
browser.takeScreenshot();
Taking a Screenshot with WebTester v2.x
:
browser.screenshot().take()
For the full set of methods for the Browser
, please refer to our documentation.