Given the code you show in the question, if you have a 30 second wait before Selenium decides that the element is missing, this means you are using implicit waits. You should stop using implicit waits and use explicit waits exclusively. The reason is that sooner or later you'll want to use an explicit wait to control precisely how long Selenium waits. Unfortunately, implicit and explicit waits just don't mix. The details are explained in this answer.
There are two general methods I use to test for the absence of an element, depending on conditions. The one problem that we face when using Selenium to test dynamic applications is the following: at which point can you be certain that the element whose absence you want to check is not going to show up a fraction of a second later than the moment at which you check? For instance, if you perform a test which clicks a button, which launches an Ajax request, which may cause an element indicating an error to be added to the DOM when the request fails, and you check for the presence of the error element immediately after asking Selenium to click the button, chances are you're going to miss the error message, if it so happens that the request fails. You'd have to wait at least a little bit to give the Ajax request a chance to complete. How long depends on your application.
This being said, here are the two methods that I use.
Pair an Absence With a Presence
I pair the absence test with a presence test, use find_elements
rather than find_element
, check for a a length of zero on the array returned by find_elements
.
By "I pair the absence test with a presence test" I mean that I identify a condition like the presence of another element on the page. This condition must be such that if the condition is true, then I do not need to wait to test for the absence: I know that if the condition is true, the element whose absence I want to test must be either finally absent or present on the page. It won't show up a fraction of a second later.
For instance, I have a button that when clicked performs a check through an Ajax call, and once the Ajax call is done puts on the page <p>Check complete</p>
and under it adds paragraphs with error messages if there are errors. To test for the case where there is no error, I'd wait for <p>Check complete</p>
to come up and only then check for the absence of the error messages. I'd use find_elements
to check for these error messages and if the length of the returned list is 0, I know there are none. Checking for these error messages themselves does not have to use any wait.
This also works for cases where there is no Ajax involved. For instance, if a page is generated by the server with or without a certain element, then there is no need to wait and the method described here can be used. The "presence" of the page (that is, the page has finished loading) is the only condition needed to check for the absence of the element you want to check.
Wait for a Timeout
In cases where I cannot benefit from some positive condition to pair with my absence check, then I use an explicit wait:
import selenium.webdriver.support.expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from nose.tools import assert_raises
def test():
WebDriverWait(driver, timeout).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".foo")))
assert_raises(TimeoutException, test)
In the code above driver
a Selenium's WebDriver
previously created, timeout
is the desired timeout, and assert_raises
is just an example of an assertion that could be used. The assertion passes if TimeoutException
is raised.