TestingPod

5 Java libraries to 10X your Test Data Management

Written by Sajitha Tharaka Pathirana | July 03, 2024

Managing test data is one of the challenging and crucial aspects of test automation for SDETs, automation testers, and test architects.

Let’s explore some of the readily available Java libraries that can amplify test data management and enhance the overall test automation process for engineers.

Introduction

There are two key components of an automated test, the path a user uses to achieve an objective and the data used in this process.

Here’s an example of a path of a user who wants to log into an application:

Step 1 – Navigate to the application URL.

Step 2 – Enter username.

Step 3 – Enter password.

Step 4 – Click Login.

The data component consists of the username and password used to login to the application.

For successful testing automation, you must pay attention to both components. In most cases, the path remains static while data adds dynamicity, making the life of automation engineers challenging.

Managing test data can be time-consuming, especially with large datasets, which creates the need for libraries. Moreover, maintaining test data without the aid of libraries can lead to data duplication, inconsistencies, and redundancy, which will jeopardize the advantages of test automation.

Let’s take a look at some of these libraries and how they can improve your existing tests.

Lombok

Lombok is a popular Java library that helps reduce boilerplate code with the help of annotations. While Lombok is mainly known for generating getters, setters, and constructors, it can also simplify test data management.

Key Features

  • @Data- Automatically generates getters, setters, toString, equals, and hashCode methods.
  • @Builder- Provides a builder pattern for creating objects, making it easier to create complex test data.
  • @Value- Creates immutable classes, ensuring test data integrity.

This is one of my favorite libraries. It speeds up the implementation of tests and reduces a lot of boilerplate code. Let’s look at an example before and after using Lambok.

Before using Lambok

public class User {
private String username;
private String email;
private int age;

public User() {
}

public User(String username, String email, int age) {
this.username = username;
this.email = email;
this.age = age;
}

public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
// Usage in tests
User testUser = new User();
testUser.setUsername (“testuser”);
testUser.setEmail (“testuser@example.com”);
testUser.setAge(25);

After using Lambok

@Data
@Builder
public class User {
private String username;
private String email;
private int age;
}
// Usage in tests
User testUser = User.builder()
.username("testuser")
.email("testuser@example.com")
.age(25)
.build();

Lambok can used as the guardian of the data model of your automation project.

Java Faker

Have you ever considered having an endless supply of realistic test data for your automation project?

Java Faker does the magic for you. It is a library that allows you to generate fake data for various use cases, such as names, addresses, and phone numbers.

Key Features

  • Comprehensive Data Generation- Supports various data types, including names, addresses, emails, and more.
  • Data Customization- Allows for custom data generation based on locale and format.

Before using Java Faker

User testUser = new User();
testUser.setUsername (“testuser”);
testUser.setEmail (“testuser@example.com”);
testUser.setAge(25);

After using Java Faker

Faker faker = new Faker();
// Generating random data
String name = faker.name().fullName();
String address = faker.address().fullAddress();
String email = faker.internet().emailAddress();

Pro Tip

  • Combine Java Faker with Lombok's @Builder to create realistic test data objects effortlessly.
Faker faker = new Faker();
User testUser = User.builder()
.username(faker.name().username())
.email(faker.internet().emailAddress())
.age(faker.number().numberBetween(18, 65))
.build();

  • Leverage the locales feature to generate location-specific data.

Faker ukFaker = new Faker(new Locale("en-GB"));

For further reference check out the Java Faker GitHub project - https://github.com/DiUS/java-faker

Instancio

While Java Faker excels at generic types, how do you handle more complex scenarios? Instancio is a library that can help automate data setup by generating test data with a single method call. It can generate a fully populated data object. Moreover, Instancio supports various data formats, including JSON, XML, and CSV, making it a versatile tool for test data management.

Key Features

  • Fluent AP- Provides a developer-friendly API for object creation.
  • Customization- Supports custom data generators with constraints.
  • Nested Object Population– Integrated capability to populate nested objects including nested objects and collections, reducing manual effort.

Before using Instancio

User testUser = new Customer();
testUser.setFirstName("testuser");
testUser.setAddress(new Address("123 Main St", "Colombo", "SL"));
testUser.setPhoneNumbers(List.of(
new Phone(PhoneType.HOME, "+94", "123-44-55"),
new Phone(PhoneType.WORK, "+94", "555-77-88")));

After using Instancio

User testUser = Instancio.of(User.class);

If you want to customize data generation, instancio provides a straightforward mechanism. In the below example, I have requested to create 03 phone numbers for the user.

User testUser = Instancio.of(User.class)
.generate(field("phoneNumbers"), gen -> gen.collection().size(3)).create();

Instancio is a great library that we can leverage the data generation with specific constraints to test scenarios cover edge cases and avoid pesticide paradox in testing due to dynamic data used in each test execution.

Owner

Owner is a library that helps the management of configuration data using Java interfaces. It's particularly useful for managing test configurations, such as database connections. This library allows tests to easily retrieve, update, and delete data in the database during the test execution.

The owner is handy, especially with integration tests where real-world data interaction is necessary.

Key Features

  • Type-Safe Configuration- Provides type-safe access to configuration properties.
  • Dynamic Reloading- Supports reloading configurations at runtime.
  • Environment-Specific Configurations- Allows for different configurations based on the environment.
public interface TestConfig extends Config {
@Key("database.url")
String databaseUrl();
@Key("database.user")
String databaseUser();
@Key("database.password")
String databasePassword();
}
// Usage
TestConfig config = ConfigFactory.create(TestConfig.class);
String dbUrl = config.databaseUrl();
String dbUser = config.databaseUser();

One of the best use cases for using Owner would be to manage environment-specific configurations to run the tests seamlessly across different environments.

DBTestCompare

DBTestCompare is a library designed to simplify database testing by efficiently comparing database states before and after test execution. This allows developers and testers to ensure the accuracy and consistency of data.

Key Features

  • Schema Comparison- Compares database schemas to detect structural changes.
  • Data Comparison- Compares data within tables to identify discrepancies.
  • Integration- Integrates with popular testing frameworks like JUnit and TestNG.

The greatest benefit of leveraging DBTestCompare is saving tons of time and reduction of errors when manually comparing data.

public class DatabaseTest {
public void compareDatabaseStates() {
DBTestCompare.compare("jdbc:h2:mem:testdb", "jdbc:h2:mem:reference");
}
}

Conclusion

Managing test data is a crucial aspect of test automation that can impact the reliability and maintainability of your test suites. By leveraging Java libraries such as Lombok, Java Faker, Instancio, Owner, and DBTestCompare, you can simplify test data management, reduce maintenance overhead, and enhance the robustness of your tests by avoiding primitive implementations.