Wednesday, December 25, 2013

Random element in an array

    In performance testing, we sometimes need to deal with a list of values.  For example, when we test an e-commerce web site, we may need to extract a list of products from a page.  With the list/array extracted, we can do operations such as randomly picking an item to view or to add to cart.  On some platform, this logically simple operation can be a daunting job.

    Saw an interesting blog by Howard Clark on testing Peoplesoft Financials 9.0 using loadrunner: "Randomly Selecting an Array of Values and Using That Value As A Parameter".  Here is the script to pick a random BUID copied from that blog. It's listed here just to show how complex it is - you don't have to read it.

 int TotalNumberOfBUIDs;  
 char TotalNumberOfBUIDschar[3]; //working variable  
 char *AvailableBUIDsparam; //working variable  
 TotalNumberOfBUIDs = rand() %TotalNumberOfBUIDs;  
 lr_output_message(“%d”, TotalNumberOfBUIDs);  
 itoa(TotalNumberOfBUIDs, TotalNumberOfBUIDschar, 10); //working variable conversion  
 lr_save_string(TotalNumberOfBUIDschar, “BUIDindex”);  
 AvailableBUIDsparam = lr_eval_string(“{AvailableBUIDs_{BUIDindex}}”);  
 lr_save_string(AvailableBUIDsparam, “BUIDs”);  
 lr_save_string((lr_eval_string(lr_eval_string(“{BUIDs}”))), “BUID”);  
 “Name=VCHR_ERRC_WRK_BUSINESS_UNIT”, “Value={BUID}”, ENDITEM, //application of the value that was captured and then randomized  

    While I was impressed by the author's skills in C,  I couldn't help wondering how an average test engineer can do this.  They know their test subject well, but writing such complex C program can be well above their heads.   On Netgend platform, it's so much easier.

 AvailableBUIDs = substring(str, "class=’PSSRCHRESULTSODDROW’ >", "<", "all");  
 TotalNumberOfBUIDs = length(AvailableBUIDs);
 BUIDindex = randNumber(0, TotalNumberOfBUIDs-1); //indexing is 0 based  
 BUID = AvailableBUIDs[BUIDindex];  //variable "BUID" now contains a random value.

    Even though we tried to use the same variable names as in loadrunner script, our script is still much shorter and easier to understand.  Here are some of the reasons for the simplicity:
  • In a NetGend script, all variables are local to an instance/Vuser.  There is no need to use API to get the value of a variable (called "parameter" in Loadrunner) into code space or write the value back to the variable after some operations in the code space.
  • NetGend supports the array variable.  In this case, the variable "AvailableBUIDs" holds the array of extracted BUIDs.
  • You can get the length of the array by the function "length()".
  • You can get any element in the array by indexing using [].  For example: AvailableBUIDs[BUIDindex] gives the value of "BUIDindex+1"th element. (it's 0 based)
    Note that the above short script (4 lines) can be made even shorter.   The readability may suffer a little bit but it's still fairly easy to understand. 
 AvailableBUIDs = substring(str, "class=’PSSRCHRESULTSODDROW’ >", "<", "all");  
 BUID = AvailableBUIDs[randNumber(0,length(AvailableBUIDs)-1)];  

    A good performance test platform needs to make complex test scenarios simple, not the other way around.


  1. Your example contains a lot of extraneous code. A solid performance tester with an understanding of the language of their tool can reduce that complexity in terms of numbers of actual lines of code.

    Plus, if you don't care for C, Loadrunner also supports the use of VB, Java and in some cases C# or JavaScript. As development skills are a primary foundation skill set for any performance tester it is not unreasonable to expect that a performance tester have mastery of the language of their performance testng tool.

    Let us also take a look at why C is the default language of LoadRunner.
    (1) It is standardized and open (ANSO Standards)
    (2) It is the lowest weight language, outside of assembler. You want your tool to have as low an overhead as possible
    (3) It is enormously flexible in terms of what you can do with the tool if you have something odd which is non standard which has to be addressed in code where no native integration exists
    (4) It is cross platform by design without the need for a virtual machine. NAtive code always runs faster.

  2. Happy New year to you again James.

    Thanks for listing the reasons why loadrunner used C as the default language.
    I like C programming too and wrote a user space tcp/ip stack in C. What I wanted to point out in the blog is that there can be better choices of language/syntax so that it's easier for users who doesn't have lots of programming background to understand the logic.
    Have the following statement tends to obscure the simple logic in it.
    lr_save_string( lr_eval_string("my name is{name}, age is {age}"), "msgbuffer");

    For someone who doesn't have lots of programming background,
    msgbuffer = "my name is ${name}, age is ${age}"
    is a little easier to understand.

    Thanks for the discussion.