At Wix engineering, we’ve found that in most cases we don’t need a NoSQL database, and that MySQL is a great NoSQL database if it’s used appropriately.
Selenium WebDriver is widely used as a first-choice framework when it comes to testing web applications. In this article I would like to introduce you to two design patterns, that work great with selenium tests. In this post we will dig into Page Object pattern and combine it with Page Factory. As always, whole code for project is available on my github. Page Object Pattern Page Object is a concept that helps to reduce the number of duplicated code, and helps with test maintenance, resulting from changes in the structure and functionality of the web application. The main idea behind page object is to place the code relating to the functionality of subpages in separate classes. In a very simplified way, if your web application includes pages: home about contact We should create three separate page object classes: Home.java About.java Contact.java Each class should contain only those methods that support functionality for the corresponding subpage, and define selectors only for this subpage. We should also remember, that public methods in page object class are only those, that represents user’s workflow. One important point is that each public method in page object class should return object of page that user is on. For example, if a button on the page does not gets you to different subpage, this method should return this. Moreover, if a button is a link to another page, the method should return page object class of this subpage. Here is a code snippet of this approach using an example from previous article, where we wrote tests for Facebook login: public class LoginPage { private static By userEmailLoginInput = By.id("email"); private static By userPasswordLoginInput = By.id("pass"); private static By loginSubmitBtn = By.id("u_0_n"); private WebDriver driver; public LoginPage(WebDriver driver) { this.driver = driver; driver.get("http://facebook.com"); } public LoginPage enterUserLogin(String login) { WebElement emailBox = driver.findElement(userEmailLoginInput); emailBox.click(); emailBox.sendKeys(login); return this; } public LoginPage enterUserPassword(String password) { WebElement passwordBox = driver.findElement(userPasswordLoginInput); passwordBox.click(); passwordBox.sendKeys(password); return this; } public HomePage submitLoginCredentials() { WebElement submitBtn = driver.findElement(loginSubmitBtn); submitBtn.click(); return new HomePage(driver); } } In above example, methods enterUserLogin() and enterUserPassword() don’t transfer user to another subpage, but perform activities on the login page, so return type is object of LoginPage class (this). On the other hand, submitLoginCredentials() method moves user to home page (or to the page informing about the login failure), so it returns home page class object. In real life example, in HomePage.class we would have had methods that perform actions on the home page, but since it’s only an example code demonstrating pattern usage, we have only checkIfLoginSucceed() method here: public class HomePage { private WebDriver driver; public HomePage(WebDriver driver) { this.driver = driver; } public boolean checkIfLoginSucceed() { return driver.getPageSource().contains("fbxWelcomeBoxName"); } } …and test looks as follows: @Test public void shouldNotLoginWithIncorrectCreds() { LoginPage loginPage = new LoginPage(driver); loginPage.enterUserLogin("wrong@login.com"); loginPage.enterUserPassword("wrongPassword"); HomePage homePage = loginPage.submitLoginCredentials(); assert (!homePage.checkIfLoginSucceed()); } Page Factory pattern The main idea behind this pattern is to support page object classes, and to allow better page selectors management. Page Factory provide us with a set of annotations, which work great with selectors and enhance code readability. To understand this, let’s look at a standard initialization webelement through the selector: private static By email = By.id(“email”); WebElement emailBox = driver.findElement(email); Unfortunately, the readability leaves much to be desired. The problem is also that variable with selector and web element object require a separate initialization. Along with Page Factory, this is greatly simplified: private WebElement email; That’s all! Page Factory search page source code for element with id=”email” by default and assigns it to declared webelement. Of course, this minimalism can introduce some confusion, and therefore I recommend the use of @FindBy annotation: @FindBy(id = “email”) private WebElement userEmailLoginInput; We can also search selectors by other attributes, such as xpath, name, className, etc. Everything we have to do to use this pattern, is to initialize PageFactory in the page object class constructor: PageFactory.initElements(driver, this); Our LoginPage.class with page factory pattern will look like this: public class LoginPage { @FindBy(id = "email") private WebElement userEmailLoginInput; @FindBy(id = "pass") private WebElement userPasswordLoginInput; @FindBy(id = "u_0_n") private WebElement loginSubmitBtn; private WebDriver driver; public LoginPage(WebDriver driver) { this.driver = driver; driver.get("http://facebook.com"); PageFactory.initElements(driver, this); } public LoginPage enterUserLogin(String login) { userEmailLoginInput.click(); userEmailLoginInput.sendKeys(login); return this; } public LoginPage enterUserPassword(String password) { userPasswordLoginInput.click(); userPasswordLoginInput.sendKeys(password); return this; } public HomePage submitLoginCredentials() { loginSubmitBtn.click(); return new HomePage(driver); } } Important thing to notice is that every time we call a method on web element, page factory search for our element all over again through page sources. If page isn’t AJAX-based, we can use page factory cache to search an element only with page factory initialization, and then retrieve it from cache: @FindBy(id = “email”) @CacheLookup private WebElement userEmailLoginInput; Summary As in every aspect of software development, design patterns in test automations help us to develop tests faster and more efficient. Page Object and Page Factory are two simple patterns, that significantly improve maintenance and readability of selenium tests. For complete sources of examples in this article please visit my github. If you have any questions, feel free to leave a comment!
Calling all HTML5 game developers! The 2015 js13kGames competition is set to kick off, Think you can make an awesome HTML5 game in just 13kb? Test your mettle here.
This interview covers topics from lambdas in Java 8, to the sun.misc.Unsafe controversy, to VarHandle in Java 9, to the work of Chronicle Software, which is amazing.