Thursday, October 20, 2011

Data-Driven testing using Junit and TestNG


Most of the guys who are into automation may be knowing the term Data-Driven testing. But the word will still be new for some fresh faces in the field of automation. In this blog I will explain what is Data-Driven testing and will give an example of Data-driven testing using Junit and TestNG frameworks.

Data-Driven testing as the name suggests is a test driven by the Data. For ex. You have a user detail form where you need to enter details of multiple users and save them. Here if you have 5 different user data available and you have to write automation cases for these, you may end up writing 5 different automation test cases(one for each user data).
If you apply a Data-Driven approach you will end up with only one test-case, that is filling the form with user data and then submitting it. The test case will get executed based on the data provided to it. In this case it will be 5 and hence the test case will get executed 5 times with different data-set.

The advantage of using a Data-driven approach is that you reduce your effort in writing/maintaing test-cases for your different type of data. In case of additions or deletion of new/old entries , you just have to change the data and not your actual test-case.

Following I will mention a Data-Driven approach for searching on google with different data using Junit and TestNg frameworks:


Using Junit:
import static org.junit.Assert.fail;

import com.thoughtworks.selenium.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverBackedSelenium;
import org.openqa.selenium.firefox.FirefoxDriver;

import java.util.Arrays;
import java.util.List;

@RunWith(Parameterized.class)
public class JunitGoogleBase {
  public Selenium selenium;
  WebDriver driver;
  private String testData;
  
  public JunitGoogleBase(String testData){
   this.testData=testData;
  }
  
  @Parameters
   public static List< Object[]> data() {
    return Arrays.asList(new Object[][]{{"testing"},{"Software testing"}});
   }

  @Before
  public void setUp() throws Exception {
   driver= new FirefoxDriver();
   selenium = new WebDriverBackedSelenium(driver, "http://www.google.com"); 
   selenium.open("http://www.google.com");
  }

  @Test
  public void testSearch() throws Exception {
   selenium.open("/");
   selenium.type("id=lst-ib", testData);
   selenium.click("//input[@value='Google Search']");
   for (int second = 0;; second++) {
    if (second >= 60) fail("timeout");
    try { if (selenium.isElementPresent("link=Software testing - Wikipedia, the free encyclopedia")) break; } catch (Exception e) {}
    Thread.sleep(1000);
   }
   selenium.click("link=Software testing - Wikipedia, the free encyclopedia");
   for (int second = 0;; second++) {
    if (second >= 60) fail("timeout");
    try { if (selenium.isTextPresent("Software testing")) break; } catch (Exception e) {}
    Thread.sleep(1000);
   }
   
  }

  @After
  public void tearDown() throws Exception {
   selenium.stop();
   
  }
}

Using TestNg:

import com.thoughtworks.selenium.*;


import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverBackedSelenium;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;



public class TestNGGoogleBase {
  public Selenium selenium;
  WebDriver driver;
  
  @DataProvider(name="parameter")
   public static Object[][] data() {
    return new Object[][]{{"testing"},{"Software testing"}};
   }

  @BeforeMethod
  public void setUp() throws Exception {
   driver= new FirefoxDriver();
   selenium = new WebDriverBackedSelenium(driver, "http://www.google.com"); 
   selenium.open("http://www.google.com");
  }

  @Test(dataProvider="parameter")
  public void testSearch(String testData) throws Exception {
   selenium.open("/");
   selenium.type("id=lst-ib", testData);
   selenium.click("//input[@value='Google Search']");
   for (int second = 0;; second++) {
    if (second >= 60) Assert.fail("timeout");
    try { if (selenium.isElementPresent("link=Software testing - Wikipedia, the free encyclopedia")) break; } catch (Exception e) {}
    Thread.sleep(1000);
   }
   selenium.click("link=Software testing - Wikipedia, the free encyclopedia");
   for (int second = 0;; second++) {
    if (second >= 60) Assert.fail("timeout");
    try { if (selenium.isTextPresent("Software testing")) break; } catch (Exception e) {}
    Thread.sleep(1000);
   }
  }

  @AfterMethod
  public void tearDown() throws Exception {
   selenium.stop();
  }
 

}
The main difference in the above two functions is that you provide a Paramaterized option to the class in Junit and supply data to the constructor of the said class. Where as in TestNG you do the same at the test-method level.

Its simple to do data-driven testing in TestNG framework as you can provide a different data providing function for each test-method, but the same is not possible in Junit.

10 comments:

  1. Hi Varun,
    Looked at your blog. It is a nice blog. I had one question: Does TestNG provide any mechanism to externalize your test data (for example in a CSV file). I know JUnit currently does not have this support and they are actively considering to have such a support soon along with many new cool features. The JUnit code for the same is here : https://github.com/anujgandharv/junit-theories-ext

    Cheers!

    ReplyDelete
    Replies
    1. DataProvider is a feature where a test is executed multiple times based on the data provided. TestNG provides this feature in the simplest way possible. TestNG leaves the data providing part to the user. It depends on the user from where and how he needs to provide the data. In the above example I am using an array with pre-populated data. I can convert the same to get it from any of the other sources like csv,excel,DB or simple text file. This gives more flexibility to the user while developing a framework. I dont feel there is a necessity to add such feature to it.
      Junit is a gud unit test framework and there are certain things that I really like about it. But addition of features to Junit4 is making it more complex to understand and use by majority of the users.

      Delete
  2. Hi Varun,
    Can u pls let me know....
    How can we read/write data from/to an Excel excel sheet using selenium TestNG

    Thanks in advance.

    ReplyDelete
  3. Hi Varun,

    I have a problem in Report-Output folder.
    I am giving my custom method names and in the report output folder i am not getting the results in the order in which they are executed.I am actually posting a screenshot for each method,so the results seem haphazard.

    How to get the report in the order in which the methods have been executed ?

    Thanks,
    Karthik

    ReplyDelete
  4. Hi Varun,

    Please look into the below code, i am getting output as
    Got URL
    Testing Scenario
    Logged Out
    Logged In

    why priority is not getting consider here..?

    public class DependencyAnnotation {
    @Test(groups={"PreCondition"},priority=0)
    public void getURL(){
    System.out.println("Got URL");
    }

    @Test(priority=1,dependsOnGroups={"PreCondition"})
    public void login() {
    System.out.println("Logged In");
    }

    @Test(priority=2)
    public void testScenario(){
    System.out.println("Testing Scenario");
    }

    @Test(priority=3)
    public void logout(){
    System.out.println("Logged Out");
    }
    }

    ReplyDelete
    Replies
    1. Your methods looks good. But I dont understand why its not working. I havent used "priority" feature in TestNG. Could please post your issue in Stackoverflow under testng section. Cedric is very much active there and may be he will answer to your query.

      Delete
  5. I'm using firefox , can you please explain me how to set the proxy settings.


    As while i ran my test class in eclipse IDE the firfox is opening but it is not connecting to baseurl which i had given in the class.

    ReplyDelete
  6. Hi varun,

    can u tell me how to write the results into excel using TetsNG?


    Thanks

    ReplyDelete
    Replies
    1. The simplest way will be to write a class which implement the ITestLIstener interface provided by TestNG. This will give you handle on the ongoing test execution. You log the results onto the excel file inside different methods onTestSuccess, onTestSkipped etc.

      Delete