Showing posts with label LoadRunner. Show all posts
Showing posts with label LoadRunner. Show all posts

Wednesday, February 8, 2017

Debugging a LoadRunner script

Each performance engineer has his own style of debugging and is comfortable one of the approaches. While the following approach doesn’t claim to be the best approach, it sure helps with an approach for the beginners and act as a quick reference for the hands on guys as well.

·         One request at a time - While some go with one concept at a time, this approach suggests to go with one request / transaction at a time. During the debugging process, place a return -1 or return 0; after the transaction to ensure that replay of the script goes only until the transaction that we are currently working. Apply all the concepts like parameterization, correlation, page verification, think time and transactions for this transaction and replay to ensure that the script is working fine until the current transaction.
Note: return -1 will stop the execution of the script whereas return 0 will stop only the current iteration. To understand the difference, try setting the Runlogic to more than 1 iteation.

·         Correlation Challenges: The most probable reasons that a dynamic data is not captured is
o   The Left and right boundaries defined in the correlation function can be wrong – Be sure to check for the additional spaces, Tab Vs. spaces, escaping the double quotes
o   The placement of correlation function – Majority of the cases, the dynamic data should be available in previous request’s response. However, this may not be true always. Be sure to identify the request that receives the response with dynamic data and the correlation function should be placed above such request
o   Size matters – if huge dynamic data (Ex: Viewstate) is to be captured, be sure to specify the max length of the LR parameter by using the function web_set_max_html_param_len() function before capturing the dynamic data
o   Ensure dynamic data is generated by server – While 95% of the cases the dynamic data is received in server response, there is also a chance that the dynamic data is generated by client side java script as well (Ex: Hashcode generator). In such cases, the java script code needs to be identified and integrated with the script using web_js_run() function

·         Headers are crucial – LoadRunner is able to handle all the standard headers by default. However, if the request contains custom headers, those need to be added in the script explicitly with the functions web_add_header() / web_add_auto_header(). The easiest way to identify if the script is missing on any custom headers is to compare the snapshot information / Advanced trace in Log settings with network sniffing data (either from Developer tools or Fiddler session’s data)

·         Encoding data – web_url() and web_submit_data are capable of handling URL encoding automatically whereas the web_custom_request expects the form data as is. Hence, if the raw data of the request contains the URL encoding, be sure to convert the text into URL encoded form by using the function web_convert_param()

     As long as the request triggered from LoadRunner is same as the one from the browser, the scripts should work fine without any issues. Simulating the exact same request to that of the browser is the key while debugging the script.


Sunday, August 10, 2014

strstr function in LoadRunner

The most common problem that a performance tester face with automation in LoadRunner is string manipulations. To understand and implement string manipulations, one need to know the important functions that are used to do so. the function strstr() is one of the most important functions that are used for string manipulations.

The function strstr() returns the address location of a sub-string in a main string. If the sub-string is not found in the main string, the function would return zero. Hence this function can be used to validate if a sub-string is found in the main string or not.

To understand the function better, let us consider a small example:

char MainStr[1000] = "Welcome to Performance Testing Training online";
char SubStr[10] = "Train";
char * position;

position = (char *)strstr(MainStr, SubStr);

In the above example, when a MainStr variable is declared, a variable is created and 1000 bytes are allocated and the variable "MainStr" contains the starting address location. Let us assume that in the current example the Memory address location allocated for the variable MainStr is from 12001 to 13000. Now the variable MainStr contains the address location 12001.

When the strstr() function is executed, the compiler looks for the characters in the substring starting from the first address location i.e. 12001 in this case. Now, the first character in the SubString is 'T' which would be first found at the address location,  12024 (as in Testing), however the second character in the Substring does not match with the character in the next address location. So, the compiler ignores the address location 12024 and proceeds further scanning for the character 'T' which would be found at the location 12032. All the subsequent characters do match with the characters in the subsequent address locations and hence the function strstr would the return the address location 12032. The function is type casted such that the return value is explicitly defined as character pointer.

This is the most used function for most of the string manipulations and the coming blogs illustrate the usage of this function.

I hope this information is useful. If you like the content in this blog, please click +1/ Comment. Please feel free to share with your friends.

Monday, June 9, 2014

Understanding Randomization in LoadRunner

Randomization is a common practice with majority of the performance test scripts, where dropdown / Radio buttons / Links has to be chosen by the user randomly.

For example the application requires choosing a value from the drop down randomly, then the important thing is to know how many values are there in the drop down and what their values.

We all know the web_reg_save_param() or web_reg_save_param_ex() function has to be used to capture the values. Now, because we need all the values we'll specify the attribute "ORD=ALL" / "Ordinal=all". Assume that the function is written as below:

web_reg_save_param("DropdownValues", "Lb=<option>","rb=</option>", "Ord=all", LAST);

When the above function is executed, LoadRunner creates N+1 LR variables if there are N values in the drop down.

The first drop down value will be saved to an LR variable named "DropdownValues_1" and the second value from the drop down will be save to an LR variable named "DropdownValues_2" and so on. The total number of matches / count would be saved to another parameter called "DropdownValues_count".

The function used to choose a random value is lr_paramarr_random(). This function returns an address location of the random parameter.

In our example the function should be used as:

char * randVal;


randVal = lr_paramarr_random("DropdownValues");

As the variable randVal is C string variable, cannot be used in protocol functions,  this has to be converted to an LR parameter using below statement (for details on why, please refer to variable conversion in LoadRunner).
lr_save_string(randVal, "RandDropdownVal");

When lr_paramarr_random("DropdownValues") is seen the script, the script immediately checks if there is a parameter named "DropdownValues_count" and tries to retrieve its value. If this parameter is not available, an error would be thrown.

Assuming that the count is 10, now it generates a random value between 1 -  10 and refers to the corresponding address location. i.e. if the random number is 6, it searches if there is an LR parameter called "DropdownValues_6", if yes,  its address location is returned to the string variable.

If there is no such parameter, it would throw a warning saying that "The string with parameter delimiters is not a parameter"

Hence it is very important to capture all the values using the web_reg_save_param() function with the ORD attribute set to ALL if at all the parameter has to be used for randomization.

In the next article, we will see how we can utilize this behavior in building a custom C function that works similar to web_reg_save_param() with ORD being set to ALL.


Monday, May 19, 2014

in LoadRunner Did you Know?

  • Save the current times tamp in Milli seconds to an LR parameter can be achieved with the function web_save_timestamp_param()
  • web_url() and web_submit_data() are capable of the encoding the form data automatically. But web_custom_request() cannot encode the form data automatically. The encoding can be done by the function web_convert_param()
  • Automation of the windows based web applications (that uses NTLM authentication) uses the web_set_user() function for sending the username and passwords. While replaying the script, it is recommended to use the run time setting Preferences --> Advanced -->WinInet Replay instead of Sockets
  • Reading and writing from the same file can be achieved by Virtual Table Server
  • The function lr_paramarr_random("x") first validates if there is an LR parameter called x_count, if there is no such parameter, it returns an error
  •  The function web_global_verification() works same as the run time setting Content check, except that the global verification can be paused and resumed with the functions web_global_verification_pause() and web_global_verification_resume()

Thursday, May 8, 2014

Variable conversion in LoadRunner

In the last post, I have given an overview on what types of variables are seen in an LR Script and where they should be used.

This article covers on conversion of LR Variables to C Variables and viceversa.  There are three important LR functions used for the conversion. 
We'll  see one at a time.

lr_eval_string()
This function evaluates a load runner variable and returns its value if placed in flower braces. Let us try to understand how it really works.

lr_eval_string("test") returns a string called "test"
lr_eval_string("{test}") - Now this function checks if there is LoadRunner variable called test or not. 
If there is a LoadRunner variable named test and its value is "Welcome". Now the function lr_eval_string("{test}") returns a string "Welcome"

If no LoadRunner variable exists with the name test, then the function lr_eval_string("{test}") returns a string "{test}"

Now let us see two more last example of lr_eval_string() function:

Assumption: There is an LR variable called test whose value is "{Welcome}". There is another LR variable called Welcome whose value is "Performance Testing Online".

lr_eval_string("{test}") - This returns a string "{Welcome}"
lr_eval_string() function does not do nested evaluation

lr_eval_string(lr_eval_string("{test}"))
 = lr_eval_string("{Welcome}");
 = "Performance Testing Online"

LR to C String
Now that you understand the usage of lr_eval_string() function let us see how we can convert an LR Variable to C string variable.

char CStr[100];

to save "Performance Testing Online" into the string variable CStr, the syntax is:

strcpy(CStr, lr_eval_string(lr_eval_string("{test}")));

Please note that an equal symbol (=) cannot be used to assign a value to a string variable. We will have a separate article on why.

So, the conclusion is, to save an LR value to a C string variable, the lr_eval_string() function is used.

Now let us see, how we can convert an LR Parameter to C integer variable
 
let us assume that the LR variable test stores a value of "10".

LR to C Integers
This value should be converted to a string format first using lr_eval_string() function. This function returns a string value. To convert a string value into an integer, we have C function called atoi() read it as A to I (meaning alphabets to Integers)

int Count;

Count = atoi(lr_eval_string("{test}"));

This is how a value in LR variable is saved to a C variable. Though the heading says converting an LR variable to C variable, in fact we are storing the value of an LR variable into a C variable.

Now let us see the otherway i.e. converting a C integer / String to an LR parameter.

we have two functions named lr_save_string() and lr_save_int() to save a string and integer values to an LR parameter respectivily.

C to LR
int i = 256;

lr_save_int(i, "Total"); 

Now Total is an LR variable which stored a value of 256 in it. Inside the web_url() or web_submit_data or web_custom_request it can be used as {Total}

char Text[100] = "Welcome to Performance Testing Online";

lr_save_string(text, "Status");
Now Status is an LR variable which stored the entire string in it. In a web request it should be used as {Status}


I hope this article is informative and helpful.  If you have any questions, please feel free to comment.


Thanks,
Ram N

Sunday, May 4, 2014

Variables in a LoadRunner script

We have already seen the various types of functions in a Web (Http/HTML) script. The language used for the Web based script is "C", which means all the C data types can be used in a LoadRunner script.

In a Web protocol script, the variables are classified into two categories.

  • C variables
  • LR variables

C Variables - Being a procedural language, C expects all the variables to be declared at the beginning of the function/action.
For Example:

int randNum;
char Strbuff[100];
float thinktime;

However, any LR variable does not need any declaration as such. But, the script expects the variable name to be specified in the function.

For example

web_reg_save_param("SessID", "LB=............","RB=", LAST);
in the above statement, we are explicitly saying that SessID is an LR variable to which the dynamic data is to be saved.

Let us look at few other examples on how the LR variables specified in the script.

web_reg_find("Text=SampleText", "SaveCount=txt_Count", LAST);
in the above example, the LR variable that is created is txt_Count.

lr_save_string("SampleData", "x"); /lr_save_int(10, "y")

In the above cases, the string "Sample Data" or the integer 10 is stored to  LR variable called x /y ( created first and then value is stored).

So, the conclusion is C variables are to be declared at the beginning of the script and LR variables need not be.

Now the most important aspect is where to use what type of variables? Where can C variables be used, where can LR variables be used.

Putting it in simple terms, the protocol based functions like web_url()/web_submit_data(), LR variables are to be used with in flower braces for example {x} or {SessID} or {txt_Count}

In the Language specific functions, its obvious that only C variables are to be used. For example

randNum = rand()%Count + 1;
sprintf(buff, "Test_%d", i);
strcpy("Welcome", StrBuff);

LR functions accepts either types of parameters. For example, 

lr_save_int(i, "y") - where i is C variable and Y will become an LR variable.

lr_eval_string("{x}"); - here x is an LR parameter.

I hope this article provides you the basic information on types of variables of an LR Script. The next article explains how to convert these parameters from type to the other.

Sunday, June 10, 2012

Understanding a LoadRunner Web (HTTP/HTML) script

Once a script is recorded using the Virtual User Generator with the best recording options (please refer to the link ), the next important thing is to understand the complete script and the functions recorded in the script.

At a very high level, the entire script can be classified into three groups i.e.

  • Protocol Specific functions
  • LoadRunner functions
  • Language specific functions
Protocol Specific functions: 
These functions can be used with a specific protocol only and they cannot be used with any other protocol. For a Web (Http/HTML) protocol, the commonly seen functions are:

  • web_url(), web_image(), web_link() - All these functions are used to simulate a GET request
  • Web_submit_form() is used to simulate a POST request
  • web_submit_data() is used to simulate both GET and POST requests. The attribute "Method" tells if that request is a GET or POST.

web_reg_find() and web_reg_save_param() are the service functions used for page verification and correlation respectively.
All the above functions are starting with the word "web" indicating that they are web protocol specific functions and cannot be used outside Web protocol.
Few other web protocol functions are:

web_set_user(), web_set_max_html_param_len(), web_cache_cleanup(), web_cleanup_cookies() etc

LoadRunner functions:
All these functions are loadRunner specific and can be used across any protocol. All these functions start with lr_. Few examples for LoadRunner functions are:

lr_start_transaction() - To start a transaction to measure the response time
lr_end_transaction() - To stop a transaction to measure the response time
lr_think_time() - to wait for a specified duration
lr_eval_string() - To evaluate the value of a LoadRunner parameter placed in {}
lr_save_string() - To save a string to a LoadRunner parameter
lr_save_int() - To save an integer value to a LoadRunner parameter
lr_exit() - exit a loop/iteration/user from execution
lr_set_debug_message() - To control the log settings of the replay log
lr_output_message() - To write to the output log with an information level setting
lr_error_message() - To write to the output message with error level
etc

Language specific functions:
These functions are not a part of the tool, all the functions that can be used in a language(C or Java) can be directly used in the script provided that the protocol is supported in a language.
For example, The Web(HTTP/HTML) protocol is supported by the C language. Hence all the C functions can be used directly in Web script.
The commonly used functions are:

rand() - to generate a random number
atoi()  - converting a string into an integer
sprintf - Saving a formatted output to a string buffer
strcat - string concatenation
strcpy - Copying into a string
strtok - String tokenizer function

The JAVA protocol cannot support the C language and hence these functions cannot be used by the Java based script.

Hope the information provided about the classification a LoadRunner script is helpful in understanding how the scripts work.


Context based Recording Vs Context less Recording and HTML Vs URL based recording


To understand the "context based recording", if some one asks you a question "How is he doing?", you would definitely ask "Whom are you referring to?". But if the same question is asked during a discussion about one of your friends whose name is  Karthik, you would not ask the question because in the current context HE refers to Karthik. So you can understand who "HE" is. 


The context less question would be like "How is Karthik doing?". There won't be any more questions. Because you are explicitly pointing to a person and not using any generic terms like He, it. This is called context less mode.

In the above example of "HE", "HE" refers to Karthik only for that discussion and for a different discussion "HE" may refer to someone else.  The context is only until the discussion.
 
There are two recording modes available in LoadRunner to record the user actions of a Web Application. They are

·         HTML mode

·         URL Mode

HTML mode – In this mode of recording, each USER ACTION is recorded as a separate request.  To put it in simple terms, each HTML content (usually a page except in case of HTML Frames) is recorded as a request

If all the user actions are recorded into a Single ACTION of the script, then the HTML mode of recording acts as "Context Based Recording".

The Virtual User Generator understands the Context by looking at the previous request's response. Hence it identifies the Forms, Images etc and you would notice the below functions in a context based recording of the script.
web_submit_form() - to simulate a POST Request
web_image(), web_link() - to simulate a GET request



In VUGen, the context is applicable only till the Action. If you record a user action into a different action, the context would reset and again the context has to be created.

In a case where the tool has to enter some data in a form and if the form is not found in its previous response, the tool will halt the execution of the script.  Every request is directly dependant on the previous request’s response and has high chances of failure with the UI changes to the web application


The advantages of using the HTML recording mode is that the size is very compact and the customization efforts would be very less. The other side of the coin is that, with the UI changes to the web applications, these scripts would require very high maintenance costs.

URL Mode: In this mode of recording each resource requested by the user is recorded as a separate request.  in other words, whatever the content (like images, CSS, JS, HTML) that makes the HTML page is recorded as a separate request. When a web site is launched apart from the HTML content, there would be lot of images, java script files, CSS files downloaded. All these are called resources and each resource is recorded as a separate request.

URL mode is always context less recording because this mode refers to the data and the URL of a request directly instead of depending on previous response. This mode does not depend on the UI of the application, rather the actions associated with the user actions performed on UI. As each resource is recorded, the size of the script would be very high and this also involves in lot of customization. The benefit of having scripts with URL recording mode is that the maintenance cost associated with these are very less and can be used across various releases of the product despite lot of UI changes.

Usually URL mode of recording is used with Non –browser applications in other words any thick client activity is recorded using the URL mode.

Trade off – with the HTML recording mode, another option is available under “Advanced options” of HTML mode. The option available is Explicit URLs only mode.

The benefits of the HTML mode and URL mode is clubbed together in HTML à Explicit URLs only. With this mode, the size of the script would be compact (as only the user action is recorded as request, not at the UI level but at the request level) and requires a bit of more customization efforts but has the advance of high maintainability for longer durations. This is the most recommended recording mode for web applications where the scripts have to be maintained for longer durations

Tip: Have you forgotten to record the script using HTML à Explicit URLs mode? No problem....
Change the recording options to HTML à Explicit URLs only and now navigate to Toolsà Regenerate script. The regenerated script is as fresh as a recorded script using HTML Explicit URL’s only. But do remember that whatever the changes that are made to the script would be gone if the script is regenerated.

Next post: Understanding various logs in LoadRunner

Sunday, May 27, 2012

Date Randomization in LoadRunner

One of the common requirements that a performance tester may experience is randomizing the date.

For example in a online booking of train ticket or air tickets, we may want to book a ticket for a post date which can be any where between tomorrow or 60 days from today. Usually if it is a date is constant, that can be parameterized in LoadRunner. If thats not a fixed date and needs to be randomized, the below code will be helpful.

rand() is a C function that is used to generate a random number.
rand()%30 will give us a random number any where between 0 -29.

randNum = rand()%30 +1 //gives you a random number anywhere between 1 - 30

lr_save_datetime("%d/%m/%Y", DATE_NOW + ONE_DAY*randNum, "JrnyDate");

lr_save_datetime() is the loadrunner function to save a date of a specified format to a loadrunner variable.

In the above example, the date in the format of Date/Month/Year (25/05/2012) is saved to a LoadRunner parameter called "JrnyDate". DATE_NOW gives us the current date and ONE_DAY*randnum will give us a future random date.

Hope this information is helpful.