This is a migrated thread and some comments may be shown as answers.

Automating ASP.NET DataGrids and Repeaters that Dynamically Update

5 Answers 129 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Jason
Top achievements
Rank 2
Jason asked on 28 Feb 2011, 10:35 PM
I'm seeking some community assistance for what is probably my most vexing testing problem at the moment.  Hopefully this post finds someone out there who has dealt with a similar challenge in a more elegant/scalable manner than I have, or at very least some Telerik support staff input would be greatly helpful.

I aim to script a complete trip through a life insurance application wizard where one of many insurance carriers can be selected.  The carrier selection is made from a DataGrid ASP.NET control which orders the carriers in ascending order based on quote price (see the first screenshot).

Furthermore, once the user is within a particular carrier's app wizard, they will eventually reach a forms selection page, where the minimum required forms for the application packet are automatically selected, along with any forms that become required based on answers to preceding questions about the applicant in the previous wizard pages.  Furthermore, the user can select additional forms to include in the packet.  All forms work is done within a Repeater ASP.NET control (see second screenshot).

The rub is this: due to frequent rate changes by our carriers, and necessary forms updates performed periodically for each carrier, these pages are very dynamic in nature.  For instance, Transamerica will not always hold the same position in the DataGrid from one week to the next, and a forms update for a particular carrier may change where a particular form shows up in the Repeater.  So the challenge lies in writing a script that, for example, will ALWAYS select Transamerica as the carrier, or will ALWAYS select a particular form in the Repeater, regardless of how those items move around on the page due to necessary updates.

This is made all the more difficult due to the fact that the names of the button/checkbox controls are not specific to the carriers or the forms.  The "Add Lead" button that corresponds to Transamerica in the DataGrid will have an id of something like "StandardPlusDG_ctl06_SelectImage", a name that is specific to the position on the grid and could hence be used to select an entirely different carrier when the system is updated with the latest pricing schemes for our carriers.  Similarly, a "Buyer's Guide" form's checkbox will have an id of something like "FormsRepeater_ctl01_FormCB", which again could be used to refer to an entirely different form after a system update.

One solution I've come up with and have had moderate success with has involved creating a sort of "decision matrix" for both the carrier selection page and the forms page, where, given a data-driven context, the buttons/checkboxes that need to be selected for each individual iteration are recorded into script and nested within if/else statements.  See the third screenshot - note that buttons are set to be clicked only given certain conditions, so that the location of the "Transamerica" button is known for each iteration of the test. 

Note the flaw here - my script is only as good as the latest system update!  It gives me the power to have a fully automated process for testing our application wizard within a given week, but in order to keep this up I have to run the script every Monday and see how many test cases fail so I can know how many "fixes" I need to make so I can have a good automation script for another week.  I have made this easier on myself by building if-else page verification steps into the script (essentially, the script knows immediately if it's not in the Transamerica application wizard, and the iteration fails immediately at that point and the browser closes, opens, and runs the next iteration).  However, depending on the extent of the latest system update this can take 1-4 hours at the beginning of each week.  And this is just for one carrier - my goal is to have an automation script for each carrier!  So my need for a more scalable methodology is clear.

Has anybody out there faced a similar challenge?  Any help would be greatly appreciated!

5 Answers, 1 is accepted

Sort by
0
Stoich
Telerik team
answered on 01 Mar 2011, 03:40 PM
Hi Jason,
    this doesn't sound too hard to implement but it will require some coding. If you provide me with the code for this part of your application I could write it for you. Right now I can only offer some general guidelines.
Create a Script Step. From there:

Since the name of the carrier is the only reliable thing to go by, we want to base our find Logic on that e.g:
Element carrier = Find.ByExpression("textcontent=Transamerica");
Now you have the named element (screenshot 1). From here we want to get the corresponding "Add Lead" button. Take a look at the the named element in the Dom Explorer - the only thing connecting it to the "Add Lead" is that they they're both children of the same table row. So first we need to get to this table row:
Element parentRow = (Element) carrier.GetParent().GetParent();
This might statement might be different depending on your particular application. The DOM Explorer will help you figure it out.
Once you're "in the row", we need to move down into the table cell element that contains the button(screenshot 1):
Element[] children = (Element[])parentRow.GetChildren();
          Element tableCell;
 
          foreach (Element e in children)
          {
              if (e.InnerText.Contains("Add Lead")) { tableCell = e; break; }
          }
This is the cell that has the button. Let's get its only child (the Button):
if ( tCell != null) {
             HtmlAnchor button = (HtmlAnchor) tCell.GetChildren()[0];
             button.Click();
  }
We're done, we've clicked the correct button. Obviously, I'm assuming that the button is an HTML anchor which it may or may not be.

I hope this helps, let me know how it goes!

Best wishes,
Stoich
the Telerik team
Registration for Q1 2011 What’s New Webinar Week is now open. Mark your calendar for the week starting March 21st and book your seat for a walk through all the exciting stuff we ship with the new release!
0
Jason
Top achievements
Rank 2
answered on 01 Mar 2011, 08:54 PM
Stoich,

Thank you - this makes sense to me and I think we're onto something.  However, I'm not successful in getting a click on the Add Lead button just yet.  Just for reference, here's what I have (the major difference between my code and yours is that I'm creating an HtmlImage instead of an HtmlButton, because the Add Lead button is actually an image).

//Gets the element containing the targeted carrier
Element transCarrier = Find.ByExpression("textcontent=Transamerica");
 
//Gets the entire table row corresponding to the carrier
Element transRow = (Element)transCarrier.GetParent().GetParent();
 
//Isolating the table cell that contains the Add Lead button
Element[] transChildren = (Element[])transRow.GetChildren();
Element tableCell = null;
 
foreach (Element e in transChildren)
{
    if (e.InnerMarkup.Contains("type=image"))
    {
        tableCell = e;
        break;
    }
}
 
//Gets the button from the child element and clicks it
if (tableCell != null)
{
    HtmlImage transBtn = (HtmlImage)tableCell.GetChildren()[0];
    transBtn.Click();
}

When you ask for code, do you mean the HTML for the page or the code-behind?  Because I can readily provide you with HTML (it's possible I might have to redact a sensitive item or two, but you could easily see the fundamentals), but the code-behind would be a non-starter.  As long as seeing the HTML would suffice, I'd be happy to receive further help.  Thanks again!
0
Stoich
Telerik team
answered on 02 Mar 2011, 03:46 PM
Hello Jason,
  yes, only I need the front-end HTML page. Actually, I only need the actual Table with the Carries and the buttons but the whole page would be better. Anything that doesn't run in a browser (i.e. your actual application) is not taken into account by WebUI Test Studio and I don't need it.

If you don't want to put it one this public forum (if you consider it sensitive) then open a new support ticket (that's private) and attach it there. If you choose to do that please close this forum thread (i..e mark this as an answer) once you open the support ticket.

Hope to hear from you soon!

Kind regards,
Stoich
the Telerik team
Registration for Q1 2011 What’s New Webinar Week is now open. Mark your calendar for the week starting March 21st and book your seat for a walk through all the exciting stuff we ship with the new release!
0
Jason
Top achievements
Rank 2
answered on 02 Mar 2011, 07:17 PM
Stoich,

I will go ahead and get you the HTML source for the page in a support ticket.  However, once we come to a solution, I think it'd be nice if I came back to this thread and at least report how the issue was handled so it could have the potential to help others in a similar rough spot.
0
Accepted
Jason
Top achievements
Rank 2
answered on 08 Mar 2011, 10:19 PM
While I solved this problem (at least for the application I'm testing) with great help from Stoich and Cody with Telerik Support, I wanted to post snippets of the coded sets I've implemented so the principles behind it all can be edifying to other testers out there.

Please refer to the screenshots attached to the first post in the thread for illustrations of the pages these coded steps are running against.

Here is how I'm able to isolate an Add Lead or Next Step button for a particular carrier, regardless of its position in the DataGrid.

//Isolates an instance of a Transamerica HTML Anchor in the data grid.
HtmlAnchor carrierTextNS = ActiveBrowser.Find.ByExpression<HtmlAnchor>("TextContent=~Transamerica","OuterMarkup=~DataGridItem");
 
//Scrolls the screen to the isolated area
carrierTextNS.ScrollToVisible();
 
//Tests to see that an object has been captured by the above
Assert.IsNotNull(carrierTextNS);
 
//Isolates the table row that contains the carrierText
HtmlTableRow carrierRowNS = carrierTextNS.Parent<HtmlTableRow>().Parent<HtmlTableRow>();
 
//Isolates the Next Step button within the table row and clicks it
HtmlInputImage nextStep = carrierRowNS.Cells[5].ChildNodes[0].As<HtmlInputImage>();
nextStep.Click();

Here is an example of how I'm able to verify required forms are selected in the Repeater, as well as select desired additional forms.
//Isolates the desired Form Number
HtmlSpan appInstrText = ActiveBrowser.Find.ByExpression<HtmlSpan>("TextContent=App Instructions");
 
//Isolates the table row that contains the form number
HtmlTableRow appInstrRow = appInstrText.Parent<HtmlTableRow>();
 
//Isolates the check box within the row
HtmlInputCheckBox appInstrcbox = appInstrRow.Cells[0].Find.ByExpression<HtmlInputCheckBox>("tagname=input");
 
//Tests to see that the check box is checked
Assert.IsTrue(appInstrcbox.Checked);

//Isolates the desired form number
HtmlSpan persFinText = ActiveBrowser.Find.ByExpression<HtmlSpan>("TextContent=APE561008TAK");
 
//Isolates the table row that contains the form number
HtmlTableRow persFinRow = persFinText.Parent<HtmlTableRow>();
 
//Isolates the check box within the table row
HtmlInputCheckBox persFincbox = persFinRow.Cells[0].Find.ByExpression<HtmlInputCheckBox>("tagname=input");
 
//Tests to see that the checkbox is not already checked
Assert.IsFalse(persFincbox.Checked);
 
//Checks the check box
persFincbox.Check(true, true);

Hopefully you'll find these example helpful if you're in a similar situation.
Tags
General Discussions
Asked by
Jason
Top achievements
Rank 2
Answers by
Stoich
Telerik team
Jason
Top achievements
Rank 2
Share this question
or