in

ArtOfTest, Inc. Community Forums

Discuss and ask questions about ArtOfTest's products.

Testing ASP.NET controls set for autopostback?

Last post 08-02-2007 2:13 PM by strailey. 13 replies.
Page 1 of 1 (14 items)
Sort Posts: Previous Next
  • 07-26-2007 2:56 PM

    Testing ASP.NET controls set for autopostback?

    What is the proper WebAii method for testing ASP.NET controls that use auto postback? I already know about the gotcha regarding manually invoking the OnChange event after using the SelectDropDown() method in a WebAii test fixture when manipulating a dropdown list set for auto postback. In a previous Support Request email reply that you sent me before the forums were created, you indicated "The WaitForElement will take care of the RefreshDomTree and WaitUntilReady for you". But I find in practice, that I must do all sorts of tricks with Sleep(), RefreshDomTree(), WaitUnitlReady(), and WaitForElement() after the calling the InvokeEvent() before I can successfully check the results of a SelectedIndexChanged or OnClick event handler for an auto postback control. For instance look at the following WebAii Test (for the record, I’m using NUnit-based testing) code snippet, which clicks on a Search Image Button that has an OnClick event handler that fires off a DB search and then writes the search status to an ASP.NET label: Actions.Click(Find.ById("imgBtnSearch"));Actions.InvokeEvent(Find.ById("imgBtnSearch"), ScriptEventType.OnClick);ActiveBrowser.RefreshDomTree();Thread.Sleep(3000);Actions.WaitForElement(new FindParam("id=lblSearchResults"), 10000);Assert.AreEqual("Report Found", Find.ById("lblSearchResults").TextContent);In theory, the WaitForElement() call on the second to last line should be all that I need, I shouldn't have to use RefreshDomTree() or the Sleep(). But in practice without those extra steps, lblSearchResults is found by the WaitForElement() but often contains the initial "" value when tested on the next line, not "Report Found" (seems like either the DOM is completely refreshed or the postback has not yet completed). Once the postback completes it should either have "Report Found" or "Report Not Found", not "".  The lone WaitForElement() method will usually work if I'm single stepping through the test inside the debugger (I'm using TestDriven.NET, for the debug capability). And sometimes it may work if I just run the individual test (again via TD.NET), but it will almost certainly fail when I run all the tests in the fixture back-to-back.  I keep running into situations where it seems like the browser's DOM has not been completely refreshed even after using a WaitForElement.  Is the RefreshDomTree() a blocking operation? Or does it run in a separate thread?  After invoking an action that causes a postback, does WebAii block until the postback completes?  If not, is there some other method that can be called to cause WebAii to block (many of our event handlers invoke LDAP searches or DB operations that may take a little time to complete)?  I had a nightmare of a time testing ASP ValidationSummaries, I would get all kinds of strange inconsistent results (even malformed HTML) if I only did a WaitForElement().  Once I started experimenting with Sleep(), RefreshDomTree(), WaitUntilReady(), WaitForElement() combinations such as the following I got more consistent results.[Set one of the form's fields with a malformed date string]...Actions.Click(Find.ById("btnSubmit"));Thread.Sleep(2000);ActiveBrowser.WaitUntilReady();ActiveBrowser.RefreshDomTree();Thread.Sleep(2000);Actions.WaitForElement(new FindParam("id=ValidationSummary1"), 8000);Element validationsummary1 = ActiveBrowser.Find.ById("ValidationSummary1");Assert.IsTrue(validationsummary1.Children[0].InnerText.Contains("Date Format (mm/dd/yyyy)"));

    Am I missing something simple?  Have others experienced these timing issues?  I could certainly understand these kinds of timing issues if we were dealing with AJAX, but we're not.  After using WebAii for a few months I really like the product, except for having to play all these games following an auto postback operation.  This nuisance is further compounded by the fact that the test may run properly in the debugger or standalone, but then fail when run as part of the entire test suite (more evidence that it's some sort of timing issue).  Then I have to go back and start playing with different combinations to make it work again inside the suite.  While I'll be happy answer questions and provide small snippets, providing any of our apps or test fixtures for further examination unfortunately will not be possible (not to mention that they would not run without numerous back-end services such as DBs and AD).  Thanks for any assistance!

  • 07-26-2007 2:59 PM In reply to

    Re: Testing ASP.NET controls set for autopostback?

    Wow, it looked beautiful in the preview, I don't know what happened to all the carriage returns?  Sorry this is so hard to read.

  • 07-26-2007 5:54 PM In reply to

    Re: Testing ASP.NET controls set for autopostback?

    Hi Strailey -

    I think I know what is going on with your tests but before I explain it I want to stress that if you are experiencing difficulties like what you are seeing and it is obvious that something is not working as it should, please contact us and don't waste your time trying to hack around these issues. Our goal for WebAii is to be a rich and easy to use framework and if that is not what you are getting, either a) there is a bug, b) you are missing something or not properly using an API or c) WebAii is not suited for your scenarios. We can definietly help you figure out which one of the above is your case.

    From the code you sent us above, the issue you are fasting is definietly due to timing and the reason why you are unable to get the test to work as expected is due to how you are calling the WaitForElement() function.

    WaitForElement() does do a DOM refresh periodically until a certain condition is met. NOTE: You need to specify what that condition is.

    Let's take for example your call:

    Actions.WaitForElement(new FindParam("id=lblSearchResults"), 10000);

    This is telling the framework to wait until there is an element with id=lblSearchResults is found in the DOM. It does not tell it to wait for anything else like its content of its attributes or anything. Given that this label already exists on your page even before you invoke the click, the WaitForElement will return immediately.

    If you want to properly wait until that element has the textcontent "Report found" then you can do

    Actions.WaitForElement(new FindParam(FindType.Content, "p:Report", "id=lblSearchResults"), 10000);

    The FindParam allows you to describe how an element should be found. The WaitForElement will use that FindParam and apply it periodically between DOM refreshes until the FindParam does find an element or else it will timeout. The FindParam above tells the framework to search for an element using its TextContent and to wait until it finds an element with partial (p:) text content that has "Report" in it and has an attribute (id) = (lblSearchResults)

    Basically wait until the element lblSearchResults has a partial text content equals report. Which is when the results are back.

    I think your second issue is the same, you need to be more explicit to define what to wait for, not just the element.

    I hope this helps a bit. We are working on actually abstracting out our WaitForElement to let customers avoid the need to define the FindParam and simply us doing it for them in the background. Our RC0 should be out soon and should address some of these issues.

    Let us know if this solves your issues...

     

     

    ArtOfTest, Inc.
  • 07-27-2007 5:45 AM In reply to

    Re: Testing ASP.NET controls set for autopostback?

    Thanks, that method will definitely help in many situations.

    What is the best method for testing for the absence of an element following an autopostback?  So in the following example, test to make sure a label is displayed, click on an autopostback button, its OnClick event handler sets the ASP label's visibility to false, now verify that the label is no longer displayed.  Again, the RefreshDomTree and Sleep were added for the aforementioned timing issues.  The WaitForElement call on another page object was added due to the mistaken impression that it forced WebAii to wait until the DOM refresh completed, otherwise the Assert.IsNull often fails.

    Assert.IsNotNull(Find.ById("label1"));

    Actions.Click(Find.ById("btn1"));

    ActiveBrowser.RefreshDomTree();

    Thread.Sleep(3000);

    Actions.WaitForElement(new FindParam("id=txt1"), 10000);

    Assert.IsNull(Find.ById("label1"));

    Thanks!

  • 07-27-2007 9:52 AM In reply to

    Re: Testing ASP.NET controls set for autopostback?

    OK, here's another one of my autopostback problems. 

    Actions.SelectDropDown(Find.ById("dd1"), 4);

    Actions.InvokeEvent(Find.ById("dd1", ScriptEventType.OnChange);

    Actions.WaitForElement(new FindParam("id=txt1"), 10000);

    Actions.SetText(Find.ById("txt1"), "Test");

    Many selections of dd1 add or remove fields that could be checked for via WaitForElements, however option 4 does not make any visible changes to the form.  In my experience, for some period of time after any operation that causes an autopostback, WebAii's DOM is in a completely unstable state of flux.  Obviously, this is not unexpected since the postback may make numerous changes to the DOM.  The problem that I keep butting up against is that there seems to be no reliable way of knowing when the postback is complete and the DOM refreshed.  During this flux period all bets are off.  While single stepping the above example through the debugger, I've seen the SetText command happily write its text to the next text field on the form (no error messages).  When run as an individual standalone test one can see that WebAii writes the value to the text field and then it is promptly blanked out (maybe when the DOM refresh actually completes?).  Either of these conditions which result in the field being blank cause the form submission to fail (due to a required field validator), and subsequently causes the test case to fail.  Do you have any suggestions on how to handle the above situation?  Thanks again.

  • 07-27-2007 1:18 PM In reply to

    • sircody
    • Top 10 Contributor
    • Joined on 05-23-2007
    • Seattle, Wa
    • Posts 223

    Re: Testing ASP.NET controls set for autopostback?

    I think I can help on the visibility part of your problem. I had to deal with a similar issue on one of my companies website. In my case I had to synchronize with the website as my automation moved from one search results page to the next. In my case I have this sequence of events happening under the covers:

    1. User clicks the Navigate Next button
    2. Website responds by hiding the search results DIV section
    3. At the same time Website responds by displaying a previously invisible GIF of a spinning icon and the text "Please wait..."
    4. The web page goes quiet (i.e. goes to Done state) and WebAii sees that the web page is ready
    5. After the web server has gathered the results for the next page of search results it reverses the two
    6. The spinning GIF and text are set to invisible
    7. The results are inserted into the search results DIV section
    8. The search results DIV section is changed to visible

    I was able to create a Find parameter that waits for the search results DIV to be changed from invisible to visible. The code that accomplishes this is:

        // Click the Navigate Next Page button
        Actions.Click(Find.ById("ctl00_ctl00_MainContent_mc_sab1_sb_pgr_pgr_imgNext"));

        FindParam searchresultsdiv = new FindParam();
        searchresultsdiv.PartialAttributes.Add(new iAttribute("id", "upSearchResults"));
        searchresultsdiv.PartialAttributes.Add(new iAttribute("style", "visibility: visible;"));
        searchresultsdiv.Type = FindType.AttributesOnly;
        Actions.WaitForElement(searchresultsdiv, 30000);

        ActiveBrowser.WaitUntilReady();

    The above code works very reliably for me as I wait for the next page of search results to be returned by the web server, despite the fact that the browser is sitting in the "Done" state for a significant amount of time (i.e. a few seconds). Note that Actions.Click will not return until step 4 above is complete. Waiting on the style attribute using a partial match is the key to making it work reliably detecting when the search results have come back. I've already posted on the wish list to request an easier to use WaitForElement type of function that will wait on any particular style setting.

    Hope that is of value to you. 

    Cody

    ---- WebAii Expert User ----
  • 07-27-2007 1:31 PM In reply to

    • sircody
    • Top 10 Contributor
    • Joined on 05-23-2007
    • Seattle, Wa
    • Posts 223

    Re: Testing ASP.NET controls set for autopostback?

    strailey:

    OK, here's another one of my autopostback problems. 

    Actions.SelectDropDown(Find.ById("dd1"), 4);

    Actions.InvokeEvent(Find.ById("dd1", ScriptEventType.OnChange);

    Actions.WaitForElement(new FindParam("id=txt1"), 10000);

    Actions.SetText(Find.ById("txt1"), "Test");

     

    I am not certain but I suspect that InvokeEvent returns immediately after the event has been handled, but not necessarily after the browser is done updating the window (i.e. the event has handled but the browser is still busy). Have you tried replacing your WaitForElement with ActiveBrowser.WaitUntilReady()? I have a feeling that might solve this instance. Please give that a try and let me know what happens.

    Cody

    ---- WebAii Expert User ----
  • 07-27-2007 3:19 PM In reply to

    Re: Testing ASP.NET controls set for autopostback?

    Re: Element Visibility - Cody's code above should do the trick for you.

    Re: SelectDropDown Postback - I've actually tried to reproduce this issue several time. InvokeEvent does actually wait until the browser is ready. When a postback occurs, the browser will not signal ready until it is back from the postback so we should be waiting for that postbacks.  Actually postbacks are easy to wait for, Ajax calls is what is more tricky that is why I'm a bit suspicious about what is really going on. So I don't think you need a WaitForElement in this case and I don't think you even need the WaitUntilReady() but you can try to see if that fixes your issue (if it does, then this is a bug we need to fix). There might be something else going on with the page.

    Would you be able to send us just the HTML page with your test code? You can contact us here contact@artoftest.com

     

    ArtOfTest, Inc.
  • 08-02-2007 10:42 AM In reply to

    Re: Testing ASP.NET controls set for autopostback?

    Sir Cody, thanks, I haven't yet had a chance to try out your suggestions.  I will report back on my findings.  I've been getting such strange and inconsistent results that I decided to rebuild my development system from bare metal just to remove any possibility of contaimination from all the various tools that I installed and removed during my testing tool evaluation and selection process.  Already with the new system, I'm getting new inconsistent results.  Here's the specs on the new environment:

    Microsoft Windows XP Professional SP2

    Microsoft Visual Studio 2005 Professional with SP1 (Web Application Projects using IIS, not Cassini)

    Microsoft SQL Server 2005 Express

    TestDriven.NET 2.8 Beta Enterprise (using the NUnit 2.4 installation contained in this product)

    WebAii RC0

    nDumbster 0.0.2

    Microsoft IE Developer Toolbar

    Microsoft Sandcastle June 2007

    Microsoft AJAX Extentions 1.0 (not used, yet)

    All testing done under IE6, Firefox is not an option.

    AnkhSVN 1.0.1.2736 Final

    TortoiseSVN 1.4.3

    Now, sometimes when I run an individual test it passes.  Other times, I get the following Error:

    ------ Test started: Assembly: reporting.dll ------

    TestCase 'WATester.WebAiiNUnitTest1.Report_RequestRequestReportWithRefresh'
    failed: ArtOfTest.WebAii.Exceptions.ExecuteCommandException : ExecuteCommand failed!
    InError set by the client. Client Error:
    System.IndexOutOfRangeException: Current frame index '1' is out of range of current frames count '1'
       at ArtOfTest.InternetExplorer.IECommandProcessor.SetTargetDocument(BrowserCommand& request, IHTMLDocument2 document)
       at ArtOfTest.InternetExplorer.IECommandProcessor.ProcessCommand(WebBrowserClass ieInstance, BrowserCommand request, IHTMLDocument2 document)
    BrowserCommand (Type:'Information',Info:'DocumentMarkup',Action:'NotSet',Target:'null',Data:'',ClientId:'Client_3db93978-78df-4ba1-a206-902f312d41c3',HasFrames:'False',FramesInfo:'',TargetFrameIndex:'1',InError:'True',Response:'System.IndexOutOfRangeException: Current frame index '1' is out of range of current frames count '1'
       at ArtOfTest.InternetExplorer.IECommandProcessor.SetTargetDocument(BrowserCommand& request, IHTMLDocument2 document)
       at ArtOfTest.InternetExplorer.IECommandProcessor.ProcessCommand(WebBrowserClass ieInstance, BrowserCommand request, IHTMLDocument2 document)')
    InnerException: none.
     at ArtOfTest.WebAii.Core.Browser.ExecuteCommandInternal(BrowserCommand request)
     at ArtOfTest.WebAii.Core.Browser.ExecuteCommand(BrowserCommand request, Boolean performDomRefresh, Boolean waitUntilReady)
     at ArtOfTest.WebAii.Core.Browser.RefreshDomTree()
     at ArtOfTest.WebAii.Core.FramesCollection.RefreshAllDomTrees()
     at ArtOfTest.WebAii.Core.Browser.UpdateFrames(BrowserCommand command)
     at ArtOfTest.WebAii.Core.Browser.RefreshDomTree()
     at ArtOfTest.WebAii.Core.Browser.ExecuteCommand(BrowserCommand request, Boolean performDomRefresh, Boolean waitUntilReady)
     at ArtOfTest.WebAii.Core.Browser.ExecuteCommand(BrowserCommand request)
     at ArtOfTest.WebAii.Core.Actions.InvokeEvent(Element targetElement, ScriptEventType eventType)
     C:\Inetpub\wwwroot\reporting\reporting\WebAiiNUnitTest1.cs(679,0): at WATester.WebAiiNUnitTest1.Report_RequestRequestReportWithRefresh()

    This test rebuilds the DB, writes some changes to the Web.config (appSetting keys to enable emails, also changes the smtp host to the local system), starts the nDumbster mock SMTP Server, calls LaunchNewBrowser(), navigates to the page, performs a few SetTexts on some fields, checks an autopostback checkbox, then blows up.  Here's relevant lines:

    Actions.Check(Find.ById("chkSame"), true); //Line 678

    Actions.InvokeEvent(Find.ById("chkSame"), ScriptEventType.OnClick); //Line 679

    Anybody have any thoughts as to why I am now getting this error intermittently?

     

  • 08-02-2007 12:16 PM In reply to

    Re: Testing ASP.NET controls set for autopostback?

    Thanks. Just to note, we've been trying to track this intemitt issue for some time now and we have  fix for it. This should be fixed in RC1 scheduled to release by the end of next week.

    ArtOfTest, Inc.
  • 08-02-2007 12:32 PM In reply to

    • sircody
    • Top 10 Contributor
    • Joined on 05-23-2007
    • Seattle, Wa
    • Posts 223

    Re: Testing ASP.NET controls set for autopostback?

    strailey:

    System.IndexOutOfRangeException: Current frame index '1' is out of range of current frames count '1'
       at ArtOfTest.InternetExplorer.IECommandProcessor.SetTargetDocument(BrowserCommand& request, IHTMLDocument2 document)
       at ArtOfTest.InternetExplorer.IECommandProcessor.ProcessCommand(WebBrowserClass ieInstance, BrowserCommand request, IHTMLDocument2 document)
    BrowserCommand (Type:'Information',Info:'DocumentMarkup',Action:'NotSet',Target:'null',Data:'',ClientId:'Client_3db93978-78df-4ba1-a206-902f312d41c3',HasFrames:'False',FramesInfo:'',TargetFrameIndex:'1',InError:'True',Response:'System.IndexOutOfRangeException: Current frame index '1' is out of range of current frames count '1'

    I find this line most interesting! Does the active page have frames? Are you possibly acting on a checkbox in frame 1 which causes an update in frame 0 via postback?

    What is the value of ActiveBrowser.Frames.Count; just before the InvokeEvent call? What is the value of ActiveBrowser.Frames.Count and ActiveBrowser.FrameInfo.Index; after the failure (you can put this in the [TestCleanup()] method in order to capture the values)? I'd be interested in more diagnostic information captures in the [TestCleanup()] method. For example:

            [TestCleanup()]
            public void MyTestCleanup()
            {
                Log.WriteLine(ActiveBrowser.Frames.Count.ToString());
                Log.WriteLine(ActiveBrowser.FrameInfo.Index);
     

    I can also confirm that I reported a similar intermittent "ExecuteCommand failed!" error and was able to give the WebAii developers a reliable repro method. The last I knew they were working on it. Hopefully your problem is the same as the one I reported such that the next RC release will have it fixed for us both.

    Cody

    ---- WebAii Expert User ----
  • 08-02-2007 1:12 PM In reply to

    Re: Testing ASP.NET controls set for autopostback?

    No, the page does not use any frames.  I assumed webaii might using frames somehow to perform its magic.

    As for your requested diagnostic info.  The Frames.Count = 1and FrameInfo = null one line before the crash.  As usual for me, if I single step through the test, it doesn't crash.  If I run the test individually, it crashes and the cleanup code still reports Frames.Count = 1and FrameInfo = null.

  • 08-02-2007 1:26 PM In reply to

    • sircody
    • Top 10 Contributor
    • Joined on 05-23-2007
    • Seattle, Wa
    • Posts 223

    Re: Testing ASP.NET controls set for autopostback?

    I see. Thanks for the feedback! In that case (no frames and the diagnostic info you report) you are most definitely running into a WebAii framework bug. I see the admin also responded to you today indicating they have a fix for this which will be included in WebAii RC1 scheduled for release at the end of next week. Can you hold on until then?

    Cody

    ---- WebAii Expert User ----
  • 08-02-2007 2:13 PM In reply to

    Re: Testing ASP.NET controls set for autopostback?

    Do I have a choice?  I'm in the middle of trying to stabilize the 18K+ lines of WebAii tests that I've already written (all run fine when single-stepped) so that they work when single-stepped, run individually, and as entire suites.  Additionally, I'm trying to remove all the dang Sleeps, RefreshDomTrees, and other baggage that I've had to add to make them work reliably that I'm not suppose to have to do to make autopostbacks work.  It's a little hard to stabilize when I'm running up against strange intermittent problems ;-(.  I'd really need to get these stablized before beginning on the next 15K of tests.  If I have to wait a week, so be it, but if I don't have to that would be much better.

Page 1 of 1 (14 items)
Copyrights © 2008 ArtOfTest, Inc. All rights reserved.