UI-Tests are one of the more tedious and volatile kinds of tests that need to be implemented. They are code intensive and extremely unstable. But since the UI is part of our applications there are some things we simply have to test. Thankfully there are best practices that allow us developers to somewhat mitigate these problems. The page-object pattern is one of them and the testIT WebTester Framework is build around this pattern.
In this article I’ll demonstrate how our WebTester framework helps you harness the full potential of the page-object pattern.
The Page Object Pattern is the basic design principle on which the testIT WebTester was build. Page Objects are classes that represent a page of your web application. They provide methods that allow the test developer to interact with the page without having to know any of the actual HTML or other implementation details of that page. They provide an abstraction layer that encapsulates the “How” an interaction with a web page is done and lets the test developer focus on the “What” to do with the application.
The testIT WebTester Framework is a best practice solution for testing web applications. It is based on the Selenium web testing framework and extends it with a streamlined type-save API for interacting with elements of your web application. The most prominent features are:
Interact with Buttons, Textfields and a whole lot of other element classes instead of a generic PageElement class.
Each element the Frameworks interacts with is highlighted, so you can see what a test does when you are watching it.
Extendable Event System
Each interaction with the browser produces events that can be listened for and handled as you see fit. Out of the box a debug listener is provided so you can attach interaction logs to bug reports.
Everything is a Page Object
Every element class you encounter is a page object. Page objects can be nested to any degree needed. This makes re-usability and custom component creation easier then ever.
Full Power of Selenium
Since the testIT WebTester is build on top of Selenium you can still use any functionality that Selenium provides.
You can either download the WebTester distribution from our FTP server or you can use our NovaTec public maven repository:
To demonstrate how WebTester can be used, lets assume we are working on a web application and are writing our first UI-Test. For most applications the first thing needed to test the UI is to be able to log into the system. For this we need to automate the login process.
For this scenario the login process starts with typing in a username and a password and pressing a button on a login page. In case the given credentials were correct the user is then redirected to a welcome page and shown a welcome message. If the credentials are incorrect no redirect is executed and an error message is displayed on the login page.
From this scenario the following information can be extrapolated:
Two page-objects are needed: login- and welcome-page.
The login-page consists of the following parts:
optional message component
The welcome-page consists of a welcome message.
There are two possible navigation paths for a login:
Credentials correct leads to the welcome-page.
Credentials incorrect stays on the login-page.
All page-object classes in the WebTester framework extend the base class PageObject. They need to be initialized with the PageObjectFactory class method createPageObject(…).
Sub elements like buttons or textfields are member variables of the class with the annotation @IdentifyUsing:
The default locator method of @IdentifyUsing is ID. This means all objects are identified by their HTML id.
The locator method can be changed with the property “method”.
Possible locator methods are: ID, XPATH, CSS, CLASS, NAME and TAGNAME
It is possible to use @IdentifyUsing on a member variable of type List<? extends PageObject>. In this case all elements of the page that fit the condition of the @IdentifyUsing annotation will be loaded into that list.
Important:All PageObject based classes are loaded lazily when first accessing any properties that actually need information from the browser.
To perform operations after a page object is initialized (like asserting that the correct page is displayed after a navigation) the annotation @AfterInitialization can be used on any non static method.
To test the login scenario we first need to initialize a browser using the BrowserFactory class. Since we want to use the same browser instance for each of our tests the initialization is done on class level. For each of our tests we navigate to the login page and initialize a fresh LoginPage object. After all tests are executed we close the browser.