Keyword-Driven Data Comparison for Consistent Test Automation
One of the best practices when working with the automation framework involves transforming frequently reused coding steps into keywords. This not only simplifies the code but also makes it more readable and maintainable. The use of keywords can significantly streamline the process of writing complex codes, as well as make it easier for other team members to understand the logic behind the code. This post provides a detailed walk-through of the process to implement such keywords in your code. It covers everything from identifying the frequently reused codes that can be transformed into keywords to the actual implementation of these keywords within the coding framework. The aim is to provide a comprehensive guide that will help you leverage the power of keywords in an automation framework.
Consider a scenario in which you've created a user with specific properties. To confirm the values are saved correctly, you can access them via an admin screen. The validation process involves comparing the input values during user creation with those shown on the admin screen.
In another scenario, a user selects a product during their shopping experience. To validate the product's properties consistently across all screens, compare the attributes of the selected product with those displayed on various screens.
Test automation, a vital component in the realm of software development, typically involves the practice of verifying if the values entered or selected on one interface are accurately reflected on another. This practice is crucial to ensure the correct functionality and consistency of the system. Given the scale of this task, especially in complex systems where a large number of fields require meticulous comparison, some practitioners may opt for a more comprehensive method of image comparison instead of the more laborious individual value comparison.
The process of individual comparison, although tedious, can be more accurate and generally involves three fundamental steps. The first step involves retrieving the initial data that was input or selected. This data is usually stored in a structured format, such as a JSON file or an environment variable, for ease of access and later comparison.
The second step is the extraction of the value from the element that is displayed on a different screen. This could be a form input, drop-down selection, or any other interactive element reflecting the previously entered or selected data.
The final step is the actual process of comparison. This involves taking the two sets of values, one from the original input and one from the subsequent screen, and comparing them to ensure consistency. This comparison leads to an assertion, which will determine if the test passes or fails based on whether the values match.
Through this meticulous process, test automation helps maintain the integrity and reliability of the system, ensuring that the user experience remains consistently high and free from any data inconsistencies or errors.
In certain scenarios, we may be bypassing the comparison or neglecting the assertion because of the extensive number of steps it involves. It can be quite a daunting task, especially when the complexity of those steps is taken into account. However, to streamline this process and make it more manageable, I employ the use of keywords. These aren't just any keywords, but ones that I have adopted from my previous project, Robot Framework. Robot Framework is an open-source automation framework that provides a systematic approach to the automation of keyword-driven testing. Using keywords from this framework not only simplifies the process but also ensures a higher degree of accuracy. Now, to give you a better understanding of how these keywords are used and how they function in this context, let's delve into an example.
import { Locator, Page } from '@playwright/test';
import {
compareTheField,
comparePhoneField,
compareDateAndTimeField,
compareCountryField
} from './fieldValidations.page';
export default class UserCreationPage {
page: Page;
emailValue: Locator;
addressLine1Value: Locator;
cityValue: Locator;
postalCodeValue: Locator;
createdAtValue: Locator;
phoneValue: Locator;
stateValue: Locator;
countryValue: Locator;
constructor(page: Page) {
this.page = page;
this.emailValue = this.page.locator('#email');
this.addressLine1Value = this.page.locator('#addressLine1');
this.cityValue = this.page.locator('#city');
this.postalCodeValue = this.page.locator('#postalCode');
this.createdAtValue = this.page.locator('#createdAt');
this.phoneValue = this.page.locator('#phone');
this.stateValue = this.page.locator('#state');
this.countryValue = this.page.locator('#country');
}
public validateTheUserFields = async (testCaseName: string): Promise<void> => {
await compareTheField(this.emailValue, testCaseName, 'email');
await compareTheField(this.addressLine1Value, testCaseName, 'address');
await compareTheField(this.cityValue, testCaseName, 'city');
await compareTheField(this.postalCodeValue,testCaseName, 'postcode');
await compareDateAndTimeField(this.createdAtValue);
await comparePhoneField(this.phoneValue, testCaseName, 'phone');
await compareTheField(this.stateValue, testCaseName, 'state');
await compareCountryField(this.countryValue, testCaseName, 'country');
};
}
compareTheField
, comparePhoneField
, compareDateAndTimeField
, and compareCountryField
are keywords used for comparison. They accept an identifier to extract text. The 'testCaseName' is used to uniquely identify the data and a JSON file key where the value is stored. With these saved and extracted values, comparisons and assertions can be made. You can extend the keyword to make soft assertions true by default and pass false when necessary.
public getStoredDataBasedOnTestCaseName = async (testCaseName: string, key: string): Promise<string> => {
const { dataToStore } = process.env;
const parsedData = JSON.parse(dataToStore || '{}');
return parsedData[testCaseName]?.[key];
};
const compareTheField = async (actualValue: Locator, testCaseName: string, key: string): Promise<void> => {
await expect
.soft(actualValue)
.toContainText(await this.getStoredDataBasedOnTestCaseName(testCaseName, key));
};
To easily access the keywords, they will be placed inside the POM folder on the same level as the pages or sections.
PROJECT-NAME
- page-object-model
- keywrods
- pages
- sections
My recent publication compiled a comprehensive collection of 100 similar typescript programs. Each program not only elucidates essential Typescript concepts and expounds upon the significance of test automation but also provides practical guidance on its implementation using Playwright. This resource will undoubtedly be valuable if you look deeper into similar topics.