Scope is causing slow tests due to frame usage

179 views
Skip to first unread message

Adam

unread,
Jul 5, 2012, 12:12:01 PM7/5/12
to co...@googlegroups.com
Hey Adrian,


I'm afraid its me again.  I have updated to the latest version of Coypu from the version without scope ( I gave up when I tried before).  This has slowed down tests because Iuse frames.  My site contains a page with 3 frames, a top menu and a left menu.  So heres what I have had to do to get it to work.  In my base class I have:


public abstract class AuthenticatedPage : Page
    {
        protected ElementScope TopMenu;
        protected ElementScope LeftMenu;
        protected ElementScope MainContent;
 
        protected AuthenticatedPage(BrowserSession browserSession)
            : base(browserSession)
        {
            TopMenu = browserSession.FindFrame("1_mainMenuFrame");
            LeftMenu = browserSession.FindFrame("1_menuFrame");
            MainContent = browserSession.FindFrame("1_displayFrame");
        }


When I want to reference a link on the topmenu I use:

TopMenu.ClickLink("Log off");

Every interaction now needs to be prefixed with TopMenu. MainContent. , etc.  So this sounds ok until you look at what selenium is doing.  Everytime I run a command it does something like:

  1. Is there an iframe with the id topMenu?
  2. Is there an iframe with the name topMenu?
  3. Is there an iframe with the title topMenu?
  4. Is there an frame with the id topMenu?  <-- my code exits at this point but it could continue if I used title
  5. Is there an frame with the name topMenu?
  6. Is there an frame with the title topMenu?
  7. Click the link


I know that what I am doing is a special case and that anyone in there right mind wouldn't be using frames but its not something I can change.  Am I misusing coypu? can you think  of a better way of using it?  If not would you consider changing locator into a class which would allow option parameters which could say this is an id and a frame? or perhaps a FindFrameId and FindFrameId.  Please let me know your thoughts.


Thanks


Adam

Adrian Longley

unread,
Jul 6, 2012, 4:40:16 AM7/6/12
to co...@googlegroups.com

On 5 Jul 2012, at 17:12, Adam <afi...@gmail.com> wrote:

Hey Adrian,


I'm afraid its me again.  I have updated to the latest version of Coypu from the version without scope ( I gave up when I tried before).  This has slowed down tests because Iuse frames.  My site contains a page with 3 frames, a top menu and a left menu.  So heres what I have had to do to get it to work.  In my base class I have:


public abstract class AuthenticatedPage : Page
    {
        protected ElementScope TopMenu;
        protected ElementScope LeftMenu;
        protected ElementScope MainContent;
 
        protected AuthenticatedPage(BrowserSession browserSession)
            : base(browserSession)
        {
            TopMenu = browserSession.FindFrame("1_mainMenuFrame");
            LeftMenu = browserSession.FindFrame("1_menuFrame");
            MainContent = browserSession.FindFrame("1_displayFrame");
        }


When I want to reference a link on the topmenu I use:

TopMenu.ClickLink("Log off");

Every interaction now needs to be prefixed with TopMenu. MainContent. , etc.  So this sounds ok until you look at what selenium is doing.  Everytime I run a command it does something like:

  1. Is there an iframe with the id topMenu?
  2. Is there an iframe with the name topMenu?
  3. Is there an iframe with the title topMenu?
  4. Is there an frame with the id topMenu?  <-- my code exits at this point but it could continue if I used title
  5. Is there an frame with the name topMenu?
  6. Is there an frame with the title topMenu?
  7. Click the link


I know that what I am doing is a special case and that anyone in there right mind wouldn't be using frames but its not something I can change.  Am I misusing coypu?

I don't think so. Once you have a reference to a frame (i or otherwise) the intention was that it would not try to re-find it after the first command in that scope unless it became stale, so if the frameset page has not been reloaded I would expect it only to go through the above process once for the lifetime of the AuthenticatedPage instance.

Is that what you are seeing or are you saying if you call:

TopFrame.ClickLink('a');
TopFrame.ClickLink('b');

then it does all those finds twice? If so that would be a bug.

If this is not the problem - you only find frames once per test - but it has still significantly slowed down your tests, then we need to take another look at this strategy I agree.

can you think  of a better way of using it?  If not would you consider changing locator into a class which would allow option parameters which could say this is an id and a frame? or perhaps a FindFrameId and FindFrameId.  Please let me know your thoughts.

I agree that might be nice in special cases like this but I was hesitant to introduce this kind of thing everywhere if it is just for speed. Feels like we should fix that problem within Coypu rather than expecting everyone to do this at the cost of extra complexity on both sides.

I have been tossing around one idea that should really help with this. Be interested in your opinion:

The driver could learn which strategy was successful to find a given element by a given locator over the duration of the test run (i.e. statically ). This would apply to FindField/Button/Frame/Link etc.. Then next time it gets the same locator it could select the most successful strategy from what it has learned.

What do you reckon?

Thanks


Adam

Adam

unread,
Jul 6, 2012, 5:44:12 AM7/6/12
to co...@googlegroups.com
Hey,

I like the idea of caching where it found it from.  I thought about that, but thought it would be difficult to do because of frequent page changes and what was an id on one page could be name on another page but I guess you could create a lookup table against hte page your viewing.  After what you said, I relooked at my code and I'm pretty sure it is refinding it but I did see the following in the logs:

10:01:00.625 INFO - Executing: [find child element: 5 org.openqa.selenium.support.events.EventFiringWebDriver$EventFiringWebElement@41e32ff3, By.xpath: .] at URL: /session/1341565120618/element/5/element)
10:01:01.938 WARN - Exception thrown
org.openqa.selenium.StaleElementReferenceException: Element is no longer valid (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 31 milliseconds
For documentation on this error, please visit: http://seleniumhq.org/exceptions/stale_element_reference.html
Build info: version: '2.23.0', revision: '17137', time: '2012-06-07 15:43:04'
System info: os.name: 'Windows 2003', os.arch: 'x86', os.version: '5.2', java.version: '1.7.0_05'
Driver info: driver.version: RemoteWebDriver
Session ID: c3e20595-9062-4633-a228-7fcb6d992289
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
        at java.lang.reflect.Constructor.newInstance(Unknown Source)
        at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:188)
        at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:145)
        at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:458)
        at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:244)
        at org.openqa.selenium.ie.InternetExplorerElement.findElement(InternetExplorerElement.java:36)
        at org.openqa.selenium.remote.RemoteWebElement.findElementByXPath(RemoteWebElement.java:220)
        at org.openqa.selenium.By$ByXPath.findElement(By.java:343)
        at org.openqa.selenium.remote.RemoteWebElement.findElement(RemoteWebElement.java:155)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.openqa.selenium.support.events.EventFiringWebDriver$EventFiringWebElement$1.invoke(EventFiringWebDriver.java:327)
        at $Proxy2.findElement(Unknown Source)
        at org.openqa.selenium.support.events.EventFiringWebDriver$EventFiringWebElement.findElement(EventFiringWebDriver.java:398)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.openqa.selenium.remote.server.KnownElements$1.invoke(KnownElements.java:63)
        at $Proxy3.findElement(Unknown Source)
        at org.openqa.selenium.remote.server.handler.FindChildElement.call(FindChildElement.java:43)
        at org.openqa.selenium.remote.server.handler.FindChildElement.call(FindChildElement.java:1)
        at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
        at java.util.concurrent.FutureTask.run(Unknown Source)
        at org.openqa.selenium.remote.server.DefaultSession$1.run(DefaultSession.java:150)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)
10:01:01.985 WARN - Exception: Element is no longer valid (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 31 milliseconds
For documentation on this error, please visit: http://seleniumhq.org/exceptions/stale_element_reference.html
Build info: version: '2.23.0', revision: '17137', time: '2012-06-07 15:43:04'
System info: os.name: 'Windows 2003', os.arch: 'x86', os.version: '5.2', java.version: '1.7.0_05'
Driver info: driver.version: RemoteWebDriver
Session ID: c3e20595-9062-4633-a228-7fcb6d992289
10:01:02.078 INFO - Executing: [get window handles] at URL: /session/1341565120618/window_handles)
10:01:02.094 INFO - Done: /session/1341565120618/window_handles
10:01:02.094 INFO - Executing: [switch to window: ebecd479-8efb-49fe-abed-774bee39144a] at URL: /session/1341565120618/window)
10:01:02.141 INFO - Done: /session/1341565120618/window
10:01:02.141 INFO - Executing: [find elements: By.tagName: iframe] at URL: /session/1341565120618/elements)

So maybe that exception is the cause.  I googled the error but couldn't work out why the page would have changed, but I wonder if that exception is happening and then something is researching for it.  I do get that exception a lot while running the code.  I'm finding the remote web driver really good as it shows me what selenium is doing.

As a side note, you may want to update webdriver.support to 2.23 in Nuget as Nuget complains that only 2.19 is compatable with CoyPu but webDriver is on 2.23 and so webdriver.support throws an exception.  I have manually forced nuget to install webdriver.support 2.23 on my machine but unless there is a reason not to, you may want to update the NuGet package.

Thanks

Adam

Adrian Longley

unread,
Jul 6, 2012, 6:25:23 AM7/6/12
to co...@googlegroups.com
Coypu 0.10.1 does depend on WebDriver 2.23. Are you sure you have the latest Coypu?

Adam

unread,
Jul 6, 2012, 6:36:44 AM7/6/12
to co...@googlegroups.com
Hey,

I may be missing something but http://nuget.org/packages/Coypu says:

Dependencies


Adam


On Thursday, 5 July 2012 17:12:01 UTC+1, Adam wrote:

Adam

unread,
Jul 6, 2012, 6:39:17 AM7/6/12
to co...@googlegroups.com
Hey,

Sorry misread what you said.  Yes I am using the latest version and Selenium is at 2.23 but selenium.WebDriverSupport wouldn't install because it said Coypu wanted a previous version but looking at http://nuget.org/packages/Coypu suggests there are no dependencies on this.


Adam


On Thursday, 5 July 2012 17:12:01 UTC+1, Adam wrote:

Adam

unread,
Jul 6, 2012, 8:47:49 AM7/6/12
to co...@googlegroups.com
Hey,

Sorry its just dawned on me that I was trying to install the new web driver support package and not the 2.23 one.  Sorry for the confusion.


Adam


On Thursday, 5 July 2012 17:12:01 UTC+1, Adam wrote:

Adam

unread,
Jul 8, 2012, 2:38:57 PM7/8/12
to co...@googlegroups.com
Hey,

I've done an ElementCacher for Selenium driver.  I will pull it from work on Monday and run my tests through it to check that everything is ok.  If you want, you can have a look.  https://github.com/afinzel/coypu .  I'm not sure its checked in right.  It was the first time I tried the GitHub tool.

Cheers

Adam


On Thursday, 5 July 2012 17:12:01 UTC+1, Adam wrote:

Adrian Longley

unread,
Jul 8, 2012, 3:05:49 PM7/8/12
to co...@googlegroups.com
Adam,

That's interesting and thanks for getting involved!

I see what you are trying to do but caching is currently implemented at the level of the ElementScope where it is not supposed to ask the driver to refind unless the element has become stale. So I think this would break that unless I'm very much mistaken. Did you run all the AcceptanceTests?

I still haven't had a chance to look at the issue you reported, if there is a problem around frames I'd like to isolate that first.

Then perhaps we could consider your approach but at a higher level, which might be caching ElementScopes on the DriverScope rather than down in each Driver I think.

I'll have a think about it though, and try and get some time to hack on this over the next few days.

Cheers,
Adrian

Adam

unread,
Jul 8, 2012, 6:34:40 PM7/8/12
to co...@googlegroups.com
Hey Adrian,

I hadn't spotted the acceptance tests, just the coypu.tests , not sure how.  When I got them running I played about with the Iframe test.  Now, I'm not sure I fully understand  your code I guess I should really look at it a bit more but I did find something which may help track down the problem. What I found was that everytime the Iframe hit the FindElement, it was always stale.  This sounded like a bug with web driver.  So I did a bit of hacking with the code and modified DriverScope.FindElement to:

 protected internal ElementFound FindElement()
        {
            if (element == null || element.Stale)
            {
                element = elementFinder.Find();
                var selenium = ((OpenQA.Selenium.Remote.RemoteWebDriver)element.Native);
                try
                {
                    selenium.FindElementById("inputInIFrame");
                }
                catch
                {
                    // hit me if not the iframe
                }
                
                var areWeStale = element.Stale;
            }
            return element;
        }

This meant that when the element was a seleniumIframe areWeStale  was always true.  Please let me know if this is correct behavior or perhaps the cause of the bug.

Regards

Adam

On Thursday, 5 July 2012 17:12:01 UTC+1, Adam wrote:
Reply all
Reply to author
Forward
0 new messages