Tuesday, June 17, 2008

Selecting a random button in a grid with VS2008

I am finally getting into writing virtual users with the VS2008 VSTE tools and the learning curve is pretty steep but the amount of control that I get is pretty darn cool so I think the pain points will be worth it.

Something that has always been a pain with LR in the past is randomly selecting some parsed HTML to randomize the next step in a vuser script. Sure, you can use web_reg_save_param with "ord=all" ala:

web_reg_save_param ("someParam", "LB= value=\"", "RB=\"", "Ord=All", LAST);

and pull it all into an array parameter and then iterate over the entries in the parameter by utilizing sprintf() ala:




   1:  web_reg_save_param ("someParam", "LB= value=\"", "RB=\"", "Ord=All", LAST);

   2:   

   3:  for (i = 1; i <= atoi(lr_eval_string("{someParam_count}")); i++) {

   4:    sprintf(someParamValue, "{someParam_%d}", i);

   5:    lr_output_message("%s", lr_eval_string(someParamValue));

   6:  }




That way of accessing the parameter array info always seemed like a PITA to me (maybe I'm in the minority with this thought?). Want to substring the output even further? More of a PITA since C doesn't have any quick and friendly string handling functions (substr(), left(), ltrim(), etc).


But, you have to be able to do it to get the job done.

Today I needed to basically select a random customer view button from a grid that was returned from this WebTestRequest hit:




   1:  WebTestRequest request3 = new WebTestRequest("http://xxx.yyy.zzz.iii/someWebPage.aspx");

   2:  request3.Method = "POST";

   3:  FormPostHttpBody request3Body = new FormPostHttpBody();

   4:  request3Body.FormPostParameters.Add("__EVENTTARGET", this.Context["$HIDDEN1.__EVENTTARGET"].ToString());

   5:  request3Body.FormPostParameters.Add("__EVENTARGUMENT", this.Context["$HIDDEN1.__EVENTARGUMENT"].ToString());

   6:  request3Body.FormPostParameters.Add("__LASTFOCUS", this.Context["$HIDDEN1.__LASTFOCUS"].ToString());

   7:  request3Body.FormPostParameters.Add("__VIEWSTATE", this.Context["$HIDDEN1.__VIEWSTATE"].ToString());

   8:  request3Body.FormPostParameters.Add("__VIEWSTATEENCRYPTED", this.Context["$HIDDEN1.__VIEWSTATEENCRYPTED"].ToString());

   9:  request3Body.FormPostParameters.Add("__EVENTVALIDATION", this.Context["$HIDDEN1.__EVENTVALIDATION"].ToString());

  10:  request3.Body = request3Body;

  11:  ExtractHiddenFields extractionRule2 = new ExtractHiddenFields();

  12:  extractionRule2.Required = true;

  13:  extractionRule2.HtmlDecode = true;

  14:  extractionRule2.ContextParameterName = "1";

  15:  request3.ExtractValues += new EventHandler<ExtractionEventArgs>(selectRandomButton);

  16:  request3.ExtractValues += new EventHandler<ExtractionEventArgs>(extractionRule2.Extract);

  17:  yield return request3;

  18:  request3 = null;



The WebTestRequest has an event for allowing coders to write their own code for extracting data from the HTML output. I wrote the code below is referenced in the above code at line # 15:



   1:  void selectRandomButton(object sender, ExtractionEventArgs e) {

   2:    if (e.Response.HtmlDocument != null) {

   3:      List<String> buttonNameList = new List<String>();

   4:      foreach (HtmlTag tag in e.Response.HtmlDocument.GetFilteredHtmlTags(new string[] { "input" })) {

   5:        if (tag.GetAttributeValueAsString("type") == "submit") {

   6:          buttonNameList.Add(tag.GetAttributeValueAsString("name"));

   7:        };

   8:      };

   9:      if (buttonNameList.Count > 0) {

  10:        Random randomizer = new Random();

  11:        e.WebTest.Context.Add("RANDOMCUSTOMERBUTTON",

  12:                               buttonNameList[(int)randomizer.Next(buttonNameList.Count) - 1]);

  13:        e.Success = true;

  14:      } else {

  15:        e.Success = false;

  16:        e.Message = "No entries were found for customer view buttons.";

  17:      };

  18:    } else {

  19:      e.Success = false;

  20:      e.Message = "No HTML to work against!";

  21:    };

  22:  }



Take a gander at the loop at line #4. In that loop I'm inspected a group of elements searching for the data that I want. No need to specify a dozen calls of web_reg_save_param only to reference said params via lr_eval_string and strcmp(). That's right, nice simple easy to read code! It's all there. I can spin, fold and mutilate the information all I want! That and I have access to .NET Containers. I don't have to write my own double linked list for storing data for declaring the square array in advanced (I did a lot of square arrays because I am a slacker like that). How sweet is that?!

While it might seem more complex at first, I believe that the extra control that I get over the selection of data is fantastic. I can think of several times in the past that I've had to write more complicated code than I have wanted to for the slicing and dicing of HTML and this method would have made things so much easier for me.

And I found a cool code formatting site today located at http://www.manoli.net/csharpformat/format.aspx. It took a little work getting the CSS stuff taken care of (after all, I'm not a GUI whiz) but it was worth it for sure.

No comments: