Thursday, 17 October 2013

"Joy" of using LoadableComponent in Selenium

When using LoadableComponent in my JUnit tests, found the biggest issue is the usage of load() and isLoaded() functions.

First of all, the first trip-over is the isLoaded() HAS TO be implemented. If you leave it blank, your LoadableComponent will not be loaded. There is no error or any warning. You JUnit test will just keep hanging there and waiting until timeout.

Second thing, which is still a myth to me, is if the isLoaded() method is called to access some elements are not ready on the page yet (which is logical and common and even from the official example provided on Selenium Wiki), it does not ALWAYS successful. It seems we have to force the load() method to be called (to load the element) before any isLoaded() validation kicks in.

With debugging, I found the isLoaded() method is actually called before load() method and then is called again. It sort of makes me feeling confused as with example on Selenium Wiki, it looks logical that load() method is the first method will be called upon calling the get() method of the LoadableComponent but it is not (the load() and isLoaded() methods are not exposed to use publicly anyway and we do not have any other choices).

However, my expectation on how to use these two methods are completely flipped after I found this post on the Internet, then it explained why I have been experiencing the problems above as the load() method will not be called at first and only isLoaded() method is called and then if it is not successful, it will then call load() method. However, in my case, some of my tests on isLoaded() calls are still not successful for some (unknown) reason(s) and that is still a myth.

So the official guide of using LoadableComponent is not quite correct and it sort of leads us to think the load() method is the place we put all the logic to load the page whereas isLoaded() method is the place we put the validation on checking whether the page is loaded or not. So to my impression, load() method should be the one we always implement as it is the access point of the page and will be called first. However, from the source code in that post, it seems load() method is not necessarily to be implemented whereas the isLoaded() method is one has to be implemented.

Moreover, my pages are loadable components and in dependency on other pages. So the load() method cannot be placed in the Contructor. At the end, my solution is to call my load() method as the first line in my isLoaded() method. This then solved my problems. However, I still do not think it is nice.

Tuesday, 15 October 2013

"Wait" for the element to be ready/visible in Web page when automating functional tests

When coding to automate functional tests for web applications, I find that it is always an issue when waiting for the Web element to be ready and be accessed. I think the challenge here is the waiting time is really various as it depends on the response of the browser in different environment. No one knows how long exactly an element will be available on the page for accessing.

In Selenium, we use WebDriverWait and there are many ExpectedConditions we can choose from in Java. However, this approach does not work in many occasions based on the context. It is not complete guarantee that the element would be waited till the expected the condition meets and becomes accessible. Moreover, the wait will immediately throw error if the locator of the element is evaluated as read-only at the time. So the entire wait process will be terminated.

In Coded UI, we can use UITestControl and its related wait functions to wait until the element is ready to be accessed. However, it does not work every time, either. Moreover, if using IWebElement, there are no such waiting methods available.

With Thread.Sleep() method, we could force the wait in fixed timeframe. However, it is not efficient enough and it is not 100% guaranteed that the fixed wait is long enough.

So at the end, I go for the customized way of waiting and it is not perfect, either. But it should solve most of the issues.

public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds) {
            IWebElement element = null;
            bool found = false;                      

            do {
                try {
                    element = driver.FindElement(by);                    
                    found = true;
                } catch (Exception e) {
                    throw e;
                }

                if (!found) {
                    Thread.Sleep(1000);
                }

                timeoutInSeconds--;
            } while (timeoutInSeconds > 0 && !found);
                     
            return element;
        }

Note that the parameter of timeoutInSeconds is the time of trying to wait for the element to be available but not the time has to be waited in this call. So if the element is available before the timeout, it will be returned.

Based on this method, we can then write more customized methods (if necessary) that to add conditions of waiting. I guess this approach would sort of guarantee that an element will be accessed in the most efficient way.