Showing posts with label Correlation. Show all posts
Showing posts with label Correlation. Show all posts

Manual Correlation in LoadRunner - Video

In previous LoadRunner video (Automated Correlation in LoadRunner) I shown how to use Automated Correlation. The present LoadRunner video explains how to manually correlate dynamic values:
  • How to find dynamic values in a server response
  • How to correlate them in LoadRunner
  • How to verify the correlation
There is a screenshot from the present LoadRunner video:
Manual Correlation in LoadRunner

Automated Correlation in LoadRunner - Video

Correlation is a key concept of HP LoadRunner. The present LoadRunner video tutorial explains how to correlate dynamic values in LoadRunner automatically:
  • How to find dynamic values to be correlated
  • How to compare recorded & replayed dynamic values
  • How to correlate them in LoadRunner
  • How to verify correlation
There is a screenshot from the present LoadRunner video:
Different server responses
Also, this LoadRunner video explains concepts of Correlation and how Correlation works.
Video tutorial demonstrates LoadRunner Correlation by the example of HP Web Tours application, which is shipped with LoadRunner. So, you can repeat and learn all shown actions yourself.

Automated Correlation in LoadRunner - Video


Related articles:


Do you like these LoadRunner video? Would you like to receive them in the future?
If yes, please subscribe to this blog RSS feed or by Email. (How to subscribe? Video guide)



Do you
know that you are free to use/copy/publish all my materials on your site/blog?


LoadRunner Correlation - How to capture an array of dynamic data with web_reg_save_param function

Imagine, that server returns the following response:
(since blogspot.com doesn't show tags correctly, I'm reluctant to show server response as image) .

And we have to capture dynamic values of all IDs (underlined with green lines). These values can be used later - say, for LoadRunner script correlation.

As usual, several solutions exist :) Let's see them:

  1. Insert five web_reg_save_param functions using "Ord=1" (2, 3, ...) attribute:

    1. web_reg_save_param ("ID1Value", "LB= value=\"", "RB=\"", "Ord=1", LAST);
    2. web_reg_save_param ("ID2Value", "LB= value=\"", "RB=\"", "Ord=2", LAST);
    3. web_reg_save_param ("ID3Value", "LB= value=\"", "RB=\"", "Ord=3", LAST);
    4. web_reg_save_param ("ID4Value", "LB= value=\"", "RB=\"", "Ord=4", LAST);
    5. web_reg_save_param ("ID5Value", "LB= value=\"", "RB=\"", "Ord=5", LAST);


    Tips: Please, note that web_reg_save_param function does not perform correlation. web_reg_save_param function just registers a request for correlation from the next server response. That's why web_reg_save_param function should be placed before action functions, such as: web_url, web_submit_form, and others.

    Tips: Enable extended logging for LoadRunner parameters substitutions. It will be helpful for script debugging:

    OK, let's execute our script and see results - whether values will be captured or not:
    As you can see, web_reg_save_param functions executed correctly and parameters contain values.
    I would remind you that, we used "Ord" attribute. It indicates the ordinal position or instance of the match. Read LoadRunner Help on web_reg_save_param function for detailed info.

    Then, you can perform any operations with saved parameters (for instance, read article How to perform basic operations on LoadRunner parameters?)


    Another solution is to not use "Ord" attribute. Instead of it, we will extend boundaries to capture values from a server response.


  2. Insert five web_reg_save_param functions with extended boundaries:

    1. web_reg_save_param ("ID1Value", "LB=ID1\" value=\"", "RB=\"", LAST);
    2. web_reg_save_param ("ID2Value", "LB=ID2\" value=\"", "RB=\"", LAST);
    3. web_reg_save_param ("ID3Value", "LB=ID3\" value=\"", "RB=\"", LAST);
    4. web_reg_save_param ("ID4Value", "LB=ID4\" value=\"", "RB=\"", LAST);
    5. web_reg_save_param ("ID5Value", "LB=ID5\" value=\"", "RB=\"", LAST);


    I extended left boundaries and included ID1, ID2, etc with inverted quote. Since new boundaries will define values explicitly, we don't need use "Ord" attribute. That's why I deleted "Ord" attribute from web_reg_save_param function.

    Let's execute new code and see results:
    Values captured successfully! :) Ain't it fun? :)


    I think, now is a time to introduce third way how to capture an array of dynamic data.
    For that, we will use "Ord=All" attribute of web_reg_save_param function:


  3. Insert web_reg_save_param function using "Ord=All" attribute:

    1. web_reg_save_param ("IDValues", "LB= value=\"", "RB=\"", "Ord=All", LAST);


    It looks very simple, doesn't it? :) Let's execute it and see results:

    Values captured. Great!
    There are several important items and I would like to pay your attention:
    • We specified one web_reg_save_param function only with "Ord=All" attribute, and it captured all values.
    • Captured values were saved into parameters with automatically generated names.
      Please, note that I specified initial parameter name - "IDValues". Values were saved into parameters "IDValues_1", "IDValues_2", "IDValues_3", etc. So, an array of values were created.
    • Additional parameter was created automatically - "IDValues_count". It contains number of matches saved to the parameter array.

    Please, see this example - how to use "_count" LoadRunner parameter to iterate all items in a array of captured values:

    1. web_reg_save_param ("IDValues", "LB= value=\"", "RB=\"", "Ord=All", LAST);

    2. // get number of matches
    3. nCount = atoi(lr_eval_string("{IDValue_count}"));

    4. for (i = 1; i <= nCount; i++) {
    5.     // create full name of a current parameter
    6.     sprintf(szParamName, "{IDValue_%d}", i);

    7.     // output a value of current parameter
    8.     lr_output_message("Value of %s: %s",szParamName, lr_eval_string(szParamName));
    9. }


    And the result of execution is:
    (click to enlarge image).

    Using above example, you can simplify LoadRunner script correlation. If you have to capture an array of values from server response, do not forget about web_reg_save_param function only with "Ord=All" attribute.


Summary:
  • I provided several solutions how to perform correlation and capture an array of dynamic values.
  • Last solution (web_reg_save_param function using "Ord=All" attribute) is more simple and convenient.
  • One call of web_reg_save_param function can capture five, ten or hundred values and place them into an array of parameters.
    It is convenient - LoadRunner correlation becomes easier.


Do you have questions on LoadRunner correlation, my dear reader?
Ask me, and I will do my best to prepare exhaustive and detailed answer...

---
Thank you,
Dmitry Motevich



Related articles:

How to select correct boundaries for web_reg_save_param LoadRunner function?

I will explain and show - how to select correct boundaries for web_reg_save_param LoadRunner function.

web_reg_save_param
is used for LoadRunner script correlation. That's why every load tester should study this function thoroughly, if you wish your scripts work correctly.

Imagine that the server returns the following part of HTML page:
HTML source codeNote: I will refer to this example later.

  1. What boundaries should be used in web_reg_save_param LoadRunner function to capture value of "ID1" (abcde)?

    The correct left boundary for web_reg_save_param function should be:
    • ID1" value="
    And right boundary for web_reg_save_param is:
    • "
    See the solution:

    Do you know why it is? I will explain in details.

    To find out the boundaries, we have to see texts located on the left and on the right.

    What is the text located on the left? There are several variants:
    • " (inverted comma)
      Actually, inverted comma cannot be used as left boundary, because it is located in several places in server's responce.
      So, we have to extend the left boundary:
    • =" (equal sign and inverted comma)
      These two characters also unusable, because it is located in several places too. For example, type="text" or value="abcde". So, we have to extend the left boundary again.
      So, I recommend to include unique part - ID1:
    • ID1" value="
      These string occurs one time in server's response. So, it can identify uniquely the value of "ID1" (abcde).

    Right boundary can be found easily. Since abcde is followed by inverted comma, we can assign inverted comma to right boundary. So, right boundary is ".

    We have found left and right boundaries, so the final web_reg_save_param function is:

    1. web_reg_save_param("pID1Value", "LB=ID1\" value=\"", "RB=\"", LAST);


    Hint: Since left and right boundaries contains inverted commas, we have to insert backslash before.
    Backslash followed by special characters are named Escape Sequences.

    Let's execute our code.
    For that, enable extended logging from Run-time Settings:

    The result of LoadRunner script execution is the following:

    As you can see, we specified correct boundaries for web_reg_save_param LoadRunner function. Value of ID1 has been captured correctly.

    Hint: Use lr_eval_string function to get captured value (value of LoadRunner parameter).
    An example:


  2. What boundaries should be used in web_reg_save_param LoadRunner function to user name (John Smith)?

    Using of web_reg_save_param LoadRunner function looks similar to previous example with a small difference - we have to extract user name from several lines:

    1. User name:
    2. John Smith
    3. bla-bla-bla


    How to process this case? Piece of cake :)

    Left boundary for user name is "User name:" text followed by a new line. In terms of C language, a new line is "\r\n". So, the left boundary is "User name:\r\n". Right boundary is a new line only - "\r\n".

    So, the final code, which can be used for LoadRunner script correlation, is:

    1. web_reg_save_param("pUserName", "LB=User name:\r\n", "RB=\r\n", LAST);


    The result of its execution is:

web_reg_save_param is a kind of "must know" LoadRunner function. The principle is simple - it tries parse server's response and find a text, located between left and right boundaries.

In next articles, I will show different variants how to use web_reg_save_param LoadRunner function for script correlation. So, keep tracking carefully :)



Related articles:


Using Correlation in LoadRunner scripts - visual tutorial

Today, I will explain - what is LoadRunner correlation and how to perform it.
In my humble opinion, correlation is the key concept of LoadRunner. So, strong understanding of correlation is mandatory requirement for any test engineer, if he plans to be LoadRunner professional or even guru :)


Example from a real practice:


I recorded LoadRunner script for a web server, which contained two special fields - timestamp and checksum:

web_submit_data("rms.jsp",
    "Action=http://eprumossd0010:8400/RMS/jsp/rms.jsp",
    "Method=POST",
    "RecContentType=text/html",
    "Referer=http://eprumossd0010:8400/RMS/html/testFramework.html",
    "Snapshot=t4.inf",
    "Mode=HTML",
    ITEMDATA,
    "Name=TIMESTAMP", "Value=1192177661211", ENDITEM,
    "Name=CHECKSUM", "Value=715E19300D670ED77773BBF066DAAAE2866484B8", ENDITEM,
    // others parameters ...
    LAST);

Every time a client web browser connects to web server, server gets current time stamp, calculates checksum and sends them to client. These two fields are used to identify a current session. In other words, the pair of timestamp+checksum is analog of session ID.

The scheme of this interaction is the following:


Where is the problem? Let's replay the recorded LR script.

The problem occurs when I try to execute my recorded script.
Web server checks its current time with a time stamp, sent by client. If client's data is out-of-date or incorrect, then server returns an error:

The parameter "CHECKSUM" is not found or has invalid value.

There is the scheme for this interaction:

Client cannot re-use old (i.e. hard-coded) values for times tamp and checksum. It must request new data.
So, instead of hard-coded values, LR script should process dynamic data, returned from server. This can be done using a correlation:


The definition of correlation is:
Correlation is the capturing of dynamic values passed from the server to the client.


Correlation can be done with 2 ways:
  1. Automatically
  2. Manually
I will describe auto-correlation in the future posts. For now, I can say that this is not ideal solution. Sometimes, it does not work, or works incorrectly.

Manual correlation is a choice of real LoadRunner engineer. It's a kind of "must have" knowledge!
Well, let's start investigating a manual correlation.

The algorithm of manual correlation is the following:
  1. Find a dynamic value to capture.
  2. Find server's response, containing the dynamic value.
  3. Capture the dynamic value.
    Special parameter will be used instead of dynamic value.
  4. Replace every occurrence of dynamic value in script with the parameter.
  5. Check changes.
Now, I will describe each step in details:
  1. Find a dynamic value to capture
    I recommend to record and save two equal VuGen scripts. After that, open menu item "Tools / Compare with Scripts..." and you can compare both recorded scripts in WDiff:
    The differences are highlighted by yellow. This highlighting means that lines (parameters values) change from run to run. So, most probably, these values should be correlated.

    Tips: Sometimes, comparing of two scripts cannot detect dynamic values. Imagine, that you recorded this script:
        "Name=SessionID", "Value=A38E9002A41", ENDITEM,
        "Name=CurrentMonthID", "Value=4", ENDITEM,
        ...
    It's obvious, that SessionID should be correlated. What about CurrentMonthID parameter? Second recorded script can contain "Value=4" too. And it's possible, that your script will work correctly during the April (4th month is April), and will not work from 1st May! So, be careful, my dear reader :)

    Tips:
    Look through the source code of recorded script. Timestamp, CheckSum, SessionID, and different IDs - all of they are potential candidates to be correlated.

    Tips: Check Replay (Execution) log carefully. Errors can be there. The widespread reason of script's errors is an absence of correlations.

    Tips: Execute your script with enabled run-time viewer (menu "Tools / General Options.. / Display"). Any shown errors ("Page not found", "Session timeout", etc) indicate about potential correlations.

  2. Find server's response, containing the dynamic value
    Before script executing, please enable extended logging from "Vuser / Run-Time Settings...":
    Then execute script.
    Open Replay (Execution) log and find server's response, which contains dynamic values of TIMESTAMP and CHECKSUM:
    Great! Now we know, where server sends both dynamic values.
    And we found the step, that returns these values. This is 13th line - Action.c (13). Double click the line, containing timstamp's and checksum's values, 13th line of script will be opened:
    web_submit_data("generateChecksum.jsp",     "Action=http://eprumossd0010:8400/RMS/jsp/generateChecksum.jsp",
        "Method=POST",
        "RecContentType=text/html",
        ...
    This means that server's response for generateChecksum.jsp page contains dynamic values which should be correlated.

  3. Capture the dynamic value
    I will show two ways how to capture a dynamic value:
    • Automatic capturing from Tree-view
    • Manual from Script-view
    These ways are similar enough. Also, they use the same function - web_reg_save_param.

    I start from:
    • Automatic capturing from Tree-view.
      Open Tree view (menu "View / Tree view"):
      Then:
      • click "View recording snapshot only" btn (2);
      • select generateChecksum.jsp page from tree view (3);
      • select "Body" to view body of server's response (4).

      As result, you will see recorded values of CHECKSUM and TIMESTAMP (5).

      Now, select value of first dynamic value (checksum), right-click, and select "Create parameter":
      After that you will see the message box:
      You can create parameter for dynamic value.
      If you want to replace all occurrences of dynamic value ("715E19...") in script, press "Yes" btn.
      To not replace all occurrences, press "No" btn.

      Tips: I recommend to not replace all occurrences of dynamic value. It can lead to incorrect results. It's more preferable to replace occurrences one by one with "Search and Replace" dlg.

      OK, I click "No" btn.

      Return to Script-view ("View / Script View") and see changes. There are new lines, inserted before generateChecksum.jsp page:

      // [WCSPARAM WCSParam_Text1 40 715E19300D670ED77773BBF066DAAAE2866484B8] Parameter {WCSParam_Text1} created by Correlation Studio
      web_reg_save_param
      ("WCSParam_Text1",
          "LB=window.parent.setChecksum(\"",
          "RB=\"",
          "Ord=1",
          "RelFrameId=1",
          "Search=Body",
          "IgnoreRedirections=Yes",
          LAST);

      web_reg_save_param function finds and saves a text string from the next server's response. In other words, it captures a dynamic value.

      In this example, web_reg_save_param function will save the captured value into WCSParam_Text1 parameter. The function finds the left boundary (window.parent.setChecksum(") and after that it finds the right boundary ("). The string, found between left and right boundaries, will be saved to WCSParam_Text1 parameter.
      Ord attribute indicates the ordinal position of captured value. In the example (Ord=1), we capture the value between first left boundary and left one.
      Easy to guess, that "Search=Body" means search in a body of server's response.
      I recommend to study Help on web_reg_save_param function. It's very interesting :)

      Note: the capturing of TIMESTAMP parameter is similar. It generates the following code:

      // [WCSPARAM WCSParam_Text2 13 1192177661211] Parameter {WCSParam_Text2} created by Correlation Studio
      web_reg_save_param("WCSParam_Text2",
          "LB=, ",
          "RB=)",
          "Ord=1",
          "RelFrameId=1",
          "Search=Body",
          "IgnoreRedirections=Yes",
          LAST);

    • Manual capturing from Script-view.
      Actually, this method consists in a manual writing of web_reg_save_param function. It requires strong knowledge on this function and its parameters. There are many attributes of web_reg_save_param function, and I do not want to duplicate HP's Help :)

      Tips: I recommend to rename default parameter (WCSParam_Text1, 2, 3, etc) to something sensible. For example, in my example - I would prefer prmCheckSum and prmTimeStamp to WCSParam_Text1 and WCSParam_Text2.

  4. Replace every occurrence of dynamic value in script with the parameter
    This is not difficult step.
    Open "Search and Replace" dlg ("Edit / Replace..."). And replace one-by-one hard-coded values with a parameter.

    Why it is important?
    Imagine, that you have the following code:

    web_submit_data("somepage",
        ...
        "Name=OrderNumber", "Value=125", ENDITEM,
        "Name=UserID", "Value=125",

    If you create parameter for UserID, and perform replacing of all occurrences of its value ("125"), then it will produce the code:

    web_submit_data("somepage",
        ...
        "Name=OrderNumber", "Value={WCSParam_Text1}", ENDITEM,
        "Name=UserID", "Value={WCSParam_Text1}",

    It may be wrong! OrderNumber can be static value and be equal to 125, while UserID may change.

    Now, I assume that you replace all needed occurrences of hard-coded values. We have to perform last step:

  5. Check changes
    After above manipulations, our script will look like:

    web_submit_data("rms.jsp",
        "Action=http://eprumossd0010:8400/RMS/jsp/rms.jsp",
        "Method=POST",
        "RecContentType=text/html",
        "Referer=http://eprumossd0010:8400/RMS/html/testFramework.html",
        "Snapshot=t4.inf",
        "Mode=HTML",
        ITEMDATA,
        "Name=TIMESTAMP", "Value={WCSParam_Text2}", ENDITEM,
        "Name=CHECKSUM", "Value={WCSParam_Text1}", ENDITEM,
        // others parameters ...
        LAST);

    The statement "{WCSParam_Text1}" means "get value of WCSParam_Text1 parameter".
    So, current algorithm is:
    • when server returns different values of CheckSum and TimeStamp
    • then web_submit_data captures and places them into WCSParam_Text1 and WCSParam_Text2 parameters
    • after that we use {WCSParam_Text1} and {WCSParam_Text2} get current values of parameters and use them in scripts

    Let's run our modified script and see results of capturing from server's response:
    These are values, which are sent to a server by a client:

    You can see that dynamic values are saved to parameters and their values are substituted instead of parameters in scripts. Great! We have just correlated our script and it is working now!

    Tips: To get/debug a captured value of parameter, use the following statements:
    lr_output_message("Value of WCSParam_Text1: %s", lr_eval_string("{WCSParam_Text1}"));
    lr_output_message("Value of WCSParam_Text2: %s", lr_eval_string("{WCSParam_Text2}"));

    Execute script again, he result is:


Epilogue:
I hope, I provided simple and understandable explanation of LoadRunner correlation.
Please, share your comments and thoughts, dear readers.

Do you have ideas for further topics - welcome :)

Dmitry Motevich,
QA / Automated testing specialist




Related articles: