Thursday, October 31, 2013

Syntax comparison between Loadrunner and Netgend javascript

    In previous blogs, we know that Netgend platform, built on javascript, can support 50,000 VUsers on one system. But performance testing is not only about supporting a large number VUsers,  it's also about flexibility - how easy it is to emulate client.

    To make the test platform flexible, we have to deal with per-VUser variables,  these are variables that are only accessible (read and write) by a VUser.  This is the basis for many VUsers to run independently.  We will use "pvar" to denote per-VUser variable in this blog.

    Loadrunner offers flexible support on pvar,  you can create a pvar and assign value to it and use its value later to do some operations.   Down side is that it requires some good C background to use it.  In netgend javascript, a variable is naturally a pvar.  So user doesn't need much programming background. Here is a quick comparison.
LoadrunnerNetGend Javascript
Assign to a pvarlr_save_string("John Doe", "fullName")

//generate a random number
//between 20 and 30
randomnumber = rand() % 11
randomnumber += 20
lr_save_int(randomnumber, "age")
fullName = "John Doe";
age  = randNumber(20,30);
get value from pvarname = lr_eval_string("fullName");
age  = lr_eval_string("age");
char msgbuffer[100];
sprintf(msgbuffer, "my name is %s, age is %s", name, age);
lr_save_string(msgbuffer, "msgbuffer")
msgbuffer = "my name is ${fullName}, my age is ${age}";
compare pvar with a string if(strcmp(lr_eval_string("{pMonth}"),"JAN")==0) if (pMonth == "JAN") {
     Note that in the above, loadrunner syntax would require user to be aware of the type of variable and use different functions to access them (lr_save_string vs lr_save_int).   To make matter worse, you may have to use "lr_save_var" in some cases.  In netgend javascript, all is transparent to user, who never has to worry about all these: is it an integer, is it a string, what is the size of the string.

     The above is about scalar pvar, it only holds one value.  What about array variable?   We need it to hold a list of values, for instance, a list of links within a HTML page.  In netgend javascript, a pvar can be array variable,  you just need to use an index to get the value of an item.  The following will give you a good idea of the syntax.

    Here is is an example (taken from Google group discussion),  that shows how to grab a list of values (in string format) from a http response and print them out in Loadrunner.
 web_reg_save_param ("IDValues", "LB=value=\"", "RB=\"", "Ord=All", LAST);  
 // get number of matches  
 nCount = atoi(lr_eval_string("{IDValue_count}"));  
 for (i = 1; i <= nCount; i++) {  
   // create full name of a current parameter  
   sprintf(szParamName, "{IDValue_%d}", i);  
   // output a value of current parameter  
   lr_output_message("Value of %s: %s",szParamName, lr_eval_string(szParamName));  
    In netgend javascript, this is super easy, thanks to the simple syntax for array variable.
 IDValues = substring(http.replyBody, "value=\"", "\"", "all");  
 for (i=0; i < getSize(IDValues); i++) {  
   logMsg(sprintf("Value of %d is %s\n", i, IDValues[i]));  
    Note that in the above, "substring" function will grab all the strings between "value=\"" and "\"" and return a list, "IDValues" variable will hold this list.

   Lastly, we look at syntax related to HTTP.  To access information about a HTTP transaction,  Loadrunner requires you to do the following
 HttpRetCode = web_get_int_property(HTTP_INFO_RETURN_CODE);  
 downloadSize = web_get_int_property(HTTP_INFO_DOWNLOAD_SIZE);
 downloadTime = web_get_int_property(HTTP_INFO_DOWNLOAD_TIME);

   In netgend javascript, we can easily access the information from following variables
 http.finalRespTime :  The time it took beween http request and entire http response is received.
    With them, we can easily do many interesting operations, such as logging all the requests and replies when the respCode is >= 500.
if (http.respCode >= 500) { 

    There will be more to come on Loadrunner syntax vs netgend javascript. Stay tuned.


  1. Your examples appear to come from someone weak in the foundational language of LoadRunner, "C" (Not C++, not C#). If you want to change the syntax web virtual users are also supported in VB and JavaScript, so if users are more proficient in those languages then they can shift their language development model. The default language is C because of it's light weight and cross platform portability.

    Example 1:

    lr_save_int( ( rand() % 10 + 21 ), "age"); // Can also be handled as a parameter with a random number within a range with no code, only a referene to {age} as a parameter with a random number within particular bounds

    Example 2:

    lr_save_string( lr_eval_string("my name is{name}, age is {age}"), "msgbuffer"); // There is no need to pull values into a C variable only to reuse them and convert them back to a Loadrunner variable. You are also going to have an issue with your inline declaration which requires a starting bracketed area for the declaration such as if () { char foo(100)="";......}
    Example 3:

    Your compare is a standard C string compare, valid for all C/C++ based languages.

    Example 4:

    web_reg_save_param ("IDValues", "LB=value=\"", "RB=\"", "Ord=All", LAST);
    // get number of matches , set before request as a service function. Using these parameters for left and right boundary are actually poor because they are so indistinct. You would want something distinct to pull in just the values that you absolutely have to capture.

    // HTTP Request

    for (i = 1; i <= atoi(lr_eval_string("{IDValue_count}"); i++) {
    // create full name of a current parameter
    sprintf(szParamName, "{IDValue_%d}", i);
    // output a value of current parameter
    lr_output_message("Value of %s: %s",szParamName, lr_eval_string(szParamName));

    Example 5:

    By default Loadrunner captures the status code on all requests for reporting purposes. In general you rarely have to capture an http response code if youa re following recommended pratices, which is to check for the content of the expected page. In the case of a 4xx or a 5xx status page you will naturally fail to find the expected content in the response of a request. In such a case where a content check has failed you branch your code based upon the missing content. This also works for an HTTP 2xx or 3xx status page which returns a valid page but one which contains content which is inappropriate to your business process, such as attempting to login to a "dead account" which would return a valid 200 status page but not the appropriate status page to allow the business process to continue....or if you tried within one to two page requests you would hit a 500 class page for an out of content request to the business process under test.

    Since the status' are collected for all requests you can simply run a report at the end of the test for the requests which returned a 500 status without having to decide in advance that you need to collect that data explicitly.

  2. Happy New year to you James.

    I know you are a guru in loadrunner and have been
    advocating for companies to hire more skilled loadrunner professionals to run performance testing. I understand and support it.

    Thanks for the examples on loadrunner, I think they help to show the point that a user needs to have pretty good background in C AND in loadrunner API (lr_save_int, lr_eval_string, lr_save_string ...).

    On Example 5, testing the response content is quite simply and natural on NetGend platform
    if (contains(http.replyBody, /"some patterns here"/) {
    //do something
    I agree that testing http response status code is not quite common but it can be useful in some cases, it's here as an example.

    Again, thanks for the discussion, maybe we are on the same side ;-)