Core Java

Writing Data Driven Tests for your Java Application

JUnit is an extremely powerful testing framework that not only provides its users with a facility to write quick and easy tests but also provides an opportunity for users to extend it and make it work the way they want it to. Many frameworks have been built on top of JUnit that provides various ease of use functionalities to their target audience.

EasyTest is one such framework whose primary focus is to bring Data Driven Testing functionality to the JUnit world.

JUnit already has some mechanism in place that provides its users some sort of data driven test feeling. But its not sufficient and also it is not clean. for example, a user can use @Parameterized Runner to write Data Driven Tests but using Parameterized Runner results in a lot of unnecessary code to be written.

EasyTest tries to solve the problems by bridging the gap between what JUnit already has and what is most convenient to the users.

In today’s post, I will give a brief overview of what EasyTest is and how it has evolved from being a hobby to a full fledged project that is being used in a lot of companies and by a lot of people.

Getting Started

In order to get started with EasyTest, All you have to do is download the JAR file. You can do that via Maven. Here is the link to the latest easytest-core JAR on Maven.

Once you have downloaded the JAR file, you are ready to write your first Data Driven Test. Here is a step by step guide to getting up and running quickly with EasyTest Core Module.

Step 1 : Have the latest EasyTest dependency in you pom file:

<dependency>
<groupId>org.easetech</groupId>
<artifactId>easytest-core</artifactId>
<version>1.3.2</version>
</dependency>

Step 2: Create a simple Test Class with test method

@RunWith(DataDrivenTestRunner.class)
    @DataLoader(filePaths = { "testExcelData.xls" })
    public class TestExcelDataLoader{
    
      private ItemService itemService = new RealItemService();

    @Test
    public void getExcelTestData(@Param(name="libraryId")
    Float libraryId, @Param(name="itemId")
    Float itemId) {
        System.out.print("Executing getExcelTestData :");
        System.out.println("LibraryId is :" + libraryId + " and Item Id is :" + itemId);
    }

There are a lot of options available with EasyTest Library that you can use to efficiently execute your tests. For example, if you want to execute your tests in parallel, then EasyTest provides a Parallel annotation. Have a look at this blog post to understand the Parallel Annotation in detail.

Here is another detailed example making use of the available features in EasyTest:

@RunWith(DataDrivenTestRunner.class)
    @DataLoader(filePaths = { "testExcelData.xls" })
    @Format(date='dd/MM/yyyy')
    @Report
    @Parallel(threads=5)
    public class TestExcelDataLoader{
    
      @Duration(timeInMillis=1000)
      private ItemService itemService = new RealItemService();

    @Test
    public void getExcelTestData(@Param(name="libraryId")
    Float libraryId, @Param(name="itemId")
    Float itemId) {
        System.out.print("Executing getExcelTestData :");
        System.out.println("LibraryId is :" + libraryId + " and Item Id is :" + itemId);
    }

You can have a look at the source code’s javadocs to understand what each of the annotation means and can also get the idea of the functionalities available in EasyTest.

Writing test classes with so many annotations on each test class can not only be time consuming (typical boiler plate code), but it can also introduce bugs that are difficult to trace. Therefore Easytest provides you the ability to define once and use everywhere functionality. Have a look at the below example, which is the same as above, but more concise :

Alternatively, you can use TestPolicy annotation at the class level to move all the annotations to a separate reusable Test Policy class. Here is an example.

     @RunWith(DataDrivenTestRunner.class)
    @TestPolicy(TestExcelDataPolicy.class)
    public class TestExcelDataLoader{
    
      @Duration(timeInMillis=1000)
      private ItemService itemService = new RealItemService();

    @Test
    public void getExcelTestData(@Param(name="libraryId")
    Float libraryId, @Param(name="itemId")
    Float itemId) {
        System.out.print("Executing getExcelTestData :");
        System.out.println("LibraryId is :" + libraryId + " and Item Id is :" + itemId);
    } 

Here, instead of defining several annotations on the test class, we have just defined a TestPolicy Annotation that abstracts away the complex definitions from the test class.

And here is how the Policy class TestExcelDataPolicy looks like:

@DataLoader(filePaths = { "org/example/data/testExcelData.xls" })
     @Format(date='dd/MM/yyyy')
     @Report
     @Parallel(threads=5)
     public class TestExcelDataPolicy {
         
     }

Having such an abstraction means that now you can reuse your test policy class on multiple tests, which considerably reduces your boiler plate code.

Once you have defined your test class, the next step is to define your test data file.

Step 3: Create you test data file(for above example it would be an excel file with name testExcelData.xls)
The first column of first row indicates the name of the test method for which the data needs to be supplied. 2nd and third column of the 1st row represents the name of the input parameters to the test. Row 2 and 3 represents the actual test data.

getExcelTestData itemId libraryId

                         11567 91475

                          null         0

Congratulations. You have just written your first Data Driven Test. When you run the above test using Junit supported IDE, EasyTest will generate 2 Tests, one for each set of data. Thus, you have just saved yourself from writing different tests for testing with different parameters.

Next, lets extend this example and try to understand some extra features of EasyTest.

Understanding the IoC Container support in EasyTest

Instead of defining/initializing your testSubject (ItemService in the above test) in the test class itself, you can also externalize the initialization logic in a config file and inject the right instance at runtime. The advantage of doing this is that you separate the initialization logic from the test logic thereby making your tests cleaner and more maintainable. Secondly, you can reuse the externalized logic in other tests as well. Lets see how we can do it for the above test.

@RunWith(DataDrivenTestRunner.class)
    @DataLoader(filePaths = { "testExcelData.xls" })
    @TestConfigProvider({TestConfigProviderClass.class})
    public class TestExcelDataLoader{
    
      @Inject
      private ItemService itemService;

    @Test
    public void getExcelTestData(@Param(name="libraryId")
    Float libraryId, @Param(name="itemId")
    Float itemId) {
        System.out.print("Executing getExcelTestData :");
        System.out.println("LibraryId is :" + libraryId + " and Item Id is :" + itemId);
    }

Note we have added two things to the above tests:

  1. TestConfigProvider annotation
  2. Inject annotation

TestConfigProvider annotation takes an array of Configuration provider classes from which to load the beans. In the above example the TestConfigProviderClass.class will look like the following:

public class TestConfigProviderClass {
    
    @TestBean public ItemService itemService(){
        return new RealItemService();
    }

Note also that we are using standard Javax annotation @Inject for injecting the Test Bean. EasyTest supports @Inject for injection by Type, @Named along with @Inject for injection by Name. Besides this EasyTest also supports injection by field name. EasyTest also has its own @Provided annotation in cases when the user doesn’t or cant use the Javax annotations.

And that concludes this blog post. I hope I have been able to give you an interesting introduction of EasyTest and its capabilities. Please reach out to me at anujkumar@easetech.org in case you have any queries or questions or if you would like to contribute to the project.

Anuj Kumar

Anuj is working as a Senior S/W Engineer in Netherlands. He is a Sun Certified Java Professional with experience in design and development of mid/large scale Java applications. He is the creator of EasyTest Framework(https://github.com/EaseTech) which is a Data Driven Testing Framework for Java.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button