WebDriver Wrapper documentation¶
What is WebDriver Wrapper? Better interface of WebDriver in Python. WebDriver is great for testing whole web apps, but it’s pain using available API. This wrapper wraps it and handle following for you:
- Adds messages into WebDriver’s exceptions. By default there is no information about which element is missing and where and so on.
- Adds usefull method to
selenium.WebDriver
andselenium.WebElement
such asfind_elements_by_text
,contains_text
,wait_for_element
,go_to
,download_file
- and more.
- Simplifys filling out of forms.
- Provide
TestCase
for unittesting. - Provide pytest fixtures for testing with pytest.
Installation¶
pip install webdriverwrapper
If you want also suggestions, then also install extra requirements:
pip install webdriverwrapper[seggestions]
Then you will see something like this:
driver.get_elm('qbdfq')
NoSuchElementException: Message: No element <* id=qbdfq> found at https://www.google.com, did you mean id=gbsfw?
Hello World!¶
driver = Chrome()
driver.get('http://www.google.com')
form_elm = driver.get_elm('gbqf')
form_elm.fill_out_and_submit({
'q': 'Hello World!',
})
driver.wait_for_element(id_='search')
driver.quit()
Documentation¶
Wrapper¶
-
class
webdriverwrapper.wrapper.
_WebdriverBaseWrapper
[source]¶ Class wrapping both
selenium.WebDriver
andselenium.WebElement
.-
click
(*args, **kwds)[source]¶ When you not pass any argument, it clicks on current element. If you pass some arguments, it works as following snippet. For more info what you can pass check out method
get_elm()
.driver.get_elm('someid').click()
-
contains_text
(text)[source]¶ Does page or element contains text?
Uses method
get_elms()
.
-
default_wait_timeout
= 10¶ Default timeout in seconds for wait* methods (such as wait_for_element).
New in version 2.7.
-
find_element_by_text
(text)[source]¶ Returns first element on page or in element containing
text
.New in version 2.0.
Deprecated since version 2.8: Use
get_elm()
instead.
-
find_elements_by_text
(text)[source]¶ Returns all elements on page or in element containing
text
.Changed in version 2.0: Searching in all text nodes. Before it wouldn’t find string “text” in HTML like
<div>some<br />text in another text node</div>
.Deprecated since version 2.8: Use
get_elms()
instead.
-
get_elm
(id_=None, class_name=None, name=None, tag_name=None, text=None, xpath=None, parent_id=None, parent_class_name=None, parent_name=None, parent_tag_name=None, css_selector=None)[source]¶ Returns first found element. This method uses
get_elms()
.
-
get_elms
(id_=None, class_name=None, name=None, tag_name=None, text=None, xpath=None, parent_id=None, parent_class_name=None, parent_name=None, parent_tag_name=None, css_selector=None)[source]¶ Shortcut for
find_element*
methods. It’s shorter and you can quickly find element in element.elm = driver.find_element_by_id('someid') elm.find_elements_by_class_name('someclasss') # vs. elm = driver.get_elm(parent_id='someid', class_name='someclass')
Changed in version 2.8: Added
text
param. Use it instead of oldfind_element[s]_by_text
methods. Thanks to that it can be used also inwait_for_element*
methods.
-
wait
(timeout=None)[source]¶ Calls following snippet so you don’t have to remember what import. See
WebDriverWait
for more information. Detault timeout is ~.default_wait_timeout.selenium.webdriver.support.wait.WebDriverWait(driver, timeout)
Example:
driver.wait().until(lambda driver: len(driver.find_element_by_id('elm')) > 10)
If you need to wait for element, consider using
wait_for_element()
instead.
-
wait_for_element
(timeout=None, message='', *args, **kwds)[source]¶ Shortcut for waiting for element. If it not ends with exception, it returns that element. Detault timeout is ~.default_wait_timeout. Same as following:
selenium.webdriver.support.wait.WebDriverWait(driver, timeout).until(lambda driver: driver.get_elm(...))
Changed in version 2.5: Waits only for visible elements.
Changed in version 2.6: Returned functionality back in favor of new method
wait_for_element_show()
.
-
wait_for_element_hide
(timeout=None, message='', *args, **kwds)[source]¶ Shortcut for waiting for hiding of element. Detault timeout is ~.default_wait_timeout. Same as following:
selenium.webdriver.support.wait.WebDriverWait(driver, timeout).until(lambda driver: not driver.get_elm(...))
New in version 2.0.
-
wait_for_element_show
(timeout=None, message='', *args, **kwds)[source]¶ Shortcut for waiting for visible element. If it not ends with exception, it returns that element. Detault timeout is ~.default_wait_timeout. Same as following:
selenium.webdriver.support.wait.WebDriverWait(driver, timeout).until(lambda driver: driver.get_elm(...))
New in version 2.6.
-
-
class
webdriverwrapper.wrapper.
_WebdriverWrapper
(*args, **kwds)[source]¶ Class wrapping
selenium.WebDriver
.-
break_point
()[source]¶ Stops testing and wait for pressing enter to continue.
Useful when you need check Chrome console for some info for example.
New in version 2.1.
-
close_alert
(ignore_exception=False)[source]¶ JS alerts all blocking. This method closes it. If there is no alert, method raises exception. In tests is good to call this method with
ignore_exception
setted toTrue
which will ignore any exception.
-
close_other_windows
()[source]¶ Closes all not current windows. Useful for tests - after each test you can automatically close all windows.
-
close_window
(window_name=None, title=None, url=None)[source]¶ WebDriver implements only closing current window. If you want to close some window without having to switch to it, use this method.
-
download_url
(url=None)[source]¶ With WebDriver you can’t check status code or headers. For this you have to make classic request. But web pages needs cookies and by this it gets ugly. You can easily use this method.
When you not pass
url
,current_url
will be used.Returns
_Download
instance.
-
fill_out
(data, prefix='', turbo=False)[source]¶ Shortcut for filling out first
<form>
on page. SeeForm
for more information.New in version 2.0.
-
fill_out_and_submit
(data, prefix='', turbo=False)[source]¶ Shortcut for filling out first
<form>
on page. SeeForm
for more information.New in version 2.0.
-
get_url
(path=None, query=None)[source]¶ You have to pass absolute URL to method
get()
. This method help you to pass only relativepath
and/orquery
. Scheme and domains is append to URL fromcurrent_url
.query
can be final string or dictionary. On dictionary it callsurllib.urlencode()
.New in version 2.0.
-
go_to
(path=None, query=None)[source]¶ You have to pass absolute URL to method
get()
. This method help you to pass only relativepath
and/orquery
. See methodget_url()
for more information.Changed in version 2.0: Removed parameter
domain
. If you want to go to completely another web app, use absolute address.
-
html
¶ Returns
innerHTML
of whole page. On page have to be tagbody
.New in version 2.2.
-
make_screenshot
(screenshot_name=None)[source]¶ Shortcut for
get_screenshot_as_file
but with configured path. If you are using baseWebdriverTestCase
. or pytest,screenshot_path
is passed to driver automatically.If
screenshot_name
is not passed, current timestamp is used.New in version 2.2.
-
-
class
webdriverwrapper.wrapper.
_WebElementWrapper
(webelement)[source]¶ Class wrapping
selenium.WebElement
.-
current_url
¶ Accessing
current_url
also on elements.
-
download_file
()[source]¶ With WebDriver you can’t check status code or headers. For this you have to make classic request. But web pages needs cookies and data from forms and by this it gets pretty ugly. You can easily use this method.
It can handle downloading of page/file by link or any type of form.
Returns
_Download
instance.
-
html
¶ Returns
innerHTML
.New in version 2.2.
-
Forms¶
-
class
webdriverwrapper.forms.
Form
(webelement)[source]¶ -
fill_out
(data, prefix='', skip_reset=False)[source]¶ Fill out
data
by dictionary (key is name attribute of inputs). You can pass normal Pythonic data and don’t have to care about how to use API of WebDriver.By
prefix
you can specify prefix of all name attributes. For example you can have inputs calledclient.name
andclient.surname
- then you will pass toprefix
string"client."
and in dictionary just"name"
.Option
skip_reset
is for skipping reset, so it can go faster. For example for multiple selects it callsdeselect_all
first, but it need to for every option check if it is selected and it is very slow for really big multiple selects. If you know that it is not filled, you can skip it and safe in some cases up to one minute! Also same with text inputs, but first is calledclear
.Example:
driver.get_elm('formid').fill_out({ 'name': 'Michael', 'surname': 'Horejsek', 'age': 24, 'enabled': True, 'multibox': ['value1', 'value2'] }, prefix='user_')
Changed in version 2.2:
turbo
renamed toskip_reset
and used also for common elements like text inputs or textareas.
-
fill_out_and_submit
(data, prefix='', skip_reset=False)[source]¶ Calls
fill_out()
and thensubmit()
.
-
Downloading¶
-
class
webdriverwrapper.download.
_Download
[source]¶ Object returned by calling
download_url()
ordownload_file()
.-
data
¶ RAW data of response.
-
encoding
¶ Encoding of reponse.
-
headers
¶ Headers of response.
See
requests.Response.headers
for more information.
-
method
¶ Used method of request.
GET
orPOST
.
-
status_code
¶ Status code of response.
-
Testing¶
Supported are both UnitTest and PyTest tests. Each of them have own section bellow, but first you have to know something about “expecting decorators”.
After each test is called method
check_expected_errors
and check_expected_infos
which will raise exception if there is some unexpected error. By default you
doesn’t have to check everytime presence of some error - TestCase
or PyTest
fixtures does that for you automatically. But sometimes you want to test that
something fail - that something ends with some error message or info message.
For that there are several decorators.
# Following test go to relative page "settings" and fill out and submit form.
# Test have to ends on page where is info message to user with key sucessfuly_saved.
@expected_info_message('sucesfully_saved')
def test_save_data(driver):
driver.go_to('settings')
driver.fill_out_and_submit({
'name': 'Michael',
})
# Test have to ends on page indicating that user doesn't have permission.
@expected_error_page('403')
def test_access_admin_page(driver):
driver.go_to('admin')
When you need some changes in method
get_error_page
,
get_error_traceback
,
get_error_messages
or get_info_messages
,
feel free to change it like that:
from webdriverwrapper import Chrome
driver = Chrome()
# Better to set it on instance, so you can change browser without changing this code.
dirver.__class__.get_error_page = your_method
dirver.__class__.get_error_traceback = your_method
dirver.__class__.get_error_messages = your_method
dirver.__class__.get_info_messages = your_method
Decorators¶
-
webdriverwrapper.decorators.
expected_error_page
(error_page)[source]¶ Decorator expecting defined error page at the end of test method. As param use what
get_error_page()
returns.New in version 2.0: Before this decorator was called
ShouldBeErrorPage
.
-
webdriverwrapper.decorators.
allowed_error_pages
(*error_pages)[source]¶ Decorator ignoring defined error pages at the end of test method. As param use what
get_error_page()
returns.New in version 2.0.
-
webdriverwrapper.decorators.
expected_error_messages
(*error_messages)[source]¶ Decorator expecting defined error messages at the end of test method. As param use what
get_error_messages()
returns.New in version 2.0: Before this decorator was called
ShouldBeError
.
-
webdriverwrapper.decorators.
allowed_error_messages
(*error_messages)[source]¶ Decorator ignoring defined error messages at the end of test method. As param use what
get_error_messages()
returns.New in version 2.0: Before this decorator was called
CanBeError
.
-
webdriverwrapper.decorators.
allowed_any_error_message
(func)[source]¶ Decorator ignoring any error messages at the end of test method. If you want allow only specific error message, use
allowed_error_messages()
instead.New in version 2.0.
-
webdriverwrapper.decorators.
expected_info_messages
(*info_messages)[source]¶ Decorator expecting defined info messages at the end of test method. As param use what
get_info_messages()
returns.New in version 2.0: Before this decorator was called
ShouldBeInfo
.
-
webdriverwrapper.decorators.
allowed_info_messages
(*info_messages)[source]¶ Decorator ignoring defined info messages at the end of test method. As param use what
get_info_messages()
returns.New in version 2.0.
Example¶
@expected_info_messages('Your information was updated.')
def test_save(driver):
driver.fill_out_and_submit({
'name': 'Michael',
})
Error and info messages¶
-
class
webdriverwrapper.errors.
WebdriverWrapperErrorMixin
[source]¶ Mixin used in
_WebdriverWrapper
.New in version 2.0: Before you had to change decorators
ShouldByError
,CanBeError
andShouldBeErrorPage
which are gone. Now you can use original decorators and just change one of these methods. For more information check out section testing.-
check_errors
(expected_error_page=None, allowed_error_pages=[], expected_error_messages=[], allowed_error_messages=[])[source]¶ This method should be called whenever you need to check if there is some error. Normally you need only
check_expected_errors
called after each test (which you specify only once), but it will check errors only at the end of test. When you have big use case and you need to be sure that on every step is not any error, use this.To parameters you should pass same values like to decorators
expected_error_page()
,allowed_error_pages()
,expected_error_messages()
andallowed_error_messages()
.
-
check_expected_errors
(test_method)[source]¶ This method is called after each test. It will read decorated informations and check if there are expected errors.
You can set expected errors by decorators
expected_error_page()
,allowed_error_pages()
,expected_error_messages()
,allowed_error_messages()
andallowed_any_error_message()
.
-
get_error_messages
()[source]¶ Method returning error messages. Should return list of messages.
By default it find element with class
error
and theirs value in attributeerror
or text if that attribute is missing. You can change this method accordingly to your app.Error messages returned from this method are used in decorators
expected_error_messages()
andallowed_error_messages()
.
-
get_error_page
()[source]¶ Method returning error page. Should return string.
By default it find element with class
error-page
and returns text ofh1
header. You can change this method accordingly to your app.Error page returned from this method is used in decorators
expected_error_page()
andallowed_error_pages()
.
-
get_error_traceback
()[source]¶ Method returning traceback of error page.
By default it find element with class
error-page
and returns text of element with classtraceback
. You can change this method accordingly to your app.
-
get_js_errors
()[source]¶ Method returning JS errors. Should return list of errors.
You have to include following JS snippet to your web app which will record all JS errors and this method will automatically read them.
<script type="text/javascript"> window.jsErrors = []; window.onerror = function(errorMessage) { window.jsErrors[window.jsErrors.length] = errorMessage; } </script>
-
-
class
webdriverwrapper.info.
WebdriverWrapperInfoMixin
[source]¶ Mixin used in
_WebdriverWrapper
.New in version 2.0: Before you had to change decorator
ShouldBeInfo
which is gone. Now you can use original decorators and just change one of these methods. For more information check out section testing.-
check_expected_infos
(test_method)[source]¶ This method is called after each test. It will read decorated informations and check if there are expected infos.
You can set expected infos by decorators
expected_info_messages()
andallowed_info_messages()
.
-
check_infos
(expected_info_messages=[], allowed_info_messages=[])[source]¶ This method should be called whenever you need to check if there is some info. Normally you need only
check_expected_infos
called after each test (which you specify only once), but it will check infos only at the end of test. When you have big use case and you need to check messages on every step, use this.To parameters you should pass same values like to decorators
expected_info_messages()
andallowed_info_messages()
.
-
get_info_messages
()[source]¶ Method returning info messages. Should return list of messages.
By default it find element with class
info
and theirs value in attributeinfo
or text if that attribute is missing. You can change this method accordingly to your app.Info messages returned from this method are used in decorators
expected_info_messages()
andallowed_info_messages()
.
-
PyTest¶
Import whole module in your main conftest.py
and define fixture _driver
:
import pytest
from webdriverwrapper import Chrome
from webdriverwrapper.pytest import *
# Create browser once for all tests.
@pytest.yield_fixture(scope='session')
def session_driver():
driver = Chrome()
yield driver
driver.quit()
# Before every test go to homepage.
@pytest.fixture(scope='function')
def _driver(session_driver):
session_driver.get('http://www.google.com')
return session_driver
Then you can write tests really simply:
def test_doodle(driver):
driver.click('gbqfsb')
assert driver.contains_text('Doodles')
def test_search(driver):
driver.get_elm('gbqf').fill_out_and_submit({
'q': 'hello',
})
driver.wait_for_element(id_='resultStats')
-
webdriverwrapper.pytest.conftest.
pytest_report_header
(config)[source]¶ Pytest hook, see
_pytest.hookspec.pytest_report_header()
(Writing plugins).It’s important to see which URL is testing with which user and where are stored screenshots. It will be displayed before run of tests if you set some config values like that:
def pytest_configure(config): config.webdriverwrapper_screenshot_path = os.path.join('/', 'tmp', 'testresults') config.webdriverwrapper_testing_url = 'http://example.com' config.webdriverwrapper_testing_username = 'testing_username'
If your web app does not need any user, just don’t set it.
-
webdriverwrapper.pytest.conftest.
pytest_runtest_makereport
(item, call, __multicall__)[source]¶ Pytest hook, see
_pytest.hookspec.pytest_runtest_makereport()
.After each failed test will be generated screenshot if you specify where to save these screenshots.
def pytest_configure(config): config.webdriverwrapper_screenshot_path = os.path.join('/', 'tmp', 'testresults')
-
webdriverwrapper.pytest.conftest.
driver
(request, _driver)[source]¶ Fixture for testing. This fixture just take your driver by fixture called
_driver
and after each test callcheck_expected_errors()
andcheck_expected_infos()
. You have to just implement creating of your browser.@pytest.yield_fixture(scope='session') def _driver(): driver = Chrome() yield driver driver.quit()
UnitTest¶
-
unittest.
ONE_INSTANCE_FOR_ALL_TESTS
= 0¶
-
unittest.
ONE_INSTANCE_PER_TESTCASE
= 1¶
-
unittest.
ONE_INSTANCE_PER_TEST
= 2¶
-
class
webdriverwrapper.unittest.
WebdriverTestCase
(*args, **kwds)[source]¶ Base
TestCase
used for testing withunittest
.Example:
class TestCase(webdriverwrapper.unittest.WebdriverTestCase): domain = 'www.google.com' instances_of_driver = webdriverwrapper.unittest.ONE_INSTANCE_PER_TESTCASE screenshot_path = os.path.join('/', 'tmp', 'testreport') def _get_driver(self): return Chrome() def test_doodle(self): self.click('gbqfsb') self.assertTrue(self.contains_text('Doodles')) def test_search(self): self.get_elm('gbqf').fill_out_and_submit({ 'q': 'hello', }) self.wait_for_element(id_='resultStats')
-
break_point
()[source]¶ Alias for
break_point()
.
-
check_errors
(expected_error_page=None, allowed_error_pages=[], expected_error_messages=[], allowed_error_messages=[])[source]¶ Alias for
check_errors()
.Changed in version 2.0: Only alias. Code moved to wrapper so it could be used also by pytest.
-
close_other_windows
()[source]¶ Alias for
close_other_windows()
.
-
close_window
(window_name=None, title=None, url=None)[source]¶ Alias for
close_window()
.
-
contains_text
(text)[source]¶ Alias for
contains_text()
.
-
domain
= None¶ If you want working relative
go_to
without having to call for first timeget
(because before that you can’t use relative path), set this attribute.
-
find_element_by_text
(text)[source]¶ Alias for
find_element_by_text()
.New in version 2.0.
-
find_elements_by_text
(text)[source]¶ Alias for
find_elements_by_text()
.
-
get_elms
(*args, **kwds)[source]¶ Alias for
get_elms()
.
-
instances_of_driver
= 0¶ Specify when you want to create fresh driver. By default there is one driver for all tests (
ONE_INSTANCE_FOR_ALL_TESTS
) and you have to close it by yourself by callingquit_driver()
.If you need clear cookies, local storage and everything, then consider to use new driver for every
TestCase
or even every test method.
-
make_screenshot
(screenshot_name=None)[source]¶ Save screenshot to
screenshot_path
with given namescreenshot_name
. If name is not given, then the name is name of current test (self.id()
).Changed in version 2.2: Use
make_screenshot
directly ondriver
instead. This method is used for making screenshot of failed tests and therefor does nothing ifscreenshot_path
is not configured. It stays there only for compatibility.
-
static
quit_driver
()[source]¶ When you set
instances_of_driver
toONE_INSTANCE_FOR_ALL_TESTS
(which is default), then you have to quit driver by yourself by this method.
-
screenshot_path
= ''¶ When you set this path, it will make automatically screenshots of failed tests and saved them to this path.
-
switch_to_window
(window_name=None, title=None, url=None)[source]¶ Alias for
switch_to_window()
.
-
wait_after_test
= False¶ For debug only. When you set to
True
, it will wait for pressing enter after each test before moving to next test. Ideal when you need to check out for example Chrome console.But maybe better debuging is with
break_point()
.
-
Exceptions¶
You doesn’t have to care about some exception. In test result you will get some exception with clear message. But if you need something special or is there some confusion, these are all exceptions defined by this wrapper.
-
exception
webdriverwrapper.exceptions.
ErrorMessagesException
(url, error_messages, expected_error_messages, allowed_error_messages)[source]¶ Exception raised when there is some unexpected error message. Like “some field is mandatory”, “wrong e-mail” and so on.
-
exception
webdriverwrapper.exceptions.
ErrorPageException
(url, error_page, expected_error_page, allowed_error_pages, traceback=None)[source]¶ Exception raised when there is some unexpected error page. Like page 404, 500 and so on.
-
exception
webdriverwrapper.exceptions.
InfoMessagesException
(url, info_messages, expected_info_messages, allowed_info_messages)[source]¶ Exception raised when there is missing some expected info message. Like “sucessfully saved” and so on.
-
exception
webdriverwrapper.exceptions.
JSErrorsException
(url, js_errors)[source]¶ Exception raised when there is some JS error.
See
get_js_errors
for more information.