This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Welcome to Test Automation with Qadenz!

Qadenz is a robust test automation library written in Java that wraps Selenium for browser automation, TestNG for suite management, and Hamcrest for validations. Using a mildly opinionated approach, Qadenz solves the common issues encountered while implementing the wrapper layer between the tests and accompanying UI models, and the underlying frameworks (like Selenium and TestNG).

The goal of Qadenz is to take the heavy lifting out of developing a test automation project, and allow teams to focus instead on rapid scripting of tests. This is accomplished by using an easy-to-learn API that encourages simple to read tests without using Gherkin/BDD-based tools that add unnecessary complexity and maintenance overhead to the development workload.

Core Features of Qadenz:

  • Boilerplate test setup and configuration is built and ready to use
  • Selenium element interaction functionality is wrapped in a simple to use API
  • A unique conditions-based approach to validations
  • Custom built-in HTML reporting that provides detailed results data along with integrated screenshots

Qadenz is also extensible and stands ready to support custom functionality based on the needs of the tests to be automated. The design patterns that Qadenz provides can quickly and easily be followed for seamless integration of team-specific features.

License

The Qadenz Library is made available under the PolyForm Internal Use License as a “Source Available” library. Teams are welcome to use Qadenz to power their internally managed test automation projects and modify as needed, but are prohibited from re-distributing the library or marketing/selling Qadenz (and derivative works of Qadenz) as a product for their customers.

1 - Philosophy of Use

The role in a test automation project of an intermediate API that wraps frameworks such as Selenium and TestNG is far from uncommon. Many teams realize the importance of an API layer for these underlying tools as a means of simply abstracting common code and building re-usable components for frequently utilized features of the base frameworks. Some teams will take this a step further and design a wrapper layer that works to unify the development approach and adopted design patterns within the test project, thus answering the question “What is the best way for our team to implement these tools?”

Unfortunately, we as testers frequently find ourselves in fast-paced and ever-evolving environments. Designing, building, and importantly, maintaining an API such as this can be as significant an effort as keeping up with the demands for expanding test coverage.

Objectives

To this end, Qadenz targets a number of core objectives…

  • Drive easy to read tests with a clearly worded API: Simply, readable code is manageable code. Everything from the API syntax to the logging and reporting output has been carefully chosen to maximize readability and to be as simple to understand as possible.
  • Reduce coding overhead by doing the heavy lifting: Selenium interactions with Qadenz can, with one method call, log the activity, initialize an element, perform an interaction against the element, handle exceptions with logging and reporting, and capture screenshots. By offloading this work to the library, users can focus on scripting their tests rather than sorting out all the supporting functionality.
  • Encourage efficient UI Modeling: Qadenz uses CSS Selectors exclusively due to maximized flexibility and easy of use. This is further enhanced by injecting SizzleJS to enable parameterized element selectors. CSS Selectors are versatile, simple to understand, and most importantly (well crafted selectors are) more resistant to change compared to XPath. Wrapping the element selectors on the Locator object also enhances reporting with friendly element names, and encourages teams to move beyond antiquated and inefficient patterns. Page Factory is old and busted. Simon even says so.
  • Provide flexible and precise validations: The Conditions-based validations functionality is custom to Qadenz and enables high levels of precision using the What/How relationship of Conditions and Expectations. Additionally, the Verify/Check language in the API allows for hard and soft assertions, which enables the user to decide exactly when a test will be halted following a failure. Finally, the iterative nature of Qadenz validations allows for multiple validations to be made in groups, providing a more complete picture of test failures and maximized potential for quickly exposing system issues.
  • Include detailed and easily shared reports: The emailable-report.html provided by TestNG is nice for basic pass/fail results, but leaves much to be desired when it comes to detail and user experience. Other reporting libraries add a lot of noise to the code, and don’t tend to coexist with standard logging frameworks. The Qadenz reporter is powered by Logback, is fully integrated with TestNG, and produces a singular HTML output file that contains full detailed results of each test and embedded screenshots of errors and failed validations.

Opinionation

Qadenz can be considered an opinionated library. Some features and solutions have been designed specifically to guide users into a particular pattern of usage based on certain best practices, or simply to speed up the development process for testers by choosing a particular path over another. While each is explained in greater detail elsewhere in the documentation, these points are the major areas of opinionation within the Qadenz library:

  • The WebDriver is scoped to the test method: By limiting the scope of the WebDriver session, Qadenz ensures that a fresh browser is used for each test case. This also has provided an avenue to tune the execution workflow.
  • Explicit Waits over Implicit Waits: Explicit Waits allow for precise conditions to be met within a given amount of time. Implicit waits are only time-based, and cause problems when used alongside Explicit Waits.
  • Sizzle CSS Selectors only: CSS Selectors are fast, extremely versatile, and resistant to DOM change. Adding Sizzle increases their versatility and adds a number of pseudo-classes that improve the ability to parameterize element selectors. This approach is a unified strategy that ensures all contributors to a test project are following the same pattern, which further enhances the ease of code maintenance.
  • Conditions-powered validations and Explicit Waits: The Conditions and Expectations consist of precise and clearly defined evaluations. These provide a unified alternative to both sorting through the variety of assertion types or ExpectedConditions for Explicit Waits. Additionally, these classes ensure consistent and detailed information are passed to the logs and report output.
  • Locator-based UI Modeling over Page Factory & @FindBy: PageFactory is an overly complex form of instantiating page objects. @FindBy does not support parameterization and mitigating issues like the StaleElementReferenceException requires additional code in order to tune and make reliable for a given web application. Locators support parameterization, provide a context-friendly element name for the logs, and a reference to a UI element that is later used by the WebCommander or WebInspector to initialize an element at the appropriate time of use.

A Turn-Key Solution

In the end, development efficiency and code maintainability are major success factors for automation teams. How quickly can we automate this next block of tests? Is the tooling reliable enough to ensure repeatable executions? Are the implementation details tribal knowledge, or is the code clear enough that a new developer can easily and quickly ramp up for maintenance? If the answers to these questions leads to increased efficiency and improved maintainability, then the investment in these tools becomes quite worthwhile.

Qadenz is built to satisfy the need for such tool-set, and allow testers to focus on the more important task… build tests quickly.

2 - Getting Started

Bootstrapping an automation project with Qadenz is as simple as starting a new Java/Maven project, adding a dependency, and building a simple test. This guide will run through the pre-requisites, and show how to build a simple first automated test that verifies the functionality of an authentication form.

The Foundation

Before we dive into a fresh project, let us first make sure we have the necessary tooling in place to do so.

Being a Java project, we’ll need a JDK. Qadenz is currently built with JDK 11, so an equivalent or newer version must be installed. Next is an IDE. This is completely a preference-based decision, but with the prevalence of IntelliJ IDEA, it is strongly recommended. The Community Edition is free to use and will be sufficient for automation development with Qadenz. Most IDEs come with Maven bundled, and IntelliJ is no different. This is perfectly functional, but can be known to exhibit some different behavior in certain situations than a native installation. It is recommended to install the latest Maven and configure the IDE to use the native instance instead of the bundled version. Finally, ensuring IDE support for things like TestNG and Maven can make working with these tools very convenient.

Next, since this is a test automation project, we’ll need to make sure some related tooling is in place. Qadenz is built to use the RemoteWebDriver, so the Selenium Server is a necessity. Chromedriver and the Chrome browser itself will also need to be in place. Other browsers are certainly supported, Chrome is simply a good starting point due to it’s dominant market share.

Package managers are a great way to install and update development tools. In a Windows environment, Chocolatey is a good option. For Mac, Homebrew is a great choice. Linux distros will have their own package systems baked in, and these tools are typically available through official repos.

The Framing

In the IDE, start a fresh Maven project. Open the pom.xml file and add the dependency information for Qadenz.

<dependency>
    <groupId>dev.qadenz</groupId>
    <artifactId>qadenz</artifactId>
    <version>2.0.0</version>
</dependency>

Next, create a Package and Class that can hold our first test, which will exercise the Form Authentication page at Heroku’s The-Internet app. To ensure this new class is recognized as an ran as a Qadenz Test Class, the class must extend AutomatedWebTest.

package com.herokuapp.theinternet;

public class FormAuthenticationTest extends AutomatedWebTest {

}

The Fixturing

Our first test will be to complete the form with a valid username and password, click ‘Login’, and verify the confirmation text that indicates successful authentication.

Let’s first take a peek at the Form Authentication page. In order to complete the test, we need to map the Username and Password fields, and the Login button.

Then, in the Secure Area, we’ll need to map the banner in order to verify the message.

On the FormAuthenticationTest class, create Locators for the elements with which the test will interact.

private Locator usernameField = new Locator("Username Field", "#username");
private Locator passwordField = new Locator("Password Field", "#password");
private Locator loginButton = new Locator("Login Button", "#login .fa-sign-in");

private Locator bannerMessage = new Locator("Banner Message", "#flash");

Next, add the test method. A WebCommander instance is created and commands are invoked to interact with the form and complete the steps of the test.

@Test
public void testAuthenticationSucceedsWithValidCredentials() {
    WebCommander commander = new WebCommander();

    commander.enterText(usernameField, "tomsmith");
    commander.enterText(passwordField, "SuperSecretPassword!");
    commander.click(loginButton);
    commander.verify(Conditions.directTextOfElement(bannerMessage,
            Expectations.isEqualTo("You logged into a secure area!")));
}

And finally, add a TestNG Suite XML file at the project root. The required parameters will tell Qadenz which browser to use for the test, the URL of the application, and where to find the Selenium Server.

<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >

<suite name="Qadenz Quickstart" verbose="1" thread-count="1">

    <parameter name="browser" value="chrome"/>
    <parameter name="appUrl" value="https://the-internet.herokuapp.com/login"/>
    <parameter name="gridHost" value="127.0.0.1"/>

    <test name="Login Test">
        <classes>
            <class name="com.herokuapp.theinternet.FormAuthenticationTest">
                <methods>
                    <include name="testAuthenticationSucceedsWithValidCredentials"/>
                </methods>
            </class>
        </classes>
    </test>

</suite>

The coding portion is now complete, the next step is to run the test and view the results.

The Finishing

Before the test can be launched, a Selenium Server must be started. When running tests locally, this can be easily done by launching the server in standalone mode. Open a command prompt and change to the directory where the Selenium Server jar is located, then run the following command…

java -jar selenium-server-4.10.0.jar standalone

Next, return to the IDE, right click the TestNG Suite XML file, and select Run. The suite will run, a browser will be launched, and the test will be executed. Once complete, the Logs and HTML Report will be available for review.

Console Logs

In the IDE, the console will display logs captured by the test run. The console logs will contain output from the SUITE logger, which shows information about the Suite in progress. This will include data such as XML <parameter> values, browser configuration arugments, and which test methods are being ran.

The TEST logger will show information from the actual test. For the login test, the following will be displayed…

21:06:57:620 | Thread: main | INFO | WebCommander | Entering text [tomsmith] into element [Username Field].
21:06:57:798 | Thread: main | INFO | WebCommander | Entering text [SuperSecretPassword!] into element [Password Field].
21:06:57:893 | Thread: main | INFO | WebCommander | Clicking element [Login Button].
21:06:58:149 | Thread: main | INFO | Commands | Verifying Condition - Direct text of element [Banner Message] is equal to [You logged into a secure area!].
21:06:58:274 | Thread: main | INFO | Commands | Result - PASS

Each line will contain a timestamp, a thread identifier, the logging level, the name of the logger, and the log message showing the details of each step of the test.

HTML Reports

Qadenz has a built-in HTML reporter that presents the logs from each test in a browser along with screenshots of failed validations and caught exceptions. The suite-results.html file is located in the test-output directory at the project root alongside the reports generated by TestNG.

The HTML report sorts test methods by result, then groups by class. Screenshots are embedded directly into the HTML as Base64 encorded Strings, which makes sharing test results extremely simple.