Automation Testing with Selenium and Adobe Experience Manager (AEM)
Technology | April 06, 2021
Testing is a crucial stage not only in software development but also in every other industry. The clothes we wear, the food we eat, the toothbrush we use, even in this pandemic time (no pun intended) everything goes through some or other kind of testing to ensure product safety, quality, and our trust in companies.
As per the definition,
"Software testing is an investigation conducted to provide stakeholders with information about the quality of the software product or service under test."
Practically, the number of test cases even for a small piece of code or software could be infinite. Thus, stakeholders and the QA team generally agree upon the cases which are feasible to cover in a given timeline.
It is not practically possible to cover a large number of test cases manually. Eventually, teams started to automate the tasks which are repetitive and could be abstracted to run for future developments. This saves time for some complex testing scenarios which are not easy to automate. Also, it gives an assurance to stakeholders that the quality of testing is uniform across all the test cases. This combined with automated deployment led to Continuous Integration/Continuous Delivery (CI/CD). CI/CD has improved the development cycles to great extent by reducing the responsibilities of manual deployment and unit testing. In addition, it has reduced the time to the market and has given confidence to stakeholders before each release. Today we will see how we can automate the test cases with Selenium, TestNG, and Adobe Experience Manager.
- Steps to perform it
- And data to verify the results.
Here, we will use Selenium with Java to write the steps and AEM to store our data to compare the results. This data we generally call “Test or dummy data” which gets used to compare and verify the output of a test.
- Selenium framework to parse and access HTML pages and components
- AEM to store the data
- TestNG to simplify and reuse the code for multiple test cases
Selenium is a free (open-source) automated testing framework used to validate web applications across different browsers and platforms. It can be used with multiple programming languages like Java, C#, Python, etc. to create Selenium Test Scripts. Other than that, Selenium offers a suite of software and the following tools to deal with different testing requirements:
- Selenium WebDriver
- Selenium IDE
- Selenium Grid
Learn more about Selenium here.
To set up a project, we will use Maven. Maven is a build automation tool that is used to manage the project dependency and the whole project lifecycle.
Run the following command to generate a quick start maven project:
mvn archetype:generate -DgroupId=<package-name> -DartifactId=<project-id> -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
Then add these dependencies:
Selenium: The main framework for writing testing scripts
<dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>4.0.0-alpha-7</version> </dependency>
TestNG: Managing multiple tests and their lifecycle
<dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>7.4.0</version> <scope>test</scope> </dependency>
Apache POI: Reading and writing into excel files
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>5.0.0</version> </dependency>
And replace the build configuration with the following: This build configuration has Maven compiler and surefire report plugin which helps to compile the test classes and generate a test report, respectively.
<build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>3.2.1</version> <executions> <execution> <id>attach-sources</id> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M5</version> </plugin> </plugins> </pluginManagement> </build>
Or you can simply download the following zip which has everything set up with Maven wrapper.
Now, as we have set up the initial project, let's start with package structure and code abstraction.
While setting up the package structure we need to take care of the following points:
- Maximum code abstraction: As testing consists of many repeatable actions which could lead to code duplication. Therefore, to avoid that, we need to create classes and stick to the single-responsibility principle.
- Separation of test action implementations from the actual test class: As tests contain steps and complex logic to perform a particular action on a browser like clicking on a button, adding a text in an input field, etc. It makes code more difficult to manage and debug. Better way is to keep logic implementation in a POJO class and refer to its method in the test classes, which makes code more readable and structured. For this, try to create an interface or abstract classes of different HTML components or data models.
We can follow a similar package and code structure as shown below: Main Modules (POJO class package structure):
- base/core: This consists of some basic interfaces or classes which contain the members that are always required for any test like web driver, page URL and test name.
- utils: This package should contain some util classes which are required for some intermediate operations on the data or reading it from some file. These tasks generally contain reading data from Excel or some other API/URL, taking a screenshot of a page, comparing screenshots and some business logic to calculate actual data based on different inputs.
- constants: This contains the abstract constant classes which used across different test cases.
- factory: This package will manage classes suitable for the factory pattern, i.e. just require a single instance of it, and then it provides data according to the requirement. Like Web driver provider, which can have multiple methods to get browser-specific drivers and a single class manages its life cycle. Also, another example is a class to provide configuration properties from YAML or properties' files.
- components/entities: This includes individual HTML component models like breadcrumb/navigation, banner and image gallery.
- Separate package for similar/inherited components: While developing different components in AEM or any other project, we generally inherit some base components so, for this package, we can group these types of components sharing similar functionalities. For example, different calculators.
- pages: It is always better to keep separate “pages” package to manage different pages based on a fixed set of templates. We can maintain a class for each one of the templates and manage their dependencies, components individually.
Test Module (Actual test cases utilizing logic from POJO classes): Combine similar test cases and keep them in the same package.
TestNG is also an automation testing framework mainly used to generate test reports, setting up test case sequences, and reusing classes and methods to run with different parameters and test data. This makes managing test cases very easy and reduces development time. Also, it provides extensive OOTB APIs that reduce the boilerplate code. To reuse the test classes try to generalize the implementation and then we can call it from test suites XML with different parameters. Additionally, keep separate suites for respective environments to easily manage the environment-specific data and changes. Utilize different annotations to control test methods on the atomic level.
The last but not the least requirement is to manage the test data. As we are developing these test cases with AEM, we have a very big advantage as AEM is an omnichannel CMS implementing a repository structure. Thus, storing any kind of data is very easy and can be made available in different forms. Many teams keep this test data in excel sheets which we can be maintained in AEM Digital Asset Manager (DAM) and fetch it as per the need in the code. However, this adds complexity as file size and editing becomes tedious. So, a user friendly way of creating and updating the data is an implementation of page where a user can directly edit the data which can be fetched easily as a JSON response in the code. This we can make possible easily with the help of the ACS commons List tool which provides the functionality to create and edit data dynamically.
To create a test data page, follow the steps given below:
- Download latest version of ACS Commons from here
- Follow steps mentioned on this page to create a test data page of key and values.
- We can also customize this page to add more fields.
Then we can create a servlet which will take a test page path as an input and return a JSON array of test data values. ACS Commons Generic List provides the following JAVA APIs to convert list data to JAVA List.
// First obtain the com.day.cq.wcm.api.Page object for the test data list page: PageManager pageManager = resourceResolver.adaptTo(PageManager.class); Page listPage = pageManager.getPage("/etc/acs-commons/lists/targets"); // Then adapt the Page object to a com.adobe.acs.commons.genericlists.GenericList object: GenericList list = listPage.adaptTo(GenericList.class); List<Item> items = list.getItems(); String json = new Gson().toJson(items); return json;
This reduces the manual editing and updating of the excel files and provides a uniform way to manage the data. Also, if we integrate the test suite with some CI/CD build managers like Jenkins or even with Gitlab pipelines, then we can create a user-friendly UI to trigger the tests directly from AEM and also can download the results directly through UI. This makes stakeholders less dependent on the QA team for live status.
To integrate the test cases we need to configure pipelines of the respective Repository/version control system or set up some build automation tools like Terraform or Jenkins. Nowadays, all the Git repository providers come with CI/CD pipeline integration that are easy to configure using a configuration file. For more info follow Gitlab
It is high time to move towards automation testing as the time to market is getting reduced and teams are focusing more on product features and improvements rather than managing the builds and deployments. Also, it ensures that the environment will not get blocked because of the builds containing bug. Robust approach could be achieved towards the delivery and CI/CD.
- Maven: https://maven.apache.org/
- Selenium: https://www.selenium.dev/
- TestNG: https://testng.org/doc/