Checking for empty variable using IF controller in jmeter

Sometimes you need to add HTTP samplers with dynamic URL or with dynamic part of the URL which are stored in some variable after HTTP sampler post-processing.



But if Regular Expression Extractor will not find any matching string result variable will be set to default value (empty value in our case). We should test this variable for emptyness before we will use it.


Now if the News page has not any news we are sure that JMeter will handle this situation correctly.

How to add HTTP Request sampler with dynamic URL in jmeter

If you need to add HTTP Request sampler with dynamic URL that can be different each time from testing to testing you must use one of the Post-Processors offered by JMeter. I usually use Regular Expression Extractor for this purposes.

So, let's imaging that you have "Popular News" web page which contains the links to "News Story" web pages that contains the full texts of news and you want to write a test which will include both "News" page and random "News Story" page.

For this you must include "News" page HTTP Request sampler inside Simple Controller with a Regular Expression Extractor to store random "News Story" page URL to a variable:


Then use the variable with the stored random "News Story" page URL in "News Story" HTTP sampler:

Advanced test plan structure in jmeter

Working with JMeter for about 2 years I've come to the optimal (for me) structure of the test plan. It's divided into several suites (thread groups) depending on user type (visitor or signed in user, etc.) and is quite large to simulate real user activity. Complex business operations can be grouped using Simple Controller for better readability of the test plan. Also do not forget about pauses.

Here is an example test plan structure:


Thread Group - Visitor Suite
  Simple Controller - Homepage
    Transaction Controller - Homepage
      HTTP Request Sampler
      ...
  Random Order Controller
    Simple Controller - News page
      Transaction Controller - News page
        HTTP Request Sampler
        ...
    ...
Thread Group - User Suite

  Simple Controller - Sign In page
    Transaction Controller - Sign In page
      HTTP Request Sampler
      ...
  Random Order Controller
    Simple Controller - View User Profile page
      Transaction Controller - View User Profile page
        HTTP Request Sampler
        ...

Hacking the response data size limit

View Results Tree is very useful listener especially when you are debugging your test plan. You can review the response data and ensure that your test plan works good. But sometimes you you can see a message in the beginning of the response data like "Response too large to be displayed. Size: 313674 > Max: 204800, Start of message:".

JMeter - Response too large to be displayed

And unfortunately you are not able to see the whole response data. By default JMeter shows only first 200 Kb of response data. To resolve this problem you should edit the file jmeter.properties and uncomment the line:

view.results.tree.max_size=0
 This will disable response data size check at all.

Uncommented view.results.tree.max_size=0

After you have saved jmeter.properties you will never see this message again.

The problem with the response data size limit has been resolved.

How to save test results

how to save the testing results using Simple Data Writer. There is one more way about how to do it - using the command line options.

So, if you want to run the test plan from file test.jmx and save the testing results to the file log.jtl, use the following command:

jmeter -n -t test.jmx -l log.jtl
You can configure how the result data will be saved by editing the file jmeter.properties (section "Results file configuration"). For example, if you want to save the results in CSV format you should edit the following property:
jmeter.save.saveservice.output_format=csv
This way is more powerful than the one described in the previous part (Simple Data Writer) because it allows you to set some additional options like CSV delimiter, timestamp format, etc. Sometimes it could be very helpful.

Validate dynamic Html Id with Regular Expression

In some web applications, a html tag Id is dynamically generated for each user session. When using Selenium to identify the element, using locators such as Id, name, xpath may not work because the dynamic Id pattern changes constantly.
One option would be to use Regular Expression in Xpath or with other locators and locate the element. Before creating a generic regular expression, you need to validate the Regular Expression to make sure that the pattern of the regular expression covers all the possible scenarios. For example, in the user registration form below, the id changes and it has a pattern like "userId_mm_dd_yyyy_{5 digit random number}. We can use this pattern below when finding the userId Element. 
UserIdPattern="userid_[0-9]{1,2}_[0-9]{1,2}_[0-9]{4}_[0-9]{5}";

Here is the Java code to validate regular expression for this pattern. 
Step 1:  Create a Java Project, add a package, add a class "DynamicUserIdValidator.java", add a TestNG class "UserIdValidatorTest.java" and define testng.xml. 

Step 2: write the code in the DynamicUserIdValidator.java class
package com.seleniummaster.regularexpression;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DynamicUserIdValidator {
private Pattern pattern;
private Matcher matcher;
private static final String UserIdPattern="userid_[0-9]{1,2}_[0-9]{1,2}_[0-9]{4}_[0-9]{5}";
public DynamicUserIdValidator()
{
  pattern=Pattern.compile(UserIdPattern);
}
/*
* validate userId with pattern
* @param userId
*/
public boolean validate (final String userId)
{
  matcher=pattern.matcher(userId);
  return matcher.matches();
}
}
Step 3: write the code in the UserIdValidatorTest.java class
package com.seleniummaster.regularexpression;

import org.testng.Assert;
import org.testng.annotations.Test;
import org.testng.annotations.DataProvider;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.AfterClass;

public class UserIdValidatorTest {
  private DynamicUserIdValidator userIdValidator;
//test valid user Ids
  @Test(dataProvider = "ValidUserIdValidator")
  public void ValidUserIdTest(String[] userIds) {

    for (String eachUserId : userIds) {
      boolean valid = userIdValidator.validate(eachUserId);
      System.out
          .println("UserId is valid : " + eachUserId + " , " + valid);
      Assert.assertEquals(valid, true);
    }
    System.out.println("Valid User Id Validation Test Completed");
  }
//test invalid user Ids
  @Test(dataProvider = "InvalidUserIdValidator",dependsOnMethods = "ValidUserIdTest")
  public void InValidUserIdTest(String[] userIds) {

    for (String eachUserId : userIds) {
      boolean valid = userIdValidator.validate(eachUserId);
      System.out
          .println("UserId is valid : " + eachUserId + " , " + valid);
      Assert.assertEquals(valid, false);
    }
    System.out.println("Invalid User Id Validation Test Completed");
  }
//valid user Id sample data
  @DataProvider
  public Object[][] ValidUserIdValidator() {
    return new Object[][] { { new String[] { "userid_4_23_2005_85083",
        "userid_11_13_2000_31277""userid_8_27_2014_83046",
        "userid_12_24_2006_63060""userid_9_8_2000_56086",
        "userid_7_7_2005_30338""userid_10_15_2006_54936",
        "userid_9_14_2014_65261""userid_1_30_2010_64475",
        "userid_2_1_2004_58032""userid_8_4_2010_26849",
        "userid_10_19_2012_23906""userid_5_29_2004_60408",
        "userid_6_6_2011_82682""userid_6_13_2005_32055",
        "userid_12_17_2013_76612""userid_3_22_2001_41024",
        "userid_12_3_2010_51135""userid_4_13_2002_50477",
        "userid_9_25_2014_10160""userid_5_9_2009_18337",
        "userid_4_8_2002_42764""userid_5_29_2003_37048",
        "userid_12_16_2002_97276" } } };
  }
//invalid user Id sample data
  @DataProvider
  public Object[][] InvalidUserIdValidator() {
    return new Object[][] { { new String[] { "userid_108_28_2014_5815",
        "userid_104_8_2011_4572""userid_101_12_2001_4319",
        "userid_114_10_2012_2718""userid_112_11_2011_6250",
        "userid_118_7_2000_9750""userid_117_11_2007_4355",
        "userid_108_12_2005_3010""userid_113_21_2013_5157",
        "userid_112_7_2013_7582""userid_103_15_2006_3962",
        "userid_117_13_2011_4727""userid_109_5_2001_7123",
        "userid_103_12_2009_5901""userid_111_19_2002_9712",
        "userid_119_1_2008_5702""userid_105_12_2002_6523",
        "userid_100_25_2000_1151""userid_107_5_2006_4363",
        "userid_108_1_2010_5425""userid_113_12_2011_6270",
        "userid_108_26_2000_7718""userid_120_3_2003_3281",
        "userid_118_29_2003_4848" } } };
  }

  @BeforeClass
  public void initData() {
    userIdValidator = new DynamicUserIdValidator();
  }

  @AfterClass
  public void afterClass() {
  }

}
Step 4: run the test as TestNG Test.
 
Step 5: see the result below and console output. The result showed that all the valid userId and invalid userId tests passed for each data set in the validation, so we can use the pattern below in the element locator. 

UserIdPattern="userid_[0-9]{1,2}_[0-9]{1,2}_[0-9]{4}_[0-9]{5}";
 Console Output
UserId is valid : userid_4_23_2005_85083 , true
  UserId is valid : userid_11_13_2000_31277 , true
  UserId is valid : userid_8_27_2014_83046 , true
  UserId is valid : userid_12_24_2006_63060 , true
  UserId is valid : userid_9_8_2000_56086 , true
  UserId is valid : userid_7_7_2005_30338 , true
  UserId is valid : userid_10_15_2006_54936 , true
  UserId is valid : userid_9_14_2014_65261 , true
  UserId is valid : userid_1_30_2010_64475 , true
  UserId is valid : userid_2_1_2004_58032 , true
  UserId is valid : userid_8_4_2010_26849 , true
  UserId is valid : userid_10_19_2012_23906 , true
  UserId is valid : userid_5_29_2004_60408 , true
  UserId is valid : userid_6_6_2011_82682 , true
  UserId is valid : userid_6_13_2005_32055 , true
  UserId is valid : userid_12_17_2013_76612 , true
  UserId is valid : userid_3_22_2001_41024 , true
  UserId is valid : userid_12_3_2010_51135 , true
  UserId is valid : userid_4_13_2002_50477 , true
  UserId is valid : userid_9_25_2014_10160 , true
  UserId is valid : userid_5_9_2009_18337 , true
  UserId is valid : userid_4_8_2002_42764 , true
  UserId is valid : userid_5_29_2003_37048 , true
  UserId is valid : userid_12_16_2002_97276 , true
  Valid User Id Validation Test Completed
  
  UserId is valid : userid_108_28_2014_5815 , false
  UserId is valid : userid_104_8_2011_4572 , false
  UserId is valid : userid_101_12_2001_4319 , false
  UserId is valid : userid_114_10_2012_2718 , false
  UserId is valid : userid_112_11_2011_6250 , false
  UserId is valid : userid_118_7_2000_9750 , false
  UserId is valid : userid_117_11_2007_4355 , false
  UserId is valid : userid_108_12_2005_3010 , false
  UserId is valid : userid_113_21_2013_5157 , false
  UserId is valid : userid_112_7_2013_7582 , false
  UserId is valid : userid_103_15_2006_3962 , false
  UserId is valid : userid_117_13_2011_4727 , false
  UserId is valid : userid_109_5_2001_7123 , false
  UserId is valid : userid_103_12_2009_5901 , false
  UserId is valid : userid_111_19_2002_9712 , false
  UserId is valid : userid_119_1_2008_5702 , false
  UserId is valid : userid_105_12_2002_6523 , false
  UserId is valid : userid_100_25_2000_1151 , false
  UserId is valid : userid_107_5_2006_4363 , false
  UserId is valid : userid_108_1_2010_5425 , false
  UserId is valid : userid_113_12_2011_6270 , false
  UserId is valid : userid_108_26_2000_7718 , false
  UserId is valid : userid_120_3_2003_3281 , false
  UserId is valid : userid_118_29_2003_4848 , false
  
  Invalid User Id Validation Test Completed

us zip codes regular expression validation

In some tests, users need to test valid US zip codes by using regular expressions. Zip code validation may be needed when locating elements in the html tag or on the UI. This article explains how to validate US zip code regular expression pattern in Java code.  The most commonly used zip code pattern is:
Regular Expression Pattern: \b[0-9]{5}(?:-[0-9]{4})?\b
Explanation: (explanation syntax is from http://regex101.com)

Here is the Java source code to validate the US Zip Code regular expression
Step 1: create a java project as shown below, add a class "ZipCodeValidator.java", and add a JUnit test class "ZipCodeValidatorTest.java". 

Step 2: write the following code in the ZipCodeValidator.java class
package com.seleniummaster.regularexpression;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ZipCodeValidator {
  
  //note in this expression below, each back slash is an escape character, so 
  //the regular expression should be "\b[0-9]{5}(?:-[0-9]{4})?\b"
  final static String zipcodePattern="\\b[0-9]{5}(?:-[0-9]{4})?\\b";
  private static Pattern pattern;
  private static Matcher matcher;
  public ZipCodeValidator()
  {
    pattern=Pattern.compile(zipcodePattern);
  }

  public boolean validate (String ZipCode)
  {
    matcher=pattern.matcher(ZipCode);
    return matcher.matches();
  }

}
Step 3: write the following code in the ZipCodeValidatorTest.java class
 
package com.seleniummaster.regularexpression;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class ZipCodeValidatorTest {

  private ZipCodeValidator zipCodeValidator;

  @Before
  public void setUp() throws Exception {
    zipCodeValidator = new ZipCodeValidator();
  }

  @After
  public void tearDown() throws Exception {
  }
  @Test
  public void ValidZipCodeTest1() {
    System.out.println("Zip Code 12345-6789 "+ zipCodeValidator.validate("12345-6789"));
    assertTrue(zipCodeValidator.validate("12345-6789"));

  }
  @Test
  public void ValidZipCodeTest2() {
    System.out.println("Zip Code 12345-4567 "+ zipCodeValidator.validate("12345-4567"));
    assertTrue(zipCodeValidator.validate("12345-4567"));

  }
  
  @Test
  public void InvalidZipCodeTest1() {
    System.out.println("Zip Code 12345-67890 "+ zipCodeValidator.validate("12345-67890"));
    assertTrue(zipCodeValidator.validate("12345-67890"));
  }
  @Test
  public void InvalidZipCodeTest2() {
    System.out.println("Zip Code 12345-abcd "+ zipCodeValidator.validate("12345-abcd"));
    assertTrue(zipCodeValidator.validate("12345-abcd"));
  }

}
Step 4: run the test as JUnit test and see the result in the console and JUnit console.  Two zip codes are valid and other two zip codes are not correct, so two tests failed in the assertion. 
Result on the console: 
Zip Code 12345-6789 true
Zip Code 12345-4567 true
Zip Code 12345-67890 false
Zip Code 12345-abcd false

JUnit Result

Write Selenium WebDriver TestNG Result to Excel File

In this example you will learn how to use Selenium WebDriver with TestNG and write test result into an Excel file with Apache POI library. The key feature of the sample is that you use Selenium Java WebDriver that will launch a browser and run each test sequentially. Each test has description in the test methods. After test is done, you can see test result both in TestNG output html file and an Excel file as shown below.

Test Step Id Action Expected Result Actual Result
1 navigate to site and login site opens and login success Pass
2 navigate to User Settings Page Page Displayed Pass
3 User can change settings Settings changed Pass
4 User can logout Logout successfull Pass
Model your test cases
Before you start automation, you need to know what are the tests and what you are going to validate. Let's break the test suite into 4 test cases.
Test 1 (launchSiteAndLogin)
1. Go to http://seleniumsubbu.blogspot.in/index.php
2. Enter "test" in the Username field
3. Enter "xyz" in the Password filed
4. Click on the Login button
5. Verify that the text "Selenium Test" is present.

Test 2 (openUserSettingPage)
1. Click on the Settings link on the top of the page
2. Enter "test" in the Username field
3. Enter "xyz" in the Password filed
4. Click on the Login button
5. Verify that Account Prefernces page displayed.

Test 3 (ChangeUserSettings)
1. Click on the radio button near friends need my authorization to add me
2. Click on the save button
3. Verify that the text "preference saved" displayed.

Test4 (Logout)
1. Click on the Logout button
2. Verify that Login button displayed.

Automation Implementation
Step 1: Create a Java Project named "SeleniumMasterWebDriverTestNg", add a package named "com.seleniummaster.testsuite". In the build path, add the selenium-java-2.39.0.jar file and all the jar files under the lib folder as a reference. Add the TestNG class named UserSettingTest and add @BeforeClass and @AfterClass annotations. See the code in Step 2 for reference.
You also need to add poi-3.9-20121203.jar (Apache poi jar) file in the Build Path as external JARs. 
Step 2: write the UserSettingTest.java code as follows
package com.seleniummaster.testsuite;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.Assert;
import org.testng.ITestContext;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class UserSettingTest {
  private WebDriver browser;
  private String baseUrl;
  //define an Excel Work Book
  HSSFWorkbook workbook;
  //define an Excel Work sheet
  HSSFSheet sheet;
  //define a test result data object
  Map<String, Object[]> testresultdata;
  
  @Test(description="Launches the Selenium Master Test Application and Login")
  public void launchSiteAndLogin() throws InterruptedException{
    browser.get(baseUrl+"/http://seleniumsubbu.blogspot.in/index.php");
     for (int second = 0;; second++) {
          if (second >= 60Assert.fail("timeout");
          try if (isElementPresent(By.cssSelector("img[alt=\"Selenium Master\"]"))) 
            breakcatch (Exception e) {}
          Thread.sleep(1000);
        }
     browser.findElement(By.id("login_login_username")).clear();
     browser.findElement(By.id("login_login_username")).sendKeys("test");
     browser.findElement(By.id("login_login_password")).clear();
     browser.findElement(By.id("login_login_password")).sendKeys("XXXXX")//password is omitted
     browser.findElement(By.id("login_submit")).click();
    try{
      assertEquals(browser.findElement(By.cssSelector("ul.cr > li > a")).getText(),"Test Selenium");
      //add pass entry to the excel sheet
      testresultdata.put("2"new Object[] {1d"navigate to site and login""site opens and login success","Pass"});
    }
    
    catch(Exception e)
    {
      //add fail entry to the excel sheet
      testresultdata.put("2"new Object[] {1d"navigate to site and login""site opens and login success","Fail"});
    }
  }
    
  @Test(description="Navigates to the User Settings page")
    public void openUserSettingPage() throws InterruptedException {
    browser.findElement(By.linkText("Settings")).click();
    
     for (int second = 0;; second++) {
          if (second >= 60Assert.fail("timeout");
          try if (isElementPresent(By.id("login_login_username"))) 
            breakcatch (Exception e) {}
          Thread.sleep(1000);
        }
    
     browser.findElement(By.id("login_login_username")).clear();
     browser.findElement(By.id("login_login_username")).sendKeys("test");
     browser.findElement(By.id("login_login_password")).clear();
     browser.findElement(By.id("login_login_password")).sendKeys("XXXX");//password is omitted
     browser.findElement(By.id("login_submit")).click();
    
     for (int second = 0;; second++) {
          if (second >= 60Assert.fail("timeout");
          try if (isElementPresent(By.xpath("//input[@value='auth']"))) 
            breakcatch (Exception e) {}
          Thread.sleep(1000);
        }
    
     try{
       assertTrue(isElementPresent(By.xpath("//input[@value='auth']")));
      //add pass entry to the excel sheet
        testresultdata.put("3"new Object[] {2d"navigate to User Settings Page""Page Displayed","Pass"});
      }
      
      catch(Exception e)
      {
        //add fail entry to the excel sheet
        testresultdata.put("3"new Object[] {2d"navigate to User Settings Page""Page Not Displayed","Fail"});
      }
    
    
  }
    
  @Test(description="Change a User settings to add as a friends after authorization")
    public void ChangeUserSettings() {
    browser.findElement(By.xpath("//input[@value='auth']")).click();
    browser.findElement(By.id("accountprefs_submit")).click();
    try{
      assertEquals(browser.findElement(By.cssSelector("div.ok")).getText()"Preferences saved");
      //add pass entry to the excel sheet
        testresultdata.put("4"new Object[] {3d"User can change settings""Settings changed","Pass"});
      }
      
      catch(Exception e)
      {
        //add fail entry to the excel sheet
        testresultdata.put("4"new Object[] {3d"User can change settings""Settings NOT changed","Fail"});
      }
    
  }
   
  @Test(description="Log out the system")
  public void Logout() throws InterruptedException {
    for (int second = 0;; second++) {
        if (second >= 60Assert.fail("timeout");
        try if (isElementPresent(By.linkText("Logout"))) 
          breakcatch (Exception e) {}
        Thread.sleep(1000);
      }
    browser.findElement(By.linkText("Logout")).click();
    try{
      assertTrue(isElementPresent(By.id("login_login_username")));
      //add pass entry to the excel sheet
      testresultdata.put("5"new Object[] {4d"User can logout""Logout successfull","Pass"});
      }
      
      catch(Exception e)
      {
        //add fail entry to the excel sheet
        testresultdata.put("5"new Object[] {4d"User can logout""Logout successfull","Fail"});
      }
    
  }

  @BeforeClass(alwaysRun = true)
  public void setupBeforeSuite(ITestContext context) {
     baseUrl = "http://seleniumsubbu.blogspot.in";
     //create a new work book
      workbook = new HSSFWorkbook();
      //create a new work sheet
       sheet = workbook.createSheet("Test Result");
      testresultdata = new LinkedHashMap<String, Object[]>();
      //add test result excel file column header
      //write the header in the first row
      testresultdata.put("1"new Object[] {"Test Step Id""Action""Expected Result","Actual Result"});
      
    try {
      
     browser=new FirefoxDriver();
     browser.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
     catch (Exception e) {
      throw new IllegalStateException("Can't start Web Driver", e);
    }
    
  }
  @AfterClass
  public void setupAfterSuite() {
    //write excel file and file name is TestResult.xls 
    Set<String> keyset = testresultdata.keySet();
    int rownum = 0;
    for (String key : keyset) {
        Row row = sheet.createRow(rownum++);
        Object [] objArr = testresultdata.get(key);
        int cellnum = 0;
        for (Object obj : objArr) {
            Cell cell = row.createCell(cellnum++);
            if(obj instanceof Date
                cell.setCellValue((Date)obj);
            else if(obj instanceof Boolean)
                cell.setCellValue((Boolean)obj);
            else if(obj instanceof String)
                cell.setCellValue((String)obj);
            else if(obj instanceof Double)
                cell.setCellValue((Double)obj);
        }
    }
    try {
        FileOutputStream out =new FileOutputStream(new File("TestResult.xls"));
        workbook.write(out);
        out.close();
        System.out.println("Excel written successfully..");
         
    catch (FileNotFoundException e) {
        e.printStackTrace();
    catch (IOException e) {
        e.printStackTrace();
    }
    //close the browser
    browser.close();
    browser.quit();
  }
  
    private boolean isElementPresent(By by) {
        try {
          browser.findElement(by);
          return true;
        catch (NoSuchElementException e) {
          return false;
        }
      }
}
 Step 3: Create a testng.xml file to run the test suite as TestNG Suite.

Step 4: right click on the testng.xml file and select run as TestNG Suite.

Step 5: Check the test result on the console or in the test-output folder. Generally, open the index.html under the test-output folder to view the result.

The result file indicated that all the tests passed. With this pattern, you can expand the test suite with many test modules.You can also see the TestResult.xls file to view the test result. When you open the excel file, you will see the test result as shown below.

Test Step Id Action Expected Result Actual Result
1 navigate to site and login site opens and login success Pass
2 navigate to User Settings Page Page Displayed Pass
3 User can change settings Settings changed Pass
4 User can logout Logout successfull Pass