Sunday, March 11, 2018

New blogging website

Just wanted to let the community know that I no longer user blogger to blog by articles.

As of this month, I have started blogging on my own website called OzPerf.

Thursday, December 7, 2017

Modeling - Probability distribution and JMeter code


Skewness:
"In probability theory and statistics, skewness is a measure of the asymmetry of the probability distribution of a real-valued random variable about its mean. The skewness value can be positive or negative, or undefined."  (source wikipedia)


Exponential:
"In probability theory and statistics, the exponential distribution (also known as negative exponential distribution) is the probability distribution that describes the time between events in a Poisson point process, i.e. a process in which events occur continuously and independently at a constant average rate." (source wikipedia)

When designing application simulation model for performance testing you will come across scenarios which will require you to use different probability distribution to emulate correct production behavior. For example, average # of items per order, number of sessions or think time between pages.

The code below allows you to generated a skewed & exponential distribution for such a case in JMeter to emulate correct behavior as observed in production.

Skewed distribution code
min = VALUE; //update this value to minimum value expected in the distribution
max = VALUE; //update this value to maximum value expected in the distribution
bias = VALUE; //update this to a value against which  the distribution should be biased toward
influence = 1; //[0.0, 1.0] - 1 means 100% influence
rnd = Math.random()*(max-min)+min;
mix = Math.random()*influence;
result = rnd *(1 - mix) + bias * mix;

NOTE: This code is from stackoverflow and I don't remember the link to it. If you do, please let me know.

Exponential distribution code
Avg = VALUE; //update this value to reflect mean value for the distribution 
MIN = VALUE; //update this value to minimum value expected in the distribution
result = (long)(-(double)Avg*Math.log(Math.random()))+MIN;

Example (Exponential distribution):
MIN = 1;
Avg = 2.5;
result = (long)(-(double)Avg*Math.log(Math.random()))+MIN;
If above code is executed for 200 iterations/thread, it will generate the values depicted in the histogram below. More iterations executed, better the distribution will look like. For testing, two threads were used.


NOTE: If you want to have a hard boundary, add an if condition in the code to check against a MAX value.

Example (Skewed distribution):
min = 1;
max = 10;
bias = 3;
influence = 1;
rnd = Math.random()*(max-min)+min;
mix = Math.random()*influence;
result = rnd *(1 - mix) + bias * mix;

If above code is executed for 200 iterations/thread, it will generate the values depicted in the histogram below. More iterations executed, better the distribution will look like. For testing, two threads were used.



Use beanshell sampler to generate the value and save it in a variable. Pass variable into the loop controller to control it. Below is the code in beanshell sampler.




NOTE:
1: Make sure you run a few tests to get the distribution right to reflect what is happening in production.
2: If you have a better code to generate probability distribution be it exponential or any other kind, I would love to  know.

Tuesday, May 26, 2015

Merging Wireshark files

Note to myself, If you want to merge multiple wireshark files, save & execute the following command from a batch file.
Cmd /V:on /c {mergecap wireshark utility} -w {mergefile name} {files to merge}

where:
{mergecap wireshark utility} - mergecap.exe file path
{mergefile name} - name of the merged file to be generated
{files to merge} - wireshark files that need to be merged

Example:
Cmd /V:on /c "c:\Program Files\Wireshark\mergecap.exe" -w allWireshark.pcap wiresharkDump*.pcap

Run the batch file from within the same folder where all wireshark files are located.



Tuesday, September 24, 2013

SoapUI - using WHERE IN clause and Groovy code to concatenate strings

Recently, I worked on a project that was using SoapUI Pro to test an application. One of the testers had a working test case in SoapUI but wanted it done differently and therefore, approached me for a solution. Following outlines the scenario and a quick groovy code I wrote to address what he really wanted.

Scenario:
He was connecting to a database using SoapUI JDBC step and retrieving more than one result for a SQL query. He was then using FOR loop to iterate through all the values. In the FOR loop, he had another JDBC step which took result value as a parameter and returned an appropriate response (using assertion to validate the response).

What he wanted:
He wanted to get rid of FOR loop and pass all the values returned from the first JDBC step into second JDBC step.

Solution:
The solution I came up with was to concatenate all the values from the first JDBC step using a groovy code and then pass the returned string from the code into a separate JDBC step. Also change the SQL query in the final JDBC step to use WHERE IN clause.

For blogging purpose, I am connecting to MySQL database on my local machine using SoapUI Pro 4.5.2 (trial version).

I have created two tables in MySQL database. First table is a class which contains StudentName and ClassName. Second table is a Subject with StudentName and Subject fields. For code demonstration purpose, I will be querying the database to return me names of all the stundent that are in Class 3. Then I will concatenate the names using groovy code and pass it to a separate JDBC step to get me the StudentName and the Subject they are enrolled in.

NOTE:
  • This code does not cater for all the possibilities as it is only for blogging purpose. 
  • Also make sure you are adding the MySQL JDBC driver in SoapUI ext folder so you can connect to the database.
  • I am sure the code below can be refined further. saving xmlRecCount.toInteger() value to a parameter.
Steps:
  1. Add a JDBC Step to the test case. This JDBC step with query the class table and return student names that are in class 3. 
  2. Add a DataGen step to the test case. In this step create a parameter with "Type" as "Script". This Script will take response from the first step, concatenate all the student names into one string and pass it to the parameter. 
  3. Finally add another JDBC step to the test case. This step will query the Subject table uisng WHERE IN Clause and IN value will be the parameter created in step 2 above.
Code:
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
def holder = groovyUtils.getXmlHolder("GetStudentName#ResponseAsXml")

def concSqlString=""   //initialize parameter string concSqlString
def cnt =1             //initialize counter

//Get the total count of records that have the CLASS.STUDENTNAME
def xmlRecCount=holder["count(//Results[1]/ResultSet[1]/Row/CLASS.STUDENTNAME)"]


//check if only one row is returned
if (xmlRecCount.toInteger()==1)
{
      node = holder.getNodeValue('//Results[1]/ResultSet[1]/Row/CLASS.STUDENTNAME')
     concSqlString=concSqlString +"\""+node+"\""
}
else{
        //for each node, concatenate the node value to concSqlString variable
 for (node in holder['//Results[1]/ResultSet[1]/Row/CLASS.STUDENTNAME'])
 {
 if(cnt<xmlRecCount.toInteger()){
  concSqlString=concSqlString+"\""+node+"\","
  cnt=cnt+1
 }
 else
 concSqlString=concSqlString +"\""+node+"\""
 }
}

//return the concSqlString 
return concSqlString

Saturday, August 10, 2013

LoadRunner - Selecting random value using lr_paramarr_random function

In performance testing, it is really important to simulate a realistic user path through an application. For example, randomly select an image link from a gallery or select a share from a share list. In such situations, you can use the LoadRunner lr_paramarr_random function to select a random value from a captured parameter array. Similarly, you can also write a code to do the same.

Before you use the above function, you will need to use web_reg_save_param function to capture all the ordinal values. This can be achieved by passing "ORD=ALL" into the function.

The following code demonstrates the use of lr_paramarr_random function. The code saves link Ids using  web_reg_save_param function and then uses lr_paramarr_random function to randomly select an Id value. The value is passed as a parameter in web_text_link function to navigate to the appropriate webpage.

Action()
{

 //Capture all the Link IDs
 web_reg_save_param("LinkID","LB=id=\"","RB=\" href=\"default.aspx?content=business_","ORD=ALL",LAST);

 lr_start_transaction("VU01_01_Homepage");
 web_browser("website", 
  DESCRIPTION, 
  ACTION, 
  "Navigate={WebsiteUrl}", 
  LAST);

 lr_end_transaction("VU01_01_Homepage",LR_AUTO);

 lr_think_time(10);


 //Save a randomly selected ID to a Parameter
 lr_save_string(lr_paramarr_random("LinkID"),"RandomLink"); 

 //Printout the randomly selected parameter
 lr_output_message("%s",lr_eval_string("{RandomLink}"));

 //Navigate to the appropriate webpage associated to the ID
 lr_start_transaction("VU01_02_RandomLink");

 web_text_link("Links", 
  "Snapshot=t2.inf", 
  DESCRIPTION, 
  "Id={RandomLink}",
  ACTION, 
  "UserAction=Click", 
  LAST);

 lr_end_transaction("VU01_02_RandomLink",LR_AUTO);
 
 web_browser("Sync", 
  "Snapshot=t3.inf", 
  DESCRIPTION, 
  ACTION, 
  "Sync", 
  LAST);

 return 0;
}
Following is a screenshot of replay log, displaying the random id's selected for each iteration. It also displays the values captured using web_reg_save_param function.