One of our large enterprise clients develops user-facing experiences using AEM (Adobe Experience Manager). With AEM, developers can author a page using various components (think of it as “WordPress for enterprises”).
AEM consists of Author and Publisher instances. Each is a server that listens to ports 4502 and 4503 respectively. The author instance is used for developing and staging pages with content. Using various components, a developer can greatly customize a web page. It’s common to see each team develop their own components to build on top of the existing functionality. A “parsys” is an area that acts as a canvas for adding components on the page. Developers can edit the default properties of each component by updating respective fields in a dialog modal. Once the page is ready to go, a developer clicks “activate” on the site admin management interface of the page. This uploads the page to the Publisher instance and makes it live and available to the public.
How do we test that the AEM web page is available and is performing as expected? How can we do it in an automated fashion?
There’s always the option to use Selenium WebDriver to interact with the page and couple it with some sort of unit test framework that would act as a test runner. However, let’s discuss what alternatives we might have.
AEM ships with a build-in test framework called HobbsJs. Although it’s typically a good idea to use the test framework that is shipped with a development environment, I would argue that’s not the case here. Hobbs has a number of limitations. To begin, it seems it can only be used in Developer mode, so it’s only beneficial for testing preconfigured component properties. We can’t test authoring or publishing. It’s impossible to access the navigation bar when you need to switch between different modes.
Bobcat test framework is a different story. It’s an AEM-centric product. Therefore we were pleased to find a lot of features that help to drive the page test automation. Think of it as a great combination of Selenium WebDriver plus helpers to perform AEM-specific actions.
On the authoring side, Bobcat test framework supplies methods to manage page creation, activation, and deletion. It also checks if it’s present in the sideadmin tree. Use siteadminPage instance variable for that.
Ideally you would want to create a test page before each individual scenario, use it, and destroy it at the end of the scenario regardless of whether it finished with success or failure. You can achieve this setup using before and after scenario hooks.
Given that the page is open, we can use other Bobcat helpers to interact with parsys by dragging or removing components. Once the component is on the parsys, we can edit its properties. Again all of this is done programmatically using the helpers provided (no coding necessary).
The webdriver.properties file tester can specify settings for webdriver “capabilities” and default page timeout time. In the instances.properties files, we can provide Bobcat test framework with AEM instance URLs and login information. It’s not a great idea to hardcode the latter, so we suggest supplying it during runtime by injecting it into the system properties hashmap.
Logging into the siteadmin page is also easy. Given that credentials are supplied during runtime and stored in author.login and author.password respectively, Bobcat simply adds a cookie to the browser and we’re in. No need to actually type login information or pressing the Sign In button.
Use aemLogin.authorLogin() for that.
If you find yourself in the situation where Bobcat test framework doesn’t have a specific helper for your task, you can still use Selenium. Simply call methods on the webdriver instance variable. For example, we developed a method to exclusively deal with navigation bar and switch between user modes.
Once that was done, we were able to do the authoring part and immediately perform publisher side validation by switching to the Preview mode. Neat!
Authors of the Bobcat test framework made a good effort to provide extensive documentation of features and functionality on the Wiki page. However, we still found the material to be outdated, and the examples would not work right off the bat.
Going One Step Further with Cucumber
For our test framefork implementation we used a setup of JUnit + Cucumber + Bobcat.
Cucumber is a tool for driving scenario execution and to manage reporting. Each scenario is written in the Gerkhin language. It features usage of Given, When, Then, And keywords to start each phrase.
“Given I have this state, when I do something, then I should see something.”
That’s the general idea behind describing software behavior using this language. It’s commonly referred to as BDD or Behavior-Driven Development. Cucumber can match (using a RegEx engine) each Gherkin phrase with the respective block of code (step definition) written in any major coding language and then execute it.
Cucumber also supports tags. In fact this is one of its strongest features. Using tags you can include or exclude various scenarios and come up with custom run configurations based on your current needs. (You can learn more about Cucumber here.)
The sole purpose of using JUnit in the above setup is to kickstart Cucumber. For that we implemented this minimalistic TestRunner.java class:
Cucumber Meets Behavior-Driven Development
Personally, the main reason to use behavior-driven development (BDD) is to provide across-the-team visibility for testing scenarios. With the Cucumber framework, we are able to describe a user story in plain English. Now both technical and non-technical people can easily understand the test case simply by reading .feature files. It’s no longer exclusively a coding expert’s role to make a list of the currently automated scenarios and compare it with acceptance criteria generated during Sprint Planning meetings. In fact the these two should match by the end of the Sprint.
Using Bobcat Test Framework
Based on our experiences during client uplifts, we have concluded that it’s crucial to drive processes in each team. These processes help teams better understand the committed feature set for each sprint, as well as a methodically selected toolset. Using BDD and Bobcat test framework allowed us to not only rapidly develop AEM-centric test suites for multiple teams but also provide clarity for both technical and non-technical members.