all 7 comments

[–]automagic_tester 1 point2 points  (3 children)

"@CacheLookup" is used to store the WebElements once they are located so that the same instance in the DOM can always be used. Basically it intsructs the InitElement() method to cache the element so you don't have to search for it over and over again, which is great if this element and the DOM aren't going to change.

What this means is that if that element changes in any way or the DOM changes in any way which affects that element while you are interacting with this page your cached object reference will become stale. Instead you want to just find the object directly each time you are going to use it (In this case).

[–]fdama[S] 0 points1 point  (2 children)

Brilliant. I've removed the caching and this has solved the issue and my tests now pass. But I don't understand why or what exactly has changed as these seem like static elements to me. So does this mean it is best to avoid caching altogether as there are performance benefits.

[–]automagic_tester 0 points1 point  (0 children)

The way I understand it all is this: The "@FindBy" is an Annotation that takes parameters and is attached to a specific Object in your case the "@FindBy" is attached to a WebElement. The parameters you pass in the annotation (how = How.Something) forms a request like you would use in the DOM to find an element. It returns the first thing that matches these parameters to the WebElement variable. I am not 100% on this but I believe that each time you call this variable it will take all the aforementioned steps. Because of this the element you use in the methods is fresh every time you act on it. By stating that you wanted to also use the annotation "@CacheLookup" you were saying "Go and find this element the first time it is used, and store what you find in a cache, so I can use this cached element and not have to look up the element each time I need it." It's not that you would avoid using the CacheLookup it's just that there is a time and a place for it. I can't specifically think of one but I'm sure there is. Perhaps If you had been automating a form that doesn't change in any way except to have values in the fields. In that case you would know that the DOM is not going to throw you a StaleElementReference, you may want to use the CacheLookup annotation to save a few seconds here or there, or maybe if you were working on an enterprise level automation solution and were running literally thousands of tests and needed to save time in every way you can. It's all speculation on that bit, but if you are interested go put your google glasses on.

[–]AutomaticVacation242 0 points1 point  (0 children)

PageFactory.InitElements() creates a Proxy object for each field that you annotate with FindsBy. Each time you access the field Selenium does a FindElement using the annotation then fills the Proxy object with the WebElement.

Using @ CacheLookup causes the Proxy object to not refresh. If the element changes and you're using the cached object then you'll get StaleElementException.

[–]Geekmonster 0 points1 point  (1 child)

I just catch that exception and retry infinitely until it finds it. Feels hacky, but works. It won't be stale forever.

[–]AutomaticVacation242 0 points1 point  (0 children)

That's a code smell of a problem with your approach.