Testing AJAX: Selenium’s ElementNotFoundException

motif

com.thoughtworks..: ERROR: Element bla bla bla not found

Ok. Face the music. Let’s debug.

Check list:

  • Is locator well defined? Yes. 
  • The element is rendered? Yes.
  • Do I have any error when I execute code step by step? No.χ
  • Am I crazy? Perhaps. But the problem continues to be there and I have no clue why!!!

What is happening here?

Ah, Gotcha! Ajax behind the scenes! So when I run the integration tests as fast as possible, Selenium tries to locate an element that is not already rendered and/or its state changed. Then Selenium not finding anything to eat, throws the annoying exception.

Note that it is not only a problem of an element not being rendered. Depending on what precondition you need, perhaps you have to wait for an input field to be editable after some user action, or some section to be visible or even you have to make sure that an element is not being there!

First solution

Only one comment: Don’t!

Don't use Thread.sleep() to wait for element!

The Good: ?

The Bad: Code that depends on sleep() is delayed a fixed time just in case; Bad performance. Also, you’ll end having flaky results. It can happen that sometimes a component will take longer than usually to be rendered or be affected by whatever callback function is assigned to it. Well, you can “solve” that, increasing the sleep time… Ufff. A cold breeze seemed to have entered the room…

Second solution

don't do it

The Good: Intead of waiting a fixed amount of time and expect things are all right after that, a mechanism is defined to take into account that an the element has no deterministic time for being rendered, for example.

The Bad: Logic that relies on the exception mechanism; Design problem.

Proposed solution

Use of Selenium’s waitForCondition mechanism to handle all those gritty details.

Also notice that if for some reason your code is too fast (ie. infinite SeleniumExceptions that appear only when running the code at full speed), you can slow things down in a graceful way, making it slower before the waitForCondition() call and reestablishing the speed after that.

In which scenario this can be useful? Well, when you are developing your page models, perhaps you will be concerned more about something to show than actual performance and/or Ajax issues. When the code is stable, you can start playing with the parameters to adjust them to the optimal value for your system. Goal: Zero Default delay.


We'd love to hear your opinion on this post