Working with functional testing in the web application space means you need to deal with a few troublesome areas which may not be familiar to you.
Let’s look at three common situations you’ll likely run into on web applications:
- JavaScript is bound to an input field and is disrupting your test’s input to that field.
- You’re working with dynamic content where the element you need isn’t yet loaded.
- You’re working with dynamic content where the content you need isn’t yet loaded.
Problem 1: JavaScript interfering with text input
Most web automation tools and frameworks handle input fields by injecting text straight to the page’s Document Object Model (DOM). It’s very fast to set properties directly on the DOM to simulate inputting text. Unfortunately, this speed comes at a price when you’re working with JavaScript.
Problem: JavaScript is interfering with text input in your test scripts. For example, some applications might use JavaScript to check that the password and username fields both have content before enabling the login button. The JavaScript doesn’t detect your script’s input of text since it’s done at the DOM level and the JavaScript is at a higher level.
Solution: You need to have your framework or tool speak to the browser directly, or take some other action to cause that JavaScript event to fire. The solution varies by framework. When using Selenium WebDriver, the field’s onchange event only fires when focus leaves that field. You’ll need to click to another field to get the validation to work properly. That might look something like this:
Another answer might be to use one of the other WebDriver events like Blur.
Some commercial tools such as Telerik’s Test Studio, the tool I represent, have their own approaches to solving this problem. The point being, spend time understanding your app and your tools.
Problem 2: The dynamic element you need isn’t yet loaded!
Problem: Your test script is expecting to interact with a particular element, but that element hasn’t yet been loaded on the page.
Have a look at the ASP.NET AJAX demo page for a drop down menu. Use a tool like Firebug to inspect the current DOM and you’ll see the menu elements aren’t actually loaded on the page yet. The menu elements (the ones you want to interact with!) don’t get loaded until you click on the pull-down list. You can’t validate or interact with elements that aren’t yet there!
Answer: Most tools or frameworks handle these sorts of situations for you via implicit waits. The tool’s browser driver understands the necessary element isn’t there and will implicitly wait for that element to appear within a reasonable timeout period.
Selenium’s implicit wait feature handles this problem nicely. You set a default timeout for the browser session you’re currently using, after which Selenium will wait for the configured amount of time for the elements to appear. If the elements don’t show up in the DOM before the timeout expires, you’ll see an Exception, which is what you want – the elements aren’t appearing, so your test is failing. In Selenium this looks like:
Note we’re setting the ImplicitWait property to ten seconds. The test will hang around that long waiting for the service call to finish and the DOM to update with the element we need to work with.
Tools such as Test Studio or QTP generally handle the need for implicit waits without any intervention from the user.
Problem 3: The dynamic content you need isn’t yet loaded
Problem: Your script is expecting to check for or otherwise interact with some content on the page, but that content isn’t yet loaded up.
Answer: Use explicit waits to delay your test’s execution until the content is loaded.
Have a look at the ASP.NET AJAX demo page for cascading menus.
Use a tool like Firebug to inspect the current DOM and you’ll see the menu elements are there, but not their content. Make some choices for the menus, look at the DOM. Now you’ll see the content exists after having been loaded by an AJAX callback. Because the elements exist, but not their content, we need to handle this with an explicit wait. (See the great Selenium article on explicit and implicit waits.)
In the example above we need to navigate to the page, then make a series of selections. In each dropdown selection list, we’ll need to get that selection element, then wait for the specific item we want to appear. That content is loaded by the previous selection, or in the case of the Make selection, by the actual page loading.
Here’s how we write the first section of code to wait and select our option in the Make pulldown. After that, we use WebDriverWait to explicitly wait until our target element (the make of “Acura” in this case) appears. Once the content is loaded in to the options we can then select the specific item from the option list.
Actions on the remaining two lists are the same. For the final confirmation message, also AJAX-ified, we can go back to our implicit wait pattern shown earlier—that message is in an element which isn’t loaded on the page. (NOTE: The test for the confirmation message isn’t a great one. A better one would be to ensure the proper combination of make+model+color is rendered as well as the general message – I took this shortcut for brevity’s sake because this example’s already somewhat lengthy.)
The entire test looks like this:
Commercial tools generally handle this in a similar fashion: wait for the item you need to work with to appear, then interact with it. The exact steps vary, of course, with the specific tools, but the overall approach is the same.
There you have it. A quick walk-through of three common situations on web pages that can give automation folks grief. You can avoid this grief in your own automation projects by learning exactly how your own system works. More time with the development folks is a good thing for your accurate, stable, and maintainable tests!
About the Author
Jim Holmes Father. Husband. Geek. Veteran. Around 25 years IT experience. Co-author of “Windows Developer Power Tools.” Coffee Roaster. MVP for C#. Chief Cat Herder of the CodeMash Conference. Diabetic. Runner. Liked 5th grade so much he did it twice. One-time setter, middle blocker, and weakside hitter. Blogger (http://FrazzledDad.com). Evangelist for Telerik’s Test Studio, an awesome set of tools to help teams deliver better software. Big fan of naps.