![Show Menu](styles/mobile-menu.png)
![Page Background](./../common/page-substrates/page0407.png)
Do you remember that we set an
implicitly_wait
on the browser, way back in
Chap‐ ter 2 ?Do you remember I mentioned it was unreliable?
implicitly_wait
works reasonably well for any calls to any of the Selenium
find_el
ement_
calls, but it doesn’t apply to
browser.current_url
. Seleniumdoesn’t “wait” after
you tell it to click an element, so what’s happened is that the browser hasn’t finished
loading the new page yet, so
current_url
is still the old page. We need to use some
more wait code, like we did for the various Persona pages.
At this point it’s time for a “wait for” helper function. To see how this is going to work,
it helps to see how I expect to use it (outside-in!):
functional_tests/test_my_lists.py (ch20l012).
# She sees that her list is in there, named according to its
# first list item
self
.
browser
.
find_element_by_link_text
(
'Reticulate splines'
)
.
click
()
self
.
wait_for
(
lambda
:
self
.
assertEqual
(
self
.
browser
.
current_url
,
first_list_url
)
)
We’re going to take our
assertEqual
call and turn it into a lambda function, then pass
it into our
wait_for
helper.
functional_tests/base.py (ch20l013).
import
time
from
selenium.common.exceptions
import
WebDriverException
[
...
]
def
wait_for
(
self
,
function_with_assertion
,
timeout
=
DEFAULT_WAIT
):
start_time
=
time
.
time
()
while
time
.
time
()
-
start_time
<
timeout
:
try
:
return
function_with_assertion
()
except
(
AssertionError
,
WebDriverException
):
time
.
sleep
(
0.1
)
# one more try, which will raise any errors if they are outstanding
return
function_with_assertion
()
wait_for
then tries to execute that function, but instead of letting the test fail if the
assertion fails, it catches the
AssertionError
that
assertEqual
would ordinarily raise,
waits for a brief moment, and then loops around retrying it. The
while
loop lasts until
a given timeout. It also catches any
WebDriverException
that might happen if, say, an
element hasn’t appeared on the page yet. It tries one last time after the timeout has
expired, this time without the
try/except
, so that if there really is still an
AssertionEr
ror
, the test will fail appropriately.
A Common Selenium Problem: Race Conditions
|
379