How to use Builder design Pattern for test data generation in automation testing

Mohammad Faisal Khatri
7 min readSep 10, 2022
Photo by Markus Spiske on Unsplash

I bet you might have come across a scenario while Automating API/Web or Mobile Application where while registering a user or may be setting the address for checking out a product in the end to end user journey in test automation.

So, How do you do that?

Normally, We create a POJO class in Java with the fields required to register a user or to set the address for checking out the product and then set the values in the test using the constructor of the POJO class.

Let’s take an example of registering a user where following are mandatory fields required to fill in the registration form:

  1. First Name
  2. Last Name
  3. Address
  4. City
  5. State
  6. Country
  7. Mobile Number

As we need to handle these fields in automation testing we will have to pass on respective values in the fields at the time of executing the tests.

Before Using the Builder Pattern

A POJO class with the above mentioned mandatory fields will be created with the Getter and Setter methods inside that POJO class and using a constructor values are set in the respective fields.

Checkout the code example of RegisterUser class given below for the representation of what we are discussing

public class RegisterUser {
private String firstName;
private String lastName;
private String address;
private String city;
private String state;
private String country;
private String mobileNumber;

public RegisterUser (final String firstName, final String lastName, final String address, final String city,
final String state, final String country, final String mobileNumber) {
this.firstName = firstName;
this.lastName = lastName;
this.address = address;
this.city = city;
this.state = state;
this.country = country;
this.mobileNumber = mobileNumber;
}

public String getFirstName () {
return firstName;
}

public void setFirstName (final String firstName) {
this.firstName = firstName;
}

public String getLastName () {
return lastName;
}

public void setLastName (final String lastName) {
this.lastName = lastName;
}

public String getAddress () {
return address;
}

public void setAddress (final String address) {
this.address = address;
}

public String getCity () {
return city;
}

public void setCity (final String city) {
this.city = city;
}

public String getState () {
return state;
}

public void setState (final String state) {
this.state = state;
}

public String getCountry () {
return country;
}

public void setCountry (final String country) {
this.country = country;
}

public String getMobileNumber () {
return mobileNumber;
}

public void setMobileNumber (final String mobileNumber) {
this.mobileNumber = mobileNumber;
}
}

Now, if we want to use this POJO we would have to create an instance of RegisterUser class and pass the values in the constructor parameters as given in the code example below to set the data in the respective fields.

Checkout the below example of the Register User test of how we do it

public class RegistrationTest {

@Test
public void testRegisterUser () {
RegisterUser registerUser = new RegisterUser ("John", "Doe", "302, Adam Street, 1st Lane", "New Orleans",
"New Jersey", "US", "52145364");

assertEquals (registerUser.getFirstName (), "John");
assertEquals (registerUser.getCountry (), "US");
}
}

There were just seven fields in the example we took for registering the user. However, this would not be the case with every application. There would be some more additional fields required and as the fields keep on increasing every time, we would need to update the POJO class with respective Getter and Setter methods and also update the parameters in the constructor.

Finally, we would need to add the values to those fields so the data could be passed in the actual field required.

Long story short, we would need to update the code even if there is a single new field added. Also, it doesn’t look clean to add values as parameters in the tests.

Luckily, the Builder Design Pattern in Java comes to the rescue here.

What is Builder design pattern in Java?

Builder design pattern is a creational design pattern that lets you construct complex objects step by step. The pattern allows you to produce different types and representations of an object using the same construction code.[Source]

Builder Pattern helps us solve the issue of setting the parameters by providing a way to build the objects step by step by providing a method that returns the final object which can be used in the actual tests.

What is Lombok?

Project Lombok is a java library that automatically plugs into your editor and builds tools, spicing up your java. It is an annotation based java library that helps in reducing the boilerplate code.

It helps us in writing short and crisp code without having to write the boilerplate code. By passing the @Getterannotation over the class, it automatically generates Getter methods. Similarly you don’t have to write the code for Setter methods as well, its @Setterannotation updated over the class automatically generates the Setter methods.

It also has the support for using the Builder design pattern so we just need to put the @Builderannotation above the class and the rest will be taken care of by the Lombok library.

To use Lombok annotations in the project we need to add the following Maven dependency:

<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.32</version>
<scope>provided</scope>
</dependency>

Using the Builder Pattern with Lombok

Before we start refactoring the code we have written, let me tell you about the DataFaker library as well as it helps in generating fake data that can be used for testing. Ideally, in our example, every new registered user’s data should be unique otherwise we may get duplicate data errors and tests will fail.

Here, DataFaker library will help us in providing unique data in each test execution thereby helping us with registering a new user with unique data every time the registration test is run.

To use DataFaker library, we need to add the following Maven dependency in our project

<!-- https://mvnrepository.com/artifact/net.datafaker/datafaker -->
<dependency>
<groupId>net.datafaker</groupId>
<artifactId>datafaker</artifactId>
<version>2.2.2</version>
</dependency>

Now, let’s start refactoring the code. First, we will make the changes to the RegisterUser class. We would be removing all the Getter and Setter methods and also the constructor and adding the @Getter and @Builder annotation tags on the top of the RegisterUser class.

Here is how the RegisterUser class looks now after the refactoring

@Getter
@Builder
public class RegisterUserWithBuilder {
private String firstName;
private String lastName;
private String address;
private String city;
private String state;
private String country;
private String mobileNumber;
}ja

How clean and crisp it looks with that refactoring being done. Multiple lines of code removed still it will work in the same fashion as it used to earlier, thanks to Lombok.

We would have to add a new java class for generating the fake data on runtime using the Builder design pattern. We would be calling this new class as the DataBuilder class.

public class DataBuilder {

private static final Faker FAKER = new Faker();

public static RegisterUserWithBuilder getUserData () {
return RegisterUserWithBuilder.builder ()
.firstName (FAKER.name ()
.firstName ())
.lastName (FAKER.name ()
.lastName ())
.address (FAKER.address ()
.streetAddress ())
.state (FAKER.address ()
.state ())
.city (FAKER.address ()
.city ())
.country (FAKER.address ()
.country ())
.mobileNumber (String.valueOf (FAKER.number ()
.numberBetween (9990000000L, 9999999999L)))
.build ();
}
}

The getUserData() method will return the test data required for registering the user using the DataFaker library. Notice the builder() method used after the class name RegisterUserWithBuilder. It is appearing because of the @Builder annotation we have used on the top of the RegisterUserWithBuilder class.

After the builder() method we have to pass on the variables we have declared in the RegisterUserWithBuilder class and accordingly pass the fake data that we need to generate for the respective variables.

RegisterUserWithBuilder.builder ()
.firstName (FAKER.name ()
.firstName ());

The above piece of code will generate a fake first name and set it in the first name variable. Likewise, we have set fake data in all other variables.

Now, let’s move towards how we use these data in the tests. It’s very simple, the below code snippet explains it all.

    @Test
public void testRegisterUserWithBuilder () {
RegisterUserWithBuilder registerUserWithBuilder = getUserData ();

System.out.println (registerUserWithBuilder.getFirstName ());
System.out.println (registerUserWithBuilder.getLastName ());
System.out.println (registerUserWithBuilder.getAddress ());
System.out.println (registerUserWithBuilder.getCity ());
System.out.println (registerUserWithBuilder.getState ());
System.out.println (registerUserWithBuilder.getCountry ());
System.out.println (registerUserWithBuilder.getMobileNumber ());
}

We just need to call the getUserData() method while instantiating the RegisterUserWithBuilder class. Next, we would be calling the Getter methods for the respective variables we declared inside the RegisterUserWithBuilder class. Remember we had passed the @Getter annotation on the top of the RegisterUserWithBuilder class, this actually helps in calling the Getter methods here.

Also to mention here, we do not require here to pass on the multiple data as the constructor parameters for the RegisterUserWithBuilder class instead we just need to instantiate the class and call the getUserData() method!

How easy it is to generate the unique data and pass it on in the tests without having to write multiple lines of boilerplate codes.

Thanks to the Builder design pattern and Lombok!

Running the Tests

Let’s run the test and check if the user details get printed in the console. We can see that the fake data is generated successfully in the following screenshot of the test execution.

Conclusion

In this blog we discussed making use of the Builder design pattern in Java with Lombok and DataFaker library to generate fake test data on run time and use it in our automated tests. It would ease the test data generation process by eliminating the need to update the test data before running the tests.

I hope it would help you a lot in reducing the code lines and writing your code in a much cleaner way.

Happy Testing!

Paid Trainings

Contact me for Paid training related to Test Automation and Software Testing, ping me using any of the social media sites listed on LinkTree or email me @mohammadfaisalkhatri@gmail.com.

--

--

Mohammad Faisal Khatri

QA with 14+ years of experience in automation as well as manual testing. Freelancer, blogger and open source contributor.