Welcome to Brome’s documentation!

https://img.shields.io/travis/brome-hq/brome.svg https://img.shields.io/pypi/v/brome.svg Documentation Status

Brome is a Framework for Selenium

Documentation

Installation

Create a virtual env [optional]

Install virtualenv and virtualenvwrapper:

$ pip install virtualenv virtualenvwrapper

Add this line to your .bash_profile:

source /usr/local/bin/virtualenvwrapper.sh

Reload your .bash_profile:

$ source ~/.bash_profile

Create your virtualenv:

$ mkvirtualenv venv

Activate the virtualenv:

$ workon venv

Install brome

$ pip install brome

Configuration

Here is all the configuration options that brome support. You have to provide a yaml configuration file to brome when you create it. This step is already done in the bro executable:

brome = Brome(
    config_path = os.path.join(HERE, "config", "brome.yml"), #<--- this file
    selector_dict = selector_dict,
    test_dict = test_dict,
    browsers_config_path = os.path.join(HERE, "config", "browsers_config.yml"),
    absolute_path = HERE
)

Inside the brome.yml configuration file is a bunch of section with options. You can control the behavior the runner, the proxy driver, the proxy element, put some custom project config, etc... Below is a break down of each of the brome configuration options.

sample configuration file

saucelabs:
  username: ''
  key: ''
browserstack:
  username: ''
  key: ''
browser:
  maximize_window: false
  window_height: 725
  window_width: 1650
  window_x_position: 0
  window_y_position: 0
database:
  sqlalchemy.url: 'sqlite:///unittest.db'
ec2:
  wait_after_instance_launched: 30
  wait_until_system_and_instance_check_performed: true
grid_runner:
  kill_selenium_server: true
  max_running_time: 7200
  selenium_hub_config: '/resources/hub-config.json'
  selenium_server_command: 'java -jar {selenium_server_jar_path} -role hub -hubConfig {selenium_hub_config} -DPOOL_MAX 512 &'
  selenium_server_ip: 'localhost'
  selenium_server_jar_path: '/resources/selenium-server-standalone.jar'
  selenium_server_port: 4444
  start_selenium_server: false
highlight:
  highlight_on_assertion_failure: true
  highlight_on_assertion_success: true
  highlight_when_element_is_clicked: true
  highlight_when_element_is_visible: true
  highlight_when_element_receive_keys: true
  style_on_assertion_failure: 'background: red; border: 2px solid black;'
  style_on_assertion_success: 'background: green; border: 2px solid black;'
  style_when_element_is_clicked: 'background: yellow; border: 2px solid red;'
  style_when_element_is_visible: 'background: purple; border: 2px solid black;'
  style_when_element_receive_keys: 'background: yellow; border: 2px solid red;'
  use_highlight: true
logger_runner:
  filelogger: false
  format: "[%(batchid)s]\e[32m%(message)s\e[0m"
  level: 'INFO'
  streamlogger: true
logger_test:
  filelogger: false
  format: "[%(batchid)s]\e[34m(%(testname)s)\e[0m:\e[32m%(message)s\e\[0m"
  level: 'INFO'
  streamlogger: true
project:
  test_batch_result_path: false
  url: 'http://localhost:7777'
proxy_driver:
  use_javascript_dnd: true
  default_timeout: 5
  intercept_javascript_error: true
  raise_exception: true
  take_screenshot_on_assertion_failure: true
  take_screenshot_on_assertion_success: false
  validate_css_selector: true
  validate_xpath_selector: true
  wait_until_not_present_before_assert_not_present: true
  wait_until_not_visible_before_assert_not_visible: true
  wait_until_present_before_assert_present: true
  wait_until_present_before_find: true
  wait_until_visible_before_assert_visible: true
  wait_until_visible_before_find: true
runner:
  cache_screenshot: true
  embed_on_assertion_failure: false
  embed_on_assertion_success: false
  embed_on_test_crash: false
  play_sound_on_assertion_failure: false
  play_sound_on_assertion_success: false
  play_sound_on_ipython_embed: false
  play_sound_on_pdb: false
  play_sound_on_test_crash: false
  play_sound_on_test_finished: false
  sound_on_assertion_failure: '{testid} failed'
  sound_on_assertion_success: '{testid} succeeded'
  sound_on_ipython_embed: 'Attention required'
  sound_on_pdb: 'Attention required'
  sound_on_test_crash: 'Crash'
  sound_on_test_finished: 'Test finished'
webserver:
  open_browser: false
  ASSETS_DEBUG: true
  CACHE_TYPE: 'simple'
  CLOSED_REGISTRATION: false
  DEBUG: false
  DEBUG_TB_ENABLED: false
  DEBUG_TB_INTERCEPT_REDIRECTS: false
  HOST: 'localhost'
  PORT: 5000
  REGISTRATION_TOKEN: ''
  SECRET_KEY: ''
  SHOW_TEST_INSTANCES: true
  SHOW_VIDEO_CAPTURE: true
  filelogger: false
  level: 'INFO'
  streamlogger: false

project

  • test_batch_result_path: The test path where the test batch result file will be create. If you don’t want to save any file when a test batch run, just set this options to False. str [path] | bool (false only) (default: ‘’)
  • url: The url of the server on which the test run (must include the protocol) e.g.:https://the-internet.herokuapp.com/ str [url] (default: ‘’)

browserstack

  • username: Browserstack username str (default: ‘’)
  • key: Browserstack key str (default: ‘’)

saucelabs

  • username: Saucelabs username str (default: ‘’)
  • key: Saucelabs key str (default: ‘’)

proxy_driver

  • use_javascript_dnd: Use javascript to perform drag and drop. If set to false then the ActionChains.drag_and_drop with be used instead. bool (default: false)
  • wait_until_visible_before_find: If this options is set to true then each time you use the driver.find(selector) the proxy_driver will wait until the element is visible; if the element is not visible before the given timeout then it may wait_until_present(selector), raise an exception or return false. All of this is configurable from the brome.yml or provided to the function find(selector, wait_until_visible = (False | True)) directly via kwargs. bool (default: false)
  • intercept_javascript_error: If set to true this options will execute some javascript code on each driver.get() that will intercept javascript error. bool (default: false)
  • validate_xpath_selector: If set to true the proxy driver will raise an exception if the provided xpath selector is invalid. bool (default: false)
  • validate_css_selector: If set to true the proxy driver will raise an exception if the provided css selector is invalid. bool (default: false)
  • default_timeout: The default timeout in second. This will be used in a lot of the proxy driver function (wait_until_*); you can overwrite this default with the timeout kwargs. int (second) (default: 5)
  • raise_exception: This options tell the brome driver to raise exception on failure (find_*, wait_until_*) or just return a bool instead. bool (default: true)
  • wait_until_present_before_assert_present: Wait until not present before assert present. bool (default: false)
  • wait_until_not_present_before_assert_not_present: Wait until not present before assert not present. bool (default: false)
  • wait_until_not_visible_before_assert_not_visible: Wait until not visible before assert not visible. bool (default: false)
  • wait_until_visible_before_assert_visible: Wait until visible before assert visible. bool (default: false)
  • wait_until_present_before_find: Wait until visible before find. bool (default: false)
  • take_screenshot_on_assertion_success: Take screenshot on assertion success bool (default: false)
  • take_screenshot_on_assertion_failure: Take screenshot on assertion failure bool (default: false)

proxy_element

  • use_touch_instead_of_click: Use touch instead of click. bool (default: false)

browser

  • window_x_position: Window x position. int (default: 0)
  • window_y_position: Window y position. int (default: 0)
  • window_height: Window height. int (default: 725)
  • window_width: Window width. int (default: 1650)
  • maximize_window: Maximize window. Note: this may not work in a xvfb environment; so set the width and height manually in this case. bool (default: false)

highlight

  • highlight_on_assertion_success: Highlight on assertion success. bool (default: false)
  • highlight_on_assertion_failure: Highlight on assertion failure. bool (default: false)
  • highlight_when_element_is_clicked: Highlight when element is clicked. bool (default: false)
  • highlight_when_element_receive_keys: Highlight when element received keys. bool (default: false)
  • highlight_when_element_is_visible: Highlight when element is visible. bool (default: false)
  • style_when_element_is_clicked: Style when element is clicked. str ‘background: yellow; border: 2px solid red;’
  • style_when_element_receive_keys: Style when element receive keys. str ‘background: yellow; border: 2px solid red;’
  • style_on_assertion_failure: Style on assertion failure. str ‘background: red; border: 2px solid black;’
  • style_on_assertion_success: Style on assertion success. str ‘background: green; border: 2px solid black;’
  • style_when_element_is_visible: Style when element is visible. str ‘background: purple; border: 2px solid black;’
  • use_highlight: Use highlight. bool (default: false)

runner

  • embed_on_assertion_success: Embed on assertion success. bool (default: false)
  • embed_on_assertion_failure: Embed on assertion failure. bool (default: false)
  • embed_on_test_crash: Embed on test crash. bool (default: false)
  • play_sound_on_test_crash: Play sound on test crash. bool (default: false)
  • play_sound_on_assertion_success: Play sound on assertion success. bool (default: false)
  • play_sound_on_assertion_failure: Play sound on assertion failure. bool (default: false)
  • play_sound_on_test_finished: Play sound on test batch finished. bool (default: false)
  • play_sound_on_ipython_embed: Play sound on ipython embed. bool (default: false)
  • play_sound_on_pdb: Play sound on pdb. bool (default: false)
  • sound_on_test_crash: Sound on test crash. str Crash
  • sound_on_assertion_success: sound on assertion success. str {testid} succeeded
  • sound_on_assertion_failure: Sound on assertion failure. str {testid} failed
  • sound_on_test_finished: Sound on test batch finished. str Test finished
  • sound_on_ipython_embed: Sound on ipython embed. str Attention required
  • sound_on_pdb: Sound on pdb. str Attention required
  • cache_screenshot: Use the cache screenshot. bool (default: true)

database

  • sqlalchemy.url: the database url str (default: ‘’)

logger_runner

  • level: ‘DEBUG’ | ‘INFO’ | ‘WARNING’ | ‘ERROR’ | ‘CRITICAL’ (default: INFO)
  • streamlogger: The logger with output to the sdtout. bool (default: true)
  • filelogger: The logger with output to a file in the test batch result directory. bool (default: true)
  • format: Logger format. str (default: [%(batchid)s]%(message)s)

logger_test

  • level: ‘DEBUG’ | ‘INFO’ | ‘WARNING’ | ‘ERROR’ | ‘CRITICAL’ (default: INFO)
  • streamlogger: The logger with output to the sdtout. bool (default: true)
  • filelogger: The logger with output to a file in the test batch result directory. bool (default: true)
  • format: Logger format. str (default: [%(batchid)s](%(testname)s):%(message)s)

ec2

  • wait_after_instance_launched: Wait X seconds after the instances are launched. int [second] (default: 30)
  • wait_until_system_and_instance_check_performed: Wait until system and instance checks are performed. bool (default: true)

grid_runner

  • max_running_time: This is the time limit the grid runner can run before raising a TimeoutException. This is to prevent a test batch from running forever using up precious resources. (int [second]) (default: 7200)
  • start_selenium_server: Start selenium server automatically. bool (default: true)
  • selenium_server_ip: Selenium server ip address. str (default: ‘localhost’)
  • selenium_server_port: Selenium port. int (default: 4444)
  • selenium_server_command: Selenium server command. str (default: ‘’)
  • selenium_server_jar_path: Selenium server jar path. str [path] (default: ‘’)
  • selenium_hub_config: Selenium server hub config path. str [path] (default: ‘’)
  • kill_selenium_server: Kill selenium server when the test batch finished. bool (default: true)

webserver

  • open_browser: Open the webserver index in a new tab on start. bool (default: false)
  • level: ‘DEBUG’ | ‘INFO’ | ‘WARNING’ | ‘ERROR’ | ‘CRITICAL’ (default: INFO)
  • streamlogger: The logger with output to the sdtout. bool (default: true)
  • filelogger: The logger with output to a file in the test batch result directory. bool (default: true)
  • CLOSED_REGISTRATION: This options will required the user to enter a token if he want to register in the brome webserver. bool (default: false)
  • REGISTRATION_TOKEN: The token used to register in the brome webserver. str (default: ‘’)
  • HOST: [FLASK CONFIG]
  • PORT: [FLASK CONFIG]
  • DEBUG: [FLASK CONFIG]
  • CACHE_TYPE: [FLASK CONFIG]
  • ASSETS_DEBUG: [FLASK CONFIG]
  • DEBUG_TB_INTERCEPT_REDIRECTS: [FLASK CONFIG]
  • DEBUG_TB_ENABLED: [FLASK CONFIG]
  • SECRET_KEY: [FLASK CONFIG]

Locating Elements

Find methods

Use the proxy_driver (pdriver) to locate element on the web page. Three methods exist:

pdriver.find("sv:selector_variable")

pdriver.find_last("nm:form")

pdriver.find_all("tn:div")

The find method accept three kwargs:

pdriver.find("nm:button", raise_exception = False)

pdriver.find_all("id:1", wait_until_visible = False)

pdriver.find_last("cs:div > span", wait_until_present = False, raise_exception = True)

pdriver.find_all(
    "sv:selector_variable",
    wait_until_visible = True,
    wait_until_present = False,
    raise_exception = True
)

The defaults for the kwargs wait_until_present, wait_until_visible and raise_exception can be set respectively with: * proxy_driver:wait_until_present_before_find * proxy_driver:wait_until_visible_before_find * proxy_driver:raise_exception

The find and find_last method return a proxy_element.

The find_all method return a proxy_element_list.

By id
pdriver.find("id:button-1")
By css selector
pdriver.find("cs:div > span")
By name
pdriver.find("nm:button-1")
By class name
pdriver.find("cn:button")
By tag name
pdriver.find_all("tn:div")
By selector variable
pdriver.find("sv:button_1")

List of selectors

If you want to create a selector from multiple selector you can pass a list of selector to the find_* method:

pdriver.find(["sv:selector_v1", "sv:selector_v2", "xp://*[contains(@class, 'button')]"])

Selectors validation

The xpath and css selector will be validated if the config proxy_driver:validate_xpath_selector and proxy_driver:validate_css_selector are set to true.

Selector variable dictionary

A selector dictionary can be provided to brome:

selector_dict = {}
selector_dict['example_find_by_tag_name'] = "tn:a"
selector_dict['example_find_by_id'] = "id:1"
selector_dict['example_find_by_xpath'] = "xp://*[@class = 'xpath']"
selector_dict['example_find_by_partial_link_text'] = "pl:partial link text"
selector_dict['example_find_by_link_text'] = "lt:link text"
selector_dict['example_find_by_css_selector'] = "cs:.classname"
selector_dict['example_find_by_classname'] = "cn:classname"
selector_dict['example_find_by_name'] = "nm:name"
selector_dict['example_multiple_selector'] = {
    "default" : "xp://*[contains(@class, 'default')]",
    "chrome|iphone|android" : "xp://*[contains(@class, 'special')]"
}

brome = Brome(
    config_path = os.path.join(HERE, "config", "brome.yml"),
    selector_dict = selector_dict, #<--- this dict
    test_dict = test_dict,
    browsers_config_path = os.path.join(HERE, "config", "browsers_config.yml"),
    absolute_path = HERE
)

So later on in your code you can use the selector variable to find elements:

pdriver.find("sv:example_find_by_name")

Also a selector variable can vary from browser to browser:

selector_dict['example_multiple_selector'] = {
    "default" : "xp://*[contains(@class, 'default')]",
    "chrome|iphone|android" : "xp://*[contains(@class, 'special')]"
}

It support the browserName, version and platform returned by the pdriver._driver.capabilities

Plain selenium methods

If you want to use the selenium location methods just use:

pdriver._driver.find_element_by_id
pdriver._driver.find_element_by_name
pdriver._driver.find_element_by_xpath
pdriver._driver.find_element_by_link_text
pdriver._driver.find_element_by_partial_link_text
pdriver._driver.find_element_by_tag_name
pdriver._driver.find_element_by_class_name
pdriver._driver.find_element_by_css_selector
pdriver._driver.find_elements_by_name
pdriver._driver.find_elements_by_xpath
pdriver._driver.find_elements_by_link_text
pdriver._driver.find_elements_by_partial_link_text
pdriver._driver.find_elements_by_tag_name
pdriver._driver.find_elements_by_class_name
pdriver._driver.find_elements_by_css_selector

Note that this will return a selenium webelement and not a proxy_element or proxy_element_list

Waiting For Elements

Waiting methods

Use the proxy_driver (pdriver) to wait for element to be clickable, present, not present, visible or not visible:

pdriver.wait_until_clickable("xp://*[contains(@class, 'button')])

pdriver.wait_until_present("cn:test")

pdriver.wait_until_not_present("sv:submit_button")

pdriver.wait_until_visible("tn:div")

pdriver.wait_until_not_visible("cs:div > span")
Kwargs and config

All the waiting methods accept the two following kwargs:

  • timeout (int) second before a timeout exception is raise
  • raise_exception (bool) raise an exception or return a bool

The config default for these kwargs are respectively:

  • proxy_driver:default_timeout
  • proxy_driver:raise_exception
Examples
pdriver.wait_until_clickable("xp://*[contains(@class, 'button')]", timeout = 30)

pdriver.wait_until_present("cn:test", raise_exception = True)

Not waiting methods

Use the proxy_driver (pdriver) to find out if an element is present or visible:

pdriver.is_visible("xp://*[contains(@class, 'button')])

pdriver.is_present("cn:test")
Examples
if pdriver.is_visible("sv:login_btn'):
    pdriver.find("sv:login_btn").click()

if pdriver.is_present("sv:hidden_field"):
    pdriver.find("sv:username_field").clear()

Interactions

Proxy driver

Get

Same as the selenium get method except that if the config proxy_driver:intercept_javascript_error is set to True then each time you call get it will inject the javascript code to intercept javascript error:

pdriver.get("http://www.example.com")
Inject javascript script

This method will inject the provided javascript script into the current page:

pdriver.inject_js_script("https://code.jquery.com/jquery-2.1.4.min.js")

js_path = os.path.join(
    pdriver.get_config_value("project:absolute_path"),
    "resources",
    "special_module.js"
)
pdriver.inject_js_script(js_path)
Init javascript error interception

This will inject the javascript code responsible of intercepting the javascript error:

self._driver.execute_script("""
    window.jsErrors = [];
    window.onerror = function (errorMessage, url, lineNumber) {
        var message = 'Error: ' + errorMessage;
        window.jsErrors.push(message);
        return false;
    };
""")
Get javascript error

This will return a string or a list of all the gathered javascript error:

pdriver.get_javascript_error(return_type = 'string')

pdriver.get_javascript_error(return_type = 'list')

Note that each time you access the javascript error, the list holding them is reset.

Pdb

This will start a python debugger:

pdriver.pdb()

Note that calling pdb won’t work in a multithread context, so whenever you use the -r switch with the bro executable the pdb call won’t work.

Embed

This will start a ipython embed:

pdriver.embed()

pdriver.embed(title = 'Ipython embed')

Note that calling embed won’t work in a multithread context, so whenever you use the -r switch with the bro executable the embed call won’t work.

Drag and drop

The drag and drop have two implementation: one use javascript; the other use the selenium ActionChains:

pdriver.drag_and_drop("sv:source", "sv:destination", use_javascript_dnd = True)

pdriver.drag_and_drop("sv:source", "sv:destination", use_javascript_dnd = False)

pdriver.drag_and_drop("sv:source", "sv:destination") #use_javascript_dnd will be initialize from the config `proxy_driver:use_javascript_dnd`
Take screenshot

Take a screenshot:

pdriver.get_config_value('runner:cache_screenshot')
>>>True
pdriver.take_screenshot('login screen')
pdriver.take_screenshot('login screen') #won't save any thing to disc

pdriver.get_config_value('runner:cache_screenshot')
>>>False
pdriver.take_screenshot('login screen')
pdriver.take_screenshot('login screen') #first screenshot will be overridden

Note: If the runner:cache_screenshot config is set to True then screenshot sharing all the same name will be saved only once

Proxy element

Click

Click on the element:

pdriver.find("sv:login_button").click()
pdriver.find("sv:login_button").click(highlight = False)
pdriver.find("sv:login_button").click(wait_until_clickable = False)

Note: if the first click raise an exception then another click will be attempt; if the second click also fail then a exception will be raised. If you don’t want this kind of behaviour then you can use the click selenium method instead:

pdriver.find("sv:login_button")._element.click() #plain selenium method
Send keys

Send keys to the element:

pdriver.find("sv:username_input"").send_keys('username')
pdriver.find("sv:username_input"").send_keys('new_username', clear = True)
pdriver.find("sv:username_input"").send_keys('new_username', highlight = False)
pdriver.find("sv:username_input"").send_keys('new_username', wait_until_clickable = False)

Note: if the first send_keys raise an exception then another click will be attempt; if the second send_keys also fail then a exception will be raised. If you don’t want this kind of behaviour then you can use the send_keys selenium method instead:

pdriver.find("sv:login_button")._element.send_keys('username') #plain selenium method
Clear

Clear the element:

pdriver.find("sv:username_input").clear()

Note: if the first clear raise an exception then another clear will be attempt; if the second clear also fail then a exception will be raised. If you don’t want this kind of behaviour then you can use the clear selenium method instead:

pdriver.find("sv:login_button")._element.clear() #plain selenium method
Highlight

Highlight an element:

style = 'background: red; border: 2px solid black;'
pdriver.find("sv:login_button").highlight(style = style, highlight_time = .3)
Scroll into view

Scroll into view where the element is located:

pdriver.find("sv:last_element").scroll_into_view()
Select all

Select all text found in the element:

pdriver.find("sv:title_input").select_all()

Assertion

All assert function return a boolean: True if the assertion succeed; False otherwise.

If you gave a test dictionary to the Brome object in the bro executable then you can give a test id to the assert function so it can save the test result for you:

test_dict = {}
test_dict['#1'] = "The login button is visible"
test_dict['#2'] = {
    'name': 'Test',
    'embed': False
}

brome = Brome(
    config_path = os.path.join(HERE, "config", "brome.yml"),
    selector_dict = selector_dict,
    test_dict = test_dict, # <-- this dict
    browsers_config_path = os.path.join(HERE, "config", "browsers_config.yml"),
    absolute_path = HERE
)

So later in your code you can do this:

pdriver.assert_visible("sv:login_button", '#1')
>>>True

Or if you prefer you can write the test description inline instead:

pdriver.assert_visible("sv:login_button", 'The login button is visible')
>>>True

If you don’t want this assertion to be saved then use the assert function like this:

pdriver.assert_visible("sv:login_button")
>>>True

Assertion function never raise an exception.

The following config affect the fonctionality of assert functions:

  • runner:embed_on_assertion_success
  • runner:embed_on_assertion_failure
  • runner:play_sound_on_assertion_success
  • runner:play_sound_on_assertion_failure
  • proxy_driver:take_screenshot_on_assertion_failure
  • proxy_driver:take_screenshot_on_assertion_success

If you have a bug that won’t be fixed anytime soon and your config runner:embed_on_assertion_failure is set to True then you can change your test_dict like so to stop embed on this particular test:

test_dict['#2'] = {
    'name': 'Test',
    'embed': False
}

Assertion functions

Here is the list of all assert function found in the pdriver:

Assert present

This will assert that the element is present in the dom:

assert_present(selector, "#2")

assert_present(selector, "#2", wait_until_present = False)

assert_present(selector, "#2", wait_until_present = True)
  • The default for the wait_until_present kwargs is proxy_driver:wait_until_present_before_assert_present.
Assert not present

This will assert that the element is not present in the dom:

assert_not_present(selector, "#2")

assert_not_present(selector, "#2", wait_until_not_present = True)

assert_not_present(selector, "#2", wait_until_not_present = False)
  • The default for the wait_until_not_present kwargs is proxy_driver:wait_until_not_present_before_assert_not_present.
Assert visible

This will assert that the element is visible in the dom:

assert_visible(selector, "#2")

assert_visible(selector, "#2", highlight = False)

assert_visible(selector, "#2", wait_until_visible = False)
  • The default for the wait_until_visible kwargs is proxy_driver:wait_until_visible_before_assert_visible.
  • The default for the highlight kwargs is proxy_driver:highlight_on_assertion_success.
  • The highlight style is configurable with the config highlight:style_on_assertion_success.
Assert not visible

This will assert that the element is not visible in the dom:

assert_not_visible(selector, "#2")

assert_not_visible(selector, "#2", highlight = False)

assert_not_visible(selector, "#2", wait_until_not_visible = False)
  • The default for the wait_until_not_visible kwargs is proxy_driver:wait_until_not_visible_before_assert_not_visible.
  • The default for the highlight kwargs is proxy_driver:highlight_on_assertion_failure.
  • The highlight style is configurable with the config highlight:style_on_assertion_failure.
Assert text equal

This will assert that the element’s test is equal to the given value:

assert_text_equal("sv:username_input", "user", "#2")

pdriver.assert_text_equal("sv:username_input", "error", '#2', highlight = False)

pdriver.assert_text_equal("sv:username_input", "error", '#2', wait_until_visible = False)
  • The default for the wait_until_visible kwargs is proxy_driver:wait_until_visible_before_assert_visible.
  • The default for the highlight kwargs is proxy_driver:highlight_on_assertion_success.
  • The highlight style is configurable with the config highlight:style_on_assertion_success.
  • The highlight style is configurable with the config highlight:style_on_assertion_failure.
Assert text not equal

This will assert that the element’s test is not equal to the given value:

pdriver.assert_text_not_equal("sv:username_input", "error", '#2')

pdriver.assert_text_not_equal("sv:username_input", "error", '#2', highlight = False)

pdriver.assert_text_not_equal("sv:username_input", "error", '#2', wait_until_visible = False)
  • The default for the wait_until_visible kwargs is proxy_driver:wait_until_visible_before_assert_visible.
  • The default for the highlight kwargs is proxy_driver:highlight_on_assertion_success.
  • The highlight style is configurable with the config highlight:style_on_assertion_success.
  • The highlight style is configurable with the config highlight:style_on_assertion_failure.

Browsers

Browser config

The brome object need a browser config (yaml). You provide it in the bro executable:

brome = Brome(
    config_path = os.path.join(HERE, "config", "brome.yml"),
    selector_dict = selector_dict,
    test_dict = test_dict,
    browsers_config_path = os.path.join(HERE, "config", "browsers_config.yml"), # <-- this file
    absolute_path = HERE
)

The browser config look something like this:

firefox:
  browserName: 'Firefox'

c:
  browserName: 'Chrome'

So when you want to run a test using firefox you specify it to the bro executable:

$./bro run -l 'firefox'

$./bro run -l 'c'

You can add brome config in the browser config also:

firefox:
  browserName: 'Firefox'
  "highlight:use_highlight": false
  maximize_window: true
  "runner:embed_on_test_crash": true

c:
  browserName: 'Chrome'
  window_height: 950
  window_width: 1550
  "runner:embed_on_test_crash": false

You can override a brome config for a specific browser, for example if the config runner:embed_on_test_crash is set to True in the brome.yml and you wish to not embed_on_test_crash in chrome then you can set “runner:embed_on_test_crash” to false in the browser_config under the chrome section.

Init driver

If you want to change the way the browser is initiliazed then you can do the following:

#/path/to/project/model/basetest.py
from selenium import webdriver

from brome.core.model.basetest import BaseTest as BromeBaseTest
from brome.core.model.proxy_driver import ProxyDriver

class BaseTest(BromeBaseTest):

    def init_driver(self, *args, **kwargs):
        #DO WHATEVER YOU WANT
        driver = Firefox()

        #Make sure that you wrap the selenium driver in the ProxyDriver tho
        return ProxyDriver(
            driver = driver,
            test_instance = self,
            runner = self._runner
        )

#/path/to/project/tests/test_scenario.py
#Make sure that your test inherit from your BaseTest
from model.basetest import BaseTest

class Test(BaseTest):
    pass

You can look at how the brome basetest implement the init_driver (https://github.com/brome-hq/brome/search?utf8=%E2%9C%93&q=init_driver)

Examples

Localhost
Chrome
chrome:
  browserName: 'Chrome'
IE
ie:
  browserName: 'internet explorer'
Firefox
firefox:
  browserName: 'Firefox'
Safari
safari:
  browserName: 'Safari'
PhantomJS
phantomjs:
  browserName: 'PhantomJS'
IOS Simulator
iphone:
  appium: true
  deviceName: 'iPhone 5'
  platformName: 'iOS'
  platformVersion: '9.0'
  browserName: 'Safari'
  nativeWebTap: true
  "proxy_element:use_touch_instead_of_click": true
  udid: ''
Android
android:
  appium: true
  "proxy_element:use_touch_instead_of_click": true
  deviceName: 'Android'
  platformName: 'Android'
  version: '4.2.2'
  browserName: 'chrome'
Remote
EC2
chrome_ec2:
  amiid: ''
  browserName: 'chrome'
  available_in_webserver: True
  hub_ip: '127.0.0.1'
  platform: 'LINUX'
  launch: True
  ssh_key_path: '/path/to/identity.pem'
  terminate: True
  nb_browser_by_instance: 1
  max_number_of_instance: 30
  username: 'ubuntu'
  window_height: 950
  window_width: 1550
  region: 'us-east-1'
  security_group_ids: ['sg-xxxxxxx']
  instance_type: 't2.micro'
  selenium_command: "DISPLAY=:0 nohup java -jar selenium-server.jar -role node -hub http://{hub_ip}:4444/grid/register -browser browserName={browserName},maxInstances={nb_browser_by_instance},platform={platform} > node.log 2>&1 &"
Virtual Box
firefox_vbox:
  browserName: 'firefox'
  available_in_webserver: true
  hub_ip: 'localhost'
  password: ''
  platform: 'LINUX'
  launch: true
  terminate: true
  username: ''
  vbname: 'ubuntu-firefox'
  vbox_type: 'gui' #'headless'
  version: '31.0'
Sauce Labs
chrome_saucelabs:
  saucelabs: True
  platform: "Mac OS X 10.9"
  browserName: "chrome"
  version: "31"
Browserstack
ie_browserstack:
  browserstack: True
  os: 'Windows'
  os_version: 'xp'
  browser: 'IE'
  browser_version: '7.0'

Resources

Conf / Presentation

Features

  • Simple API
  • Highly configurable
  • Runner for Amazon EC2, Saucelabs, Virtualbox, Appium
  • Javascript implementation of select, drag and drop, scroll into view
  • IPython embed on assertion for debugging
  • Video recording of the session
  • Persistent test report
  • Webserver
  • Pdb integration
  • Visual validation (Beta)
  • Test state persistence system
  • Browsermob proxy integration
  • Support mobile easier (e.g.: click use Touch)