Friday, June 20, 2014

TestNG DataProviders



When you need to pass complex parameters or parameters that need to be created from Java (complex objects, objects read from a property file or a database, etc…), in such cases parameters can be passed using Dataproviders. A Data Provider is a method annotated with @DataProvider. A Data Provider returns an array of objects.
Let us check out the Login example using Dataproviders.

Steps to follow:
1)  Define the method credentials() which is defined as a DataProvider using the annotation. This method returns array of object array.
2) Add a method testLogin() to your DataProviderTest class. This method takes two strings as input parameters.
3) Add the annotation @Test(dataProvider = “Authentication”) to this method. The attribute dataProvider is mapped to “Authentication”.

Test will look like this:

package automationFramework;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class DataProviderTest {
            private static WebDriver driver;
           
  @DataProvider(name = "Authentication")
  public static Object[][] credentials() {
        return new Object[][] { { "testuser_1", "Test@123" }, { "testuser_2", "Test@111" }};
  }
 
  // Here we are calling the Data Provider object with its Name
  @Test(dataProvider = "Authentication")
  public void testLogin(String sUsername, String sPassword) {
              driver = new FirefoxDriver();
      driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
      driver.get("http://www.gmail.com");
      driver.findElement(By.id("txtUsername")).sendKeys(sUsername);
      driver.findElement(By.id("txtPassword")).sendKeys(sPassword);
      driver.findElement(By.id("btnLogin")).click();
      driver.findElement(By.xpath(".//*[@id='account_logout']/a")).click();
      driver.quit();
  }
}

Run the test by right click on the test case script and select Run As > TestNG Test. Give it few minutes to complete the execution and as the test data is provided two times, the above test will be executed two times completely.

TestNG Parameters

Everybody knows the importance of Parameterization in automation testing. It allows us to automatically run a test case multiple times with different input and validation values. As Selenium Webdriver is more an automated testing framework than a ready-to-use tool, you will have to put in some effort to support data driven testing in your automated tests. TestNG again gives us another interesting feature called TestNG Parameters. TestNG lets you pass parameters directly to your test methods with your testng.xml.

Steps to follow:
Let me take a very simple example of LogIn application, where the username and password is required to clear the authentication.
1) Create a test to perform LogIn which takes the two string argument as username & password.
2) Provide Username & Password as parameter using TestNG Annotation.

package automationFramework;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.Test;
import org.testng.annotations.Parameters;

public class TestngParameters {
            private static WebDriver driver;
  @Test
  @Parameters({ "sUsername", "sPassword" })
  public void testLogin(String sUsername, String sPassword) {
              driver = new FirefoxDriver();
      driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
      driver.get("http://www.gmail.com");
      driver.findElement(By.id("txtUsername")).sendKeys(sUsername);
      driver.findElement(By.id("txtPassword")).sendKeys(sPassword);
      driver.findElement(By.id("btnLogin")).click();
      driver.findElement(By.xpath(".//*[@id='account_logout']/a")).click();
      driver.quit();
  }
}

3. The parameter would be passed values from testng.xml as shown below.
<suite name="Suite">
    <test name="TestParameter">
            <parameter name="sUsername" value="testuser_1"/>
            <parameter name="sPassword" value="Test@123"/>
                        <classes>
                            <class name="automationFramework.TestngParameters" />
                        </classes>
    </test>
</suite>

Now, run the testng.xml, which will run the parameter testLogin method. TestNG will try to find a parameter named sUsername & sPassword.

Thursday, June 19, 2014

TestNG Asserts

TestNG also gives us the power to take decisions in the middle of the test run with the help of Asserts. With this we can put various checkpoints in the test. Asserts are the most popular and frequently used methods while creating Selenium Scripts. In selenium there will be many situations in the test where you just like to check the presence of an element. All you need to do is to put an assert statement on to it to verify its existence.
Different Assert Statements
1) Assert.assertTrue() & Assert.assertFalse()
package automationFramework;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.annotations.Test;

public class Asserts {
            private static WebDriver driver;
  @Test
  public void f() {
              driver = new FirefoxDriver();
      driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
      driver.get("url");
     
      // Here driver will try to find out My Account link on the application
      WebElement myAccount = driver.findElement(By.xpath(".//*[@id='account']/a"));
     
      //Test will only continue, if the below statement is true
      //This is to check whether the link is displayed or not
      Assert.assertTrue(myAccount.isDisplayed());
     
      //My Account will be clicked only if the above condition is true
      myAccount.click();
  }
}
Note: Assert true statement fails the test and stop the execution of the test, if the actual output is false. Assert.assertFalse() works opposite of Assert.assertTrue(). It means that if you want your test to continue only if when some certain element is not present on the page. You will use Assert false, so it will fail the test in case of the element present on the page.

2) Assert.assertEquals()

  @Test
  public void testCompare() {
              String sValue = "Nagarjun Reddy K";
              System.out.println(" What is your name?");
              Assert.assertEquals("Nagarjun Reddy K", sValue);
              System.out.println(sValue);
  }

It also works the same way like assert true and assert fail. It will also stop the execution, if the value is not equal and carry on the execution, if the value is equal.

Skipping a Test Case

Think of a situation where you are required to skip one or more @Test from your testng class. In testng, you can easily able to handle this situation by setting the ‘enabled’ parameter to ‘false’ for e.g.:

@Test(enabled = false)
To use two or more parameters in a single annotation, separate them with a comma:
@Test(priority = 3, enabled = false)

Let's take an example and set the value false for the third test.

package automationFramework;
import org.openqa.selenium.WebDriver;
import org.testng.annotations.Test;

public class MultipleTest {
            public WebDriver driver;
  @Test(priority = 0)
  public void One() {
      System.out.println("This is the Test Case number One");
  }
 
  @Test(priority = 1)
  public void Two() {
              System.out.println("This is the Test Case number Two");
  }
 
  @Test(priority = 2, enabled = false)
  public void Three() {
              System.out.println("This is the Test Case number Three");
  }
 
  @Test(priority = 3)
  public void Four() {
              System.out.println("This is the Test Case number Four");
  }
}
Output of the above example:
This is the Test Case number One
This is the Test Case number Two
This is the Test Case number Four

TestNG Sequencing & Prioritizing

Multiple Tests
There will be situations when you want to put number of tests under a single test class and like to run all in single shot. With the help of TestNG ‘@Test‘ annotations we can execute multiple tests in single TestNG file.
Take an example of four different tests under one testng class and print the test sequence on the console.
Steps to follow:
1 Press Ctrl+N , select “TestNG Class” under TestNG category and click Next
Or Right click on Test Case folder, go to TestNG and select “TestNG Class“.
2. If your project is set up and you have selected the Test Case folder before creating TestNG class then the source folder and the package name will be pre-populated on the form. Set class name as ‘TestNG‘. Leave rest of the settings untouched, do not check for “@BeforeMethod”, “@AfterMethod” for now and click Finish. That’s it.
3. By default a new class will have only one @Test method. Add three more methods by yourself and put your code accordingly in methods. Code will look like:

package automationFramework;
import org.openqa.selenium.WebDriver;
import org.testng.annotations.Test;

public class MultipleTest {
            public WebDriver driver;
  @Test
  public void One() {
      System.out.println("This is the Test Case number One");
  }
 
  @Test
  public void Two() {
              System.out.println("This is the Test Case number Two");
  }
 
  @Test
  public void Three() {
              System.out.println("This is the Test Case number Three");
  }
 
  @Test
  public void Four() {
              System.out.println("This is the Test Case number Four");
  }
}
This will enable you to execute all four tests with just one testng class. Take a look on the output.
Output of the above code:
This is the Test Case number Four
This is the Test Case number One
This is the Test Case number Three
This is the Test Case number Two

Note: By default, methods annotated by @Test are executed alphabetically. Take a look over the next topic to see how to prioritize @Test.

Sequencing & Prioritizing

You need to use the ‘priority‘ parameter, if you want the methods to be executed in your order. Parameters are keywords that modify the annotation’s function.
Let’s take the same above example and execute all @Test methods in right order. Simply assign priority to all @Test methods starting from 0(Zero).

package automationFramework;
import org.openqa.selenium.WebDriver;
import org.testng.annotations.Test;

public class MultipleTest {
            public WebDriver driver;
  @Test(priority = 0)
  public void One() {
      System.out.println("This is the Test Case number One");
  }
 
  @Test(priority = 1)
  public void Two() {
              System.out.println("This is the Test Case number Two");
  }
 
  @Test(priority = 2)
  public void Three() {
              System.out.println("This is the Test Case number Three");
  }
 
  @Test(priority = 3)
  public void Four() {
              System.out.println("This is the Test Case number Four");
  }
}
Note: TestNG will execute the @Test annotation with the lowest priority value up to the largest.
Output of the above code:
This is the Test Case number One
This is the Test Case number Two
This is the Test Case number Three
This is the Test Case number Four