54 Commits
Author SHA1 Message Date
keita.oouchi 97635dbe40 Replace old broken badge links with shields.io 2016-03-14 18:10:42 +09:00
keitaoouchi 04cadf52bb modify travis settings 2014-12-13 23:39:41 +09:00
keitaoouchi 70750c9d79 update secure password 2014-12-13 20:17:45 +09:00
keitaoouchi 8988dc48ba stop notifying in successful build 2014-12-13 15:45:27 +09:00
keitaoouchi 63bb5264cd Add slack notification after finishing travis-ci's builds. 2014-12-13 15:30:11 +09:00
keitaoouchi f02cd75c94 Automatically upload to pypi if merged into release/pypi branch. #11 2014-12-13 15:17:58 +09:00
keitaoouchi 5a5c27a19e Add pypi status badges 2014-12-13 12:33:18 +09:00
keitaoouchi c84eaaeef0 version++ 2014-11-13 12:30:53 +09:00
keitaoouchi ab334f1f63 Fix README.rst 2014-11-13 10:40:07 +09:00
keitaoouchi fcedd5ade4 Support py34 2014-11-13 10:40:07 +09:00
keitaoouchi 6dc1990728 Add py34 tests 2014-11-13 10:40:07 +09:00
Keita Oouchi 4c0e888986 Merge pull request #10 from asmundg/x-real-buittons
Look for actual <button>s as well
2014-11-13 09:57:27 +09:00
Åsmund Grammeltvedt 26320ea0d6 Look for actual <button>s as well 2014-11-12 14:40:09 +01:00
Keita Oouchi 4a6671964c Remove current_url 2013-08-06 19:14:38 +09:00
keitaoouchi 510b2c4e94 Fix README.rst 2013-06-19 13:24:04 +09:00
keitaoouchi 2b369072a4 Fix 2013-06-19 13:22:07 +09:00
keitaoouchi ed5b29f280 version++ 2013-06-19 13:16:20 +09:00
keitaoouchi 6218d1865e Add silent mode 2013-06-19 13:16:00 +09:00
keitaoouchi bc6dcaa4ed #8 2013-06-19 13:14:11 +09:00
keitaoouchi 68c2429616 implement #8 and Add some tests 2013-06-19 12:48:48 +09:00
Keita Oouchi 1dc40f610c Merge pull request #7 from kseta/master
Fix typo
2013-05-20 17:47:52 -07:00
Keigo Seta bbe21ab410 Fix typo. 2013-05-19 06:05:15 -06:00
keitaoouchi c114785723 version++ 2013-05-09 21:46:47 +09:00
keitaoouchi c55de045c0 Add Python3 support. 2013-05-09 21:46:35 +09:00
keitaoouchi b594988524 Change deprecated assertions 2013-05-09 18:08:00 +09:00
keitaoouchi e812fb1f12 Add classifiers 2013-05-09 18:07:02 +09:00
keitaoouchi d1566409e3 Fix typo 2013-05-09 17:17:45 +09:00
keitaoouchi e3c6b32a6b Add test requirements 2013-05-09 17:03:11 +09:00
keitaoouchi 1bb4dd1d98 Remove test deps 2013-05-09 17:02:02 +09:00
keitaoouchi 3945c17147 Modify test directory to sub-package 2013-05-09 17:01:30 +09:00
keitaoouchi 14d1dc202a Change script to execute setup.py test 2013-05-09 17:00:16 +09:00
keitaoouchi 5d2c28d1ee Add unittest2 for py26 2013-05-09 15:04:37 +09:00
keitaoouchi 66f1efb313 Reformat codes 2013-05-09 14:58:19 +09:00
keitaoouchi 2a1c7403f0 Reformat codes 2013-05-09 14:57:59 +09:00
keitaoouchi f6e8b40b29 Remove unittest2 2013-05-09 14:57:28 +09:00
keitaoouchi cc33da521e Add .tox 2013-05-09 14:56:34 +09:00
keitaoouchi 8a51b48946 Add py3x tests 2013-05-09 14:56:18 +09:00
keitaoouchi ce9da9cdcf Add tox config 2013-05-09 14:56:03 +09:00
keitaoouchi ddaf7441cc version++ 2013-01-16 16:39:25 +09:00
keitaoouchi a5f64e9abc Modify Recent Change 2013-01-16 16:39:14 +09:00
keitaoouchi 38ebf2613b Add new properties 2013-01-16 16:37:49 +09:00
keitaoouchi 394f096dab Add supported drivers 2013-01-08 18:58:59 +09:00
keitaoouchi 3707d9f0bf Require selenium>=2.28.0 for PhantomJS support. 2013-01-08 18:39:08 +09:00
keitaoouchi 433b8db2d4 Add PhantomJS Support 2013-01-08 18:37:03 +09:00
keitaoouchi 1339b9c95d Change polling intervals 2013-01-08 18:24:59 +09:00
Keita Oouchi f6a3e91c3f Revised docs 2012-10-08 21:31:06 +09:00
Keita Oouchi 4997a316c1 Fix #4 2012-10-08 21:15:48 +09:00
Keita Oouchi a9ce4718c2 Remove jquery support docs 2012-09-13 23:16:41 +09:00
keitaoouchi ad17ce2f4b Delete jquery support 2012-09-13 18:15:49 +09:00
keitaoouchi dc23020b90 version 0.3.5 => 0.4.0 2012-09-13 16:44:38 +09:00
keitaoouchi 86ff1e7046 ignore PyCharm 2012-09-13 16:43:50 +09:00
keitaoouchi c2e6ea051c Add syntax sugar to javascript's scroll methods 2012-09-13 16:43:05 +09:00
Keita Oouchi 04ee72be9c Add attr shortcut 2012-07-27 22:35:11 +09:00
Johannes c464ab2e59 Fixed some typos in exception texts 2012-07-26 15:44:34 +02:00
10 changed files with 483 additions and 200 deletions
+2
View File
@@ -6,3 +6,5 @@ chromedriver.log
build/
dist/
*.egg-info
.idea
.tox
+24 -5
View File
@@ -1,9 +1,28 @@
language: python
python:
- "2.6"
- "2.7"
- '2.6'
- '2.7'
- '3.2'
- '3.3'
- '3.4'
install:
- pip install -r requirements.txt --use-mirrors
- pip install -e . --use-mirrors
- pip install -r requirements.txt --use-mirrors
- pip install -e . --use-mirrors
script:
- nosetests
- python setup.py test
deploy:
provider: pypi
user: Keita
password:
secure: d5aCVLkhV/uh+/Mr/c398KmA3DVgx6TAO9HYAsDiLbzh1JQO4jsOEQ4TSrosFV2dlolDuLaXu6tHzzeoUKg8BO2wF9pTwbhoo21+Xr5CHd3bAx4WTPvC8POEByVur8sJC1lD45VR0A2sPJMppi9778dgIZpvowE8sANlvv3iztU=
on:
repo: keitaoouchi/seleniumwrapper
branch: release/pypi
distributions: sdist --formats=gztar,zip
python: 3.4
allow_failure: false
notifications:
slack:
secure: mRFzPF4qQzRfHCS9rYEKpUI9w5wvyv4AO8AVuzvwU1rExKokdl6jcxsMEYlOvozqztfjY7YSN3hm/KV60UiPBtbuox54GrvkCu/qqfx6tFRc1aS+5JclGvOGrrRyzodCIDJEuayiZIrzUSMwcwRInd+N1atpJUKoa9AgyVn+e0o=
on_success: change
on_failure: change
+91 -43
View File
@@ -3,10 +3,23 @@ About this module
selenium webdriver wrapper to make manipulation easier.
.. image:: https://secure.travis-ci.org/keitaoouchi/seleniumwrapper.png
.. image:: https://img.shields.io/pypi/dm/seleniumwrapper.svg
:target: https://pypi.python.org/pypi//seleniumwrapper/
:alt: Downloads
.. image:: https://img.shields.io/pypi/v/seleniumwrapper.svg
:target: https://pypi.python.org/pypi/seleniumwrapper/
:alt: Latest Version
.. image:: https://img.shields.io/pypi/pyversions/seleniumwrapper.svg
:target: https://pypi.python.org/pypi/seleniumwrapper/
:alt: Supported Python versions
.. image:: https://img.shields.io/pypi/l/seleniumwrapper.svg
:target: https://pypi.python.org/pypi/seleniumwrapper/
:alt: License
Features
--------
* Support Internet Explorer, Chrome, Opera, Firefox, PhantomJS
* Support remote webdriver.
* Easy to type aliases. (find_element_by_xpath => xpath, etc.)
* Wrapped WebdriverWait( ... ).until( ... ) pattern.
@@ -15,7 +28,7 @@ Features
How to install
--------------
Requires python2.6 or later (exclude python3.x).
Requires python2.6 or later.
You need *pip* or *distribute* or *setuptools*::
$ pip install seleniumwrapper
@@ -60,25 +73,10 @@ Each contents in SeleniumContainerWrapper also SeleniumWrapper::
>>> tds = [tr.xpath("//td", eager=True) for tr in br.xpath("//tr", eager=True)]
If current page already load jquery.js, you can find elements by JQuery selector::
>>> buttons = br.jquery('#hoge .fuga li:even')
If current page doesn't load jquery, you can load your local jquery by hand::
>>> br.load_js("/path/to/your/local/jquery.js")
or::
>>> br.load_js(StringIO.StringIO("/path/to/your/local/jquery.js")
You can execute javascript by invoking **script** method::
>>> br.script('alert("hoge")')
Basic API
---------
* seleniumwrapper.create(drivername)
* seleniumwrapper.connect(drivername, executor, custom_capabilities)
Create webdriver instance and wrap it with SeleniumWrapper.
SeleniumWrapper
@@ -94,6 +92,15 @@ SeleniumWrapper
>>> price = br.by_tag("th", "Price").parent.by_tag("td").text
* performance
Returns window.performance wrapped object::
>>> performance = br.performance
>>> timing = performance.timing
>>> navigation = performance.navigation
>>> timing.loadEventEnd
1358319427476
* to_select
Convert wrapped WebElement to raw Select object::
@@ -101,7 +108,7 @@ SeleniumWrapper
select method returns the same as below::
>>> br.select(id = 'select_button).select_by_visible_text("hoge")
>>> br.select(id = 'select_button').select_by_visible_text("hoge")
* alert
Returns Alert(switch_to_alert()) object::
@@ -114,7 +121,7 @@ SeleniumWrapper
>>> br.current_url
* timeout
Accessor for _timeout property.
Accessor for _timeout property::
>>> br.timeout
5
@@ -122,25 +129,47 @@ SeleniumWrapper
>>> br.timeout
10
* silent
Accessor for _silent property::
# default
>>> br.by_id("Hoge")
Traceback (most recent call last):
...
NoSuchElementException:...
>>> br.silent = True
>>> br.by_id("Hoge") is None
True
* attr(name)
Shortcut to get_attribute::
>>> br.attr('href')
* click(timeout=3, presleep=0, postsleep=0)
Continue to polling until timeout or element is displayed and clickable::
>>> br.button("Send").click()
* load_js(path_or_file)
Load javascript from /path/to/file or file like object that responds to 'read' method::
* scroll_to(x, y)
equivalent to javascript's scrollTo::
>>> br.load_js("/path/to/jquery.js")
>>> br.scrollTo(0, 100)
* jquery(target)
Find elements by jquery selector::
* scroll_by(x, y)
equivalent to javascript's scrollBy::
>>> br.jquery('#hoge .fuga li:even')
>>> br.scrollBy(10, 10)
* script(javascript)
Execute given javascript::
* scroll_into_view(jq_identifier, align_with_top=True)
find elements by jq_identifier and retrieve its first element and invoke scrollIntoView to it::
>>> br.script('alert("hoge")')
>>> var element = $('#hoge');
>>> element && element.scrollIntoView(true)
second argument is passed as javascript's boolean to scrollIntoView::
>>> br.scrollIntoView('#hoge', False)
* waitfor(type, target, eager=False, timeout=3)
See source::
@@ -198,7 +227,7 @@ SeleniumWrapper
>>> br.img(alt="I am sorry", ext="sorry.gif")
* button(value, eager=False, timeout=3)
find_element_by_xpath("//input[@type='submit' or @type='button' and @value='{}']".format(value), timeout)::
find_element_by_xpath("//input[@type='submit' or @type='button' and @value='{0}']|.//button[text()='{0}']".format(value), timeout)::
>>> br.button("Send this form").click()
@@ -238,28 +267,47 @@ SeleniumContainerWrapper
Recent Change
-------------
* 0.5.4
* Add support for Python-3.4.
* Fix **button** to look for `<button>` tag.
* 0.5.3
* Fix README
* 0.5.2
* Add silent mode option.
* 0.5.0
* Support Python3.
* 0.4.3
* Add **perfomance**, **performance.timing**, **performance.navigation**, **performance.memory** properties.
* 0.4.2
* Add 'PhantomJS' support.
* 0.4.1
* Fixed some bugs.
* 0.4.0
* Added **scroll_to**, **scroll_by**, **scroll_into_view** methods.
* 0.3.5
* Added **attr** method.
* Fixed some typos.
* 0.3.4
* Add javascript support(**load_js**, **jquery**, **script** methods). -- *UNSTABLE* --
* Add size property to SeleniumContainerWrapper
* Added size property to SeleniumContainerWrapper
* Fixed to be able to change default timeout.
* 0.3.3
* Fixed bugs of string formatting.
* 0.3.2
* Change **alert** to wait until Alert's text is accesible.
* Changed **alert** to wait until Alert's text is accesible.
* Override **current_url** to wait for page body loaded.
* 0.3.1
* Add **connect** functon.
* Added **connect** functon.
* 0.3.0
* Change **tag** method to **by_tag**.
* Add **checkbox**, **radio**.
* Change **select** property to method.
* Add **sample**, **choice** methods to SeleniumContainerWrapper.
* Fix **click** bug.
* Changed **tag** method to **by_tag**.
* Added **checkbox**, **radio**.
* Changed **select** property to method.
* Added **sample**, **choice** methods to SeleniumContainerWrapper.
* Fixed **click** bug.
* 0.2.4
* Fix bug.
* Fixed bug.
* 0.2.3
* Add ext argument to **img** (alt and ext are both optional.)
* Added ext argument to **img** (alt and ext are both optional.)
* 0.2.2
* Add new property **alert**
* Change **img**'s argument from ext to alt( find_element_by_xpath("//img[@alt='{}'.format(alt)) )
* Modify SeleniumContainerWrapper's __contains__ behavior to unwrap given object if it is a SeleniumWrapper.
* Added new property **alert**
* Changed **img**'s argument from ext to alt( find_element_by_xpath("//img[@alt='{}'.format(alt)) )
* Modified SeleniumContainerWrapper's __contains__ behavior to unwrap given object if it is a SeleniumWrapper.
+1 -3
View File
@@ -1,3 +1 @@
nose
unittest2
mock
selenium>=2.32.0
+19 -8
View File
@@ -1,10 +1,12 @@
from setuptools import setup
from sys import version
if version < '2.6.0':
raise Exception("This module doesn't support any version less than 2.6")
import sys
sys.path.append("./test")
with open('README.rst', 'r') as f:
@@ -17,25 +19,34 @@ classifiers = [
'Operating System :: OS Independent',
"Programming Language :: Python",
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Topic :: Software Development :: Libraries :: Python Modules'
]
requires = ['selenium>=2.22.1']
requires = ['selenium>=2.44.0']
tests_requires = ['mock', 'nose']
if version < '2.7.0':
tests_requires.append('unittest2')
setup(
author='Keita Oouchi',
author_email='keita.oouchi@gmail.com',
url = 'https://github.com/keitaoouchi/seleniumwrapper',
name = 'seleniumwrapper',
version = '0.3.4',
package_dir={"":"src"},
packages = ['seleniumwrapper'],
test_suite = "test_seleniumwrapper.suite",
url='https://github.com/keitaoouchi/seleniumwrapper',
name='seleniumwrapper',
version='0.5.4',
package_dir={"": "src"},
packages=['seleniumwrapper'],
license='BSD License',
classifiers=classifiers,
description = 'selenium webdriver wrapper to make manipulation easier.',
description='selenium webdriver wrapper to make manipulation easier.',
long_description=long_description,
install_requires=requires,
tests_require=tests_requires,
test_suite='test'
)
+199 -93
View File
@@ -1,12 +1,11 @@
# -*- coding: utf-8 -*-
import os
import collections
import inspect
import time
import random
import selenium
from selenium.webdriver import Ie, Opera, Chrome, Firefox
from selenium.webdriver import Ie, Opera, Chrome, Firefox, PhantomJS
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.ui import WebDriverWait
@@ -16,6 +15,7 @@ from selenium.common.exceptions import (NoSuchElementException, TimeoutException
NoAlertPresentException)
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
def create(drivername, *args, **kwargs):
if not isinstance(drivername, str):
msg = "drivername should be an instance of string. given {0}".format(type(drivername))
@@ -23,7 +23,8 @@ def create(drivername, *args, **kwargs):
drivers = {'ie': Ie,
'opera': Opera,
'chrome': Chrome,
'firefox': Firefox}
'firefox': Firefox,
'phantomjs': PhantomJS}
dname = drivername.lower()
if dname in drivers:
try:
@@ -31,9 +32,11 @@ def create(drivername, *args, **kwargs):
except Exception as e:
raise e
else:
msg = "drivername should be one of [IE, Opera, Chrome, Firefox](case-insentive). given {0}".format(drivername)
msg = "".join(("drivername should be one of [IE, Opera, Chrome, Firefox, PhantomJS]",
"(case-insentive). given {0}".format(drivername)))
raise ValueError(msg)
def connect(drivername, executor, custom_capabilities=None, **kwargs):
if not isinstance(drivername, str):
msg = "drivername should be an instance of string. given {0}".format(type(drivername))
@@ -48,10 +51,11 @@ def connect(drivername, executor, custom_capabilities=None, **kwargs):
'opera': DesiredCapabilities.OPERA,
'chrome': DesiredCapabilities.CHROME,
'firefox': DesiredCapabilities.FIREFOX,
'android': DesiredCapabilities.ANDROID}
'android': DesiredCapabilities.ANDROID,
'phatomjs': DesiredCapabilities.PHANTOMJS}
dname = drivername.lower()
if dname in capabilities:
capability = capabilities[drivername]
capability = capabilities[dname]
custom_capabilities = custom_capabilities or {}
for key in custom_capabilities:
capability[key] = custom_capabilities[key]
@@ -61,15 +65,18 @@ def connect(drivername, executor, custom_capabilities=None, **kwargs):
except Exception as e:
raise e
else:
msg = "drivername should be one of [IE, Opera, Chrome, Firefox](case-insentive). given {0}".format(drivername)
msg = "".join(("drivername should be one of [IE, Opera, Chrome, Firefox, PhantomJS]",
"(case-insentive). given {0}".format(drivername)))
raise ValueError(msg)
def _is_wrappable(obj):
if isinstance(obj, WebDriver) or isinstance(obj, WebElement):
return True
else:
return False
def _chainreact(__getattr__):
def containment(*methodname):
def wrap_or_else(obj):
@@ -77,35 +84,126 @@ def _chainreact(__getattr__):
return SeleniumWrapper(obj)
else:
return obj
self, methodobj = __getattr__(*methodname)
if inspect.isroutine(methodobj):
def reaction(*realargs):
result = methodobj(*realargs)
# for side-effective method(append, ...)
result = result if result is not None else self
return wrap_or_else(result)
return reaction
else:
return wrap_or_else(methodobj)
return containment
class SeleniumWrapper(object):
def __init__(self, driver):
class Performance(object):
def __init__(self, performance):
if not isinstance(performance, dict):
raise AttributeError('Wrapped performance object should be an instance of dict.')
self._performance = performance
@property
def memory(self):
if 'memory' in self._performance:
return Memory(self._performance['memory'])
raise AttributeError('window.performance.memory is not supported in this browser.')
@property
def navigation(self):
if 'navigation' in self._performance:
return Navigation(self._performance['navigation'])
raise AttributeError('window.performance.navigation is not supported in this browser.')
@property
def timing(self):
if 'timing' in self._performance:
return Timing(self._performance['timing'])
raise AttributeError('window.performance.timing is not supported in this browser.')
class Memory(object):
def __init__(self, memory):
self._memory = memory
def __getattr__(self, name):
return self._memory[name]
@property
def __dict__(self):
return self._memory
def __iter__(self):
return iter(self._memory)
class Navigation(object):
def __init__(self, navigation):
self._navigation = navigation
def __getattr__(self, name):
return self._navigation[name]
@property
def __dict__(self):
return self._navigation
def __iter__(self):
return iter(self._navigation)
class Timing(object):
def __init__(self, timing):
self._timing = timing
def __getattr__(self, name):
return self._timing[name]
@property
def __dict__(self):
return self._timing
def __iter__(self):
return iter(self._timing)
class SeleniumWrapper(object):
def __init__(self, driver, timeout=5, silent=False):
if _is_wrappable(driver):
self._driver = driver
self._timeout = 5
self._wrapped = driver
self._timeout = timeout
self._silent = silent
else:
msg = "2nd argument should be an instance of WebDriver or WebElement. given {0}.".format(type(driver))
raise TypeError(msg)
@property
def unwrap(self):
return self._driver
return self._wrapped
@property
def performance(self):
if isinstance(self._wrapped, WebDriver):
if self._wrapped.execute_script("return 'performance' in window;"):
timeout = time.time() + 120
script = "return window.performance.timing.loadEventEnd;"
executor = self._wrapped.execute_script
while time.time() < timeout and not executor(script):
time.sleep(0.2)
if not executor(script):
raise Exception('Timeout!')
performance = self._wrapped.execute_script('return window.performance;')
return Performance(performance)
else:
raise AttributeError("This browser is not supporting Timing APIs.")
else:
raise AttributeError("'WebElement' object has not attribute 'performance'")
@property
def parent(self):
if isinstance(self._driver, WebElement):
if isinstance(self._wrapped, WebElement):
return self.xpath("./parent::node()", timeout=self._timeout)
else:
raise AttributeError("'WebDriver' object has no attribute 'parent'")
@@ -121,7 +219,7 @@ class SeleniumWrapper(object):
timeout = time.time() + self._timeout
while time.time() < timeout:
try:
alert = self._driver.switch_to_alert()
alert = self._wrapped.switch_to_alert()
alert.text
return alert
except NoAlertPresentException:
@@ -130,35 +228,40 @@ class SeleniumWrapper(object):
raise NoAlertPresentException(msg)
def _settimeout(self, timeout):
if isinstance(timeout, int):
if isinstance(timeout, (int, float)):
self._timeout = timeout
else:
raise AttributeError('int please.')
raise AttributeError
def _gettimeout(self):
return self._timeout
timeout = property(_gettimeout, _settimeout)
@property
def silent(self):
return self._silent
@silent.setter
def silent(self, true_of_false):
if not isinstance(true_of_false, bool):
raise AttributeError
self._silent = true_of_false
def __getattribute__(self, name):
return object.__getattribute__(self, name)
@_chainreact
def __getattr__(self, name):
return self._driver, getattr(self._driver, name)
@property
def current_url(self):
self.by_tag("body", self._timeout)
return self._driver.current_url
return self._wrapped, getattr(self._wrapped, name)
def _is_selectable(self):
return self.unwrap.tag_name == 'select'
def _is_stopping(self, interval):
before = (self._driver.location['x'], self._driver.location['y'])
before = (self._wrapped.location['x'], self._wrapped.location['y'])
time.sleep(interval)
after = (self._driver.location['x'], self._driver.location['y'])
after = (self._wrapped.location['x'], self._wrapped.location['y'])
return before[0] == after[0] and before[1] == after[1]
def _wait_until_stopping(self, timeout, interval):
@@ -169,36 +272,36 @@ class SeleniumWrapper(object):
else:
time.sleep(interval)
if not self._is_stopping(interval):
raise WebDriverException("Element is not stably displayed for {sec} seconds.".format(sec=timeout))
raise WebDriverException("Element was not stably displayed for {sec} seconds.".format(sec=timeout))
def _wait_until_clickable(self, timeout, interval):
err_messages = []
endtime = time.time() + timeout
while True:
try:
self._driver.click()
self._wrapped.click()
break
except WebDriverException as e:
err_messages.append(e.msg.split(":")[-1].strip())
time.sleep(interval)
if (time.time() > endtime):
if err_messages:
template = ("Wait for elemtent to be clickable for {sec} seconds, ",
template = ("Waited for element to be clickable for {sec} seconds, ",
"but clicked other elements. {err}")
msg = "".join(template).format(sec=timeout, err=err_messages)
raise WebDriverException(msg)
def _wait_until_displayed(self, timeout, interval):
try:
WebDriverWait(self._driver, timeout, interval).until(lambda d: d.is_displayed())
WebDriverWait(self._wrapped, timeout, interval).until(lambda d: d.is_displayed())
except TimeoutException:
template = ("Wait for elemtent to be displayed for {sec} seconds, ",
template = ("Waited for element to be displayed for {sec} seconds, ",
"but <{target} ...> was not displayed:: <{dumped}>")
msg = "".join(template).format(sec=timeout, target=self._driver.tag_name, dumped=self._dump())
msg = "".join(template).format(sec=timeout, target=self._wrapped.tag_name, dumped=self._dump())
raise ElementNotVisibleException(msg)
def _dump(self):
element = self._driver
element = self._wrapped
info = {"visibility": element.value_of_css_property("visibility"),
"display": element.value_of_css_property("display"),
"height": element.value_of_css_property("height"),
@@ -208,87 +311,86 @@ class SeleniumWrapper(object):
dumped = " ".join(["{k}:{v}".format(k=k, v=info[k]) for k in info])
return dumped
def attr(self, name):
if isinstance(self._wrapped, WebElement):
return self._wrapped.get_attribute(name)
else:
raise AttributeError("This is WebDriver wrapped object.")
def click(self, timeout=None, presleep=0, postsleep=0):
timeout = timeout or self._timeout
if isinstance(self._driver, WebElement):
if isinstance(self._wrapped, WebElement):
try:
if presleep:
time.sleep(presleep)
self._wait_until_stopping(timeout, 0.1)
self._wait_until_displayed(timeout, 0.3)
self._wait_until_clickable(timeout, 0.3)
self._wait_until_stopping(timeout, 0.01)
self._wait_until_displayed(timeout, 0.01)
self._wait_until_clickable(timeout, 0.01)
if postsleep:
time.sleep(postsleep)
except Exception as e:
raise e
def load_js(self, path_or_file):
"""Load javascript from /path/to/file or file like object that responds to 'read' method."""
if isinstance(path_or_file, str) and os.path.isfile(path_or_file):
with open(path_or_file, 'r') as f:
library = f.read()
self._driver.execute_script(library)
elif hasattr(path_or_file, 'read'):
library = path_or_file.read()
self._driver.execute_script(library)
def scroll_to(self, x, y):
if isinstance(self._wrapped, WebDriver):
return self._wrapped.execute_script("window.scrollTo({:d}, {:d})".format(x, y))
else:
raise AttributeError('Given argument is not both file or /path/to/file:: {0}'.format(str(path_or_file)))
raise AttributeError("This is WebElement wrapped object.")
def jquery(self, target):
"""Returns SeleniumContainerWrapper if any elements is found."""
script = 'return $("{0}")'.format(target)
result = self._driver.execute_script(script)
if result:
if isinstance(result, collections.Sequence):
return SeleniumContainerWrapper(result)
else:
return SeleniumWrapper(result)
def scroll_by(self, x, y):
if isinstance(self._wrapped, WebDriver):
return self._wrapped.execute_script("window.scrollBy({:d}, {:d})".format(x, y))
else:
raise NoSuchElementException("Target {0} not found.".format(target))
raise AttributeError("This is WebElement wrapped object.")
def script(self, javascript, *args):
"""Synchronously execute given javascript."""
result = self._driver.execute_script(javascript, *args)
if result:
if isinstance(result, collections.Sequence):
return SeleniumContainerWrapper(result)
def scroll_into_view(self, jq_identifier, align_with_top=True):
if isinstance(self._wrapped, WebDriver):
if self._wrapped.execute_script("try{return $;}catch(e){}"):
script_template = "try{{$('{0}') && $('{0}')[0].scrollIntoView({1})}}catch(e){{}}"
script = script_template.format(jq_identifier, 'true' if align_with_top else 'false')
self._wrapped.execute_script(script)
else:
return SeleniumWrapper(result)
raise AttributeError("You must load jquery library.")
else:
raise AttributeError("This is WebElement wrapped object.")
def waitfor(self, type, target, eager=False, timeout=None):
timeout = timeout or self._timeout
if eager:
types = {"id":lambda d: d.find_elements_by_id(target),
"name":lambda d: d.find_elements_by_name(target),
"xpath":lambda d: d.find_elements_by_xpath(target),
"link_text":lambda d: d.find_elements_by_link_text(target),
"partial_link_text":lambda d: d.find_elements_by_partial_link_text(target),
"tag":lambda d: d.find_elements_by_tag_name(target),
"class":lambda d: d.find_elements_by_class_name(target),
"css":lambda d: d.find_elements_by_css_selector(target), }
types = {"id": lambda d: d.find_elements_by_id(target),
"name": lambda d: d.find_elements_by_name(target),
"xpath": lambda d: d.find_elements_by_xpath(target),
"link_text": lambda d: d.find_elements_by_link_text(target),
"partial_link_text": lambda d: d.find_elements_by_partial_link_text(target),
"tag": lambda d: d.find_elements_by_tag_name(target),
"class": lambda d: d.find_elements_by_class_name(target),
"css": lambda d: d.find_elements_by_css_selector(target), }
else:
types = {"id":lambda d: d.find_element_by_id(target),
"name":lambda d: d.find_element_by_name(target),
"xpath":lambda d: d.find_element_by_xpath(target),
"link_text":lambda d: d.find_element_by_link_text(target),
"partial_link_text":lambda d: d.find_element_by_partial_link_text(target),
"tag":lambda d: d.find_element_by_tag_name(target),
"class":lambda d: d.find_element_by_class_name(target),
"css":lambda d: d.find_element_by_css_selector(target), }
types = {"id": lambda d: d.find_element_by_id(target),
"name": lambda d: d.find_element_by_name(target),
"xpath": lambda d: d.find_element_by_xpath(target),
"link_text": lambda d: d.find_element_by_link_text(target),
"partial_link_text": lambda d: d.find_element_by_partial_link_text(target),
"tag": lambda d: d.find_element_by_tag_name(target),
"class": lambda d: d.find_element_by_class_name(target),
"css": lambda d: d.find_element_by_css_selector(target), }
finder = types[type]
try:
result = WebDriverWait(self._driver, timeout).until(finder)
result = WebDriverWait(self._wrapped, timeout).until(finder)
if eager and len(result):
return SeleniumContainerWrapper(result)
return SeleniumContainerWrapper(result, self.timeout, self.silent)
elif _is_wrappable(result):
return SeleniumWrapper(result)
return SeleniumWrapper(result, self.timeout, self.silent)
else:
return result
except TimeoutException:
template = ("Wait for elemtent to appear for {sec} seconds, ",
"but {type}:{target} didn't appear.")
msg = "".join(template).format(sec=timeout, type=type, target=target)
raise NoSuchElementException(msg)
if self.silent:
return None
else:
template = ("Waited for element to appear for {sec} seconds, ",
"but {type}:{target} didn't appear.")
msg = "".join(template).format(sec=timeout, type=type, target=target)
raise NoSuchElementException(msg)
def xpath(self, target, eager=False, timeout=None):
return self.waitfor("xpath", target, eager, timeout)
@@ -338,7 +440,9 @@ class SeleniumWrapper(object):
return self.xpath(xpath, eager, timeout)
def button(self, value, eager=False, timeout=None):
return self.xpath(".//input[@type='submit' or @type='button' and @value='{0}']".format(value), eager, timeout)
return self.xpath(
".//input[@type='submit' or @type='button' and @value='{0}']"
"|.//button[text()='{0}']".format(value), eager, timeout)
def checkbox(self, eager=False, timeout=None, **attributes):
attributes["type"] = "checkbox"
@@ -357,18 +461,20 @@ class SeleniumWrapper(object):
selected._iterable = [Select(element) for element in iterable if element.tag_name == 'select']
return selected
else:
template = ("Wait for elemtent to appear for {sec} seconds, ",
template = ("Waited for element to appear for {sec} seconds, ",
"but select:{attr} didn't appear.")
msg = "".join(template).format(sec=timeout, attr=attributes)
raise NoSuchElementException(msg)
class SeleniumContainerWrapper(object):
def __init__(self, iterable):
class SeleniumContainerWrapper(object):
def __init__(self, iterable, timeout=5, silent=False):
if not isinstance(iterable, collections.Sequence):
msg = "2nd argument should be an instance of collections.Sequence. given {0}".format(type(iterable))
raise TypeError(msg)
self._iterable = iterable
self._timeout = timeout
self._silent = silent
@_chainreact
def __getattr__(self, name):
@@ -378,7 +484,7 @@ class SeleniumContainerWrapper(object):
def __getitem__(self, key):
obj = self._iterable[key]
if _is_wrappable(obj):
return SeleniumWrapper(obj)
return SeleniumWrapper(obj, self._timeout, self._silent)
return obj
def __len__(self):
@@ -395,12 +501,12 @@ class SeleniumContainerWrapper(object):
def sample(self, size):
picked = random.sample(self._iterable, size)
if isinstance(picked, collections.Sequence):
return SeleniumContainerWrapper(picked)
return SeleniumContainerWrapper(picked, self._timeout, self._silent)
return picked
def choice(self):
picked = random.choice(self._iterable)
if _is_wrappable(picked):
return SeleniumWrapper(picked)
return SeleniumWrapper(picked, self._timeout, self._silent)
else:
return picked
+1
View File
@@ -0,0 +1 @@
+18 -8
View File
@@ -1,4 +1,5 @@
import sys
sys.path.append("./../src")
if sys.version < '2.7':
import unittest2 as unittest
@@ -6,13 +7,12 @@ else:
import unittest
import collections
import mock
import selenium
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.remote.webelement import WebElement
from seleniumwrapper.wrapper import SeleniumWrapper, SeleniumContainerWrapper
class TestSeleniumContainerWrapper(unittest.TestCase):
class TestSeleniumContainerWrapper(unittest.TestCase):
def test_container_raise_if_given_argument_is_not_an_instance_of_Sequence(self):
containment = 1
self.assertNotIsInstance(containment, collections.Sequence)
@@ -27,9 +27,9 @@ class TestSeleniumContainerWrapper(unittest.TestCase):
container = SeleniumContainerWrapper([])
container.append(1)
container.append(1)
self.assertEquals(container.count(1), 2)
self.assertEquals(container.pop(), 1)
self.assertEquals(container.count(1), 1)
self.assertEqual(container.count(1), 2)
self.assertEqual(container.pop(), 1)
self.assertEqual(container.count(1), 1)
def test_container_should_return_wrapped_object_if_possible(self):
mock1 = mock.Mock(WebDriver)
@@ -65,14 +65,14 @@ class TestSeleniumContainerWrapper(unittest.TestCase):
mock2 = mock.Mock(WebElement)
iterable = [mock1, mock2]
container = SeleniumContainerWrapper(iterable)
self.assertEquals(len(container), 2)
self.assertEqual(len(container), 2)
def test_container_has_size_property(self):
mock1 = mock.Mock(WebDriver)
mock2 = mock.Mock(WebElement)
iterable = [mock1, mock2]
container = SeleniumContainerWrapper(iterable)
self.assertEquals(container.size, 2)
self.assertEqual(container.size, 2)
def test_container_support__contains__protocol(self):
mock1 = mock.Mock(WebDriver)
@@ -93,7 +93,7 @@ class TestSeleniumContainerWrapper(unittest.TestCase):
container = SeleniumContainerWrapper(iterable)
sampled = container.sample(5)
self.assertTrue(isinstance(sampled, SeleniumContainerWrapper))
self.assertEquals(len(sampled), 5)
self.assertEqual(len(sampled), 5)
for sample in sampled:
self.assertTrue(sample in container)
@@ -104,11 +104,21 @@ class TestSeleniumContainerWrapper(unittest.TestCase):
self.assertTrue(isinstance(picked, SeleniumWrapper))
self.assertTrue(picked in container)
def test_contained_object_inherits_option_properties_from_container(self):
iterable = [mock.Mock(WebElement) for i in range(5)]
container = SeleniumContainerWrapper(iterable, 1, True)
for contained in container:
self.assertEqual(contained.timeout, 1)
self.assertTrue(contained.silent)
self.assertEqual(container[-1].timeout, 1)
self.assertTrue(container[-1].silent)
def suite():
suite = unittest.TestSuite()
suite.addTests(unittest.makeSuite(TestSeleniumContainerWrapper))
return suite
if __name__ == "__main__":
s = suite()
unittest.TextTestRunner(verbosity=2).run(s)
+93 -40
View File
@@ -1,21 +1,27 @@
import sys
sys.path.append("./../src")
if sys.version < '2.7':
import unittest2 as unittest
else:
import unittest
try:
import StringIO
except ImportError:
from io import StringIO
import mock
import StringIO
import seleniumwrapper
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.remote.webelement import WebElement
from seleniumwrapper.wrapper import SeleniumWrapper
from seleniumwrapper.wrapper import SeleniumContainerWrapper
from selenium.common.exceptions import TimeoutException, NoSuchElementException, WebDriverException, ElementNotVisibleException
from selenium.common.exceptions import (
NoSuchElementException,WebDriverException, ElementNotVisibleException, TimeoutException
)
class TestSeleniumWrapperFactory(unittest.TestCase):
def test_factory_functions_raise_typeerror_if_argument_is_not_a_string(self):
self.assertRaises(TypeError, seleniumwrapper.create, 1)
self.assertRaises(TypeError, seleniumwrapper.connect, 1, "http://somethings:9999/wd/hub")
@@ -32,15 +38,15 @@ class TestSeleniumWrapperFactory(unittest.TestCase):
m = p.start()
p2 = mock.patch("seleniumwrapper.wrapper.SeleniumWrapper")
m2 = p2.start()
seleniumwrapper.connect("android", "http://localhost:4444/wd/hub", {"hoge":"hoge"})
seleniumwrapper.connect("android", "http://localhost:4444/wd/hub", {"hoge": "hoge"})
dic = DesiredCapabilities.ANDROID
dic["hoge"] = "hoge"
m.assert_called_once_with('http://localhost:4444/wd/hub', dic)
p2.stop()
p.stop()
class TestSeleniumWrapper(unittest.TestCase):
class TestSeleniumWrapper(unittest.TestCase):
def test_init_raise_if_driver_is_not_a_webdriver_object(self):
self.assertRaises(TypeError, SeleniumWrapper, 'hoge')
@@ -52,7 +58,7 @@ class TestSeleniumWrapper(unittest.TestCase):
mocked_driver = mock.Mock(WebDriver)
mocked_driver.hoge = lambda d: d
wrapper = SeleniumWrapper(mocked_driver)
self.assertEquals(wrapper.hoge(1), 1)
self.assertEqual(wrapper.hoge(1), 1)
def test_wrapper_should_raise_AttributeError_if_wrapped_driver_also_dont_have_attribute_with_given_name(self):
mocked_driver = mock.Mock(WebDriver)
@@ -73,28 +79,33 @@ class TestSeleniumWrapper(unittest.TestCase):
mocked_driver = mock.Mock(WebDriver)
mocked_driver.find_element_by_id = lambda target: target
wrapper = SeleniumWrapper(mocked_driver)
self.assertEquals(wrapper.waitfor('id', 'hoge'), 'hoge')
self.assertEqual(wrapper.waitfor('id', 'hoge'), 'hoge')
def test_wrapper_should_handle_attr_access_even_if_attr_is_descriptor(self):
mocked_element = mock.Mock(WebElement)
class Hoge(WebDriver):
def __init__(self):
pass
@property
def hoge(self):
return mocked_element
@property
def num(self):
return 100
mocked_driver = Hoge()
wrapper = SeleniumWrapper(mocked_driver)
self.assertEquals(wrapper.num, 100)
self.assertEqual(wrapper.num, 100)
self.assertTrue(isinstance(wrapper.hoge, SeleniumWrapper), wrapper.hoge)
def test_click_should_raise_if_element_is_not_stopping_for_time_seconds(self):
class Hoge(object):
def __init__(self):
self.num = 0
def __getitem__(self, num):
self.num += 1
return self.num
@@ -102,41 +113,58 @@ class TestSeleniumWrapper(unittest.TestCase):
mocked_element = mock.Mock(WebElement)
mocked_element.location = Hoge()
wrapper = SeleniumWrapper(mocked_element)
self.assertRaises(WebDriverException, wrapper.click, **{'timeout':0.5})
self.assertRaises(WebDriverException, wrapper.click, **{'timeout': 0.5})
def test_click_should_raise_if_element_is_not_clickable_for_timeout_seconds(self):
def dummy():
raise WebDriverException("hoge:fuga:huhuhu")
mocked_element = mock.Mock(WebElement)
mocked_element.click = dummy
mocked_element.value_of_css_property.return_value = 0
mocked_element.location = {"x":0, "y":0}
mocked_element.location = {"x": 0, "y": 0}
wrapper = SeleniumWrapper(mocked_element)
self.assertRaises(WebDriverException, wrapper.click, **{'timeout':0.5})
self.assertRaises(WebDriverException, wrapper.click, **{'timeout': 0.5})
def test_click_should_raise_if_element_is_not_displayed_for_timeout_seconds(self):
mocked_element = mock.Mock(WebElement)
mocked_element.is_displayed = lambda : False
mocked_element.is_displayed = lambda: False
mocked_element.value_of_css_property.return_value = 0
mocked_element.location = {"x":0, "y":0}
mocked_element.location = {"x": 0, "y": 0}
wrapper = SeleniumWrapper(mocked_element)
self.assertRaises(ElementNotVisibleException, wrapper.click, **{'timeout':0.5})
self.assertRaises(ElementNotVisibleException, wrapper.click, **{'timeout': 0.5})
def test_click_should_raise_if_other_exception_is_thrown(self):
def dummy():
raise TypeError()
mocked_element = mock.Mock(WebElement)
mocked_element.click = dummy
wrapper = SeleniumWrapper(mocked_element)
self.assertRaises(TypeError, wrapper.click, **{'timeout':0.5})
self.assertRaises(TypeError, wrapper.click, **{'timeout': 0.5})
def test_unwrap_return_its_wrapped_object(self):
mocked_element = mock.Mock(WebElement)
wrapper = SeleniumWrapper(mocked_element)
self.assertIsInstance(wrapper.unwrap, WebElement)
class TestSeleniumWrapperAliases(unittest.TestCase):
def test_execute_script_should_return_None_if_null_was_returned(self):
mocked_driver = mock.Mock(WebDriver)
mocked_driver.execute_script.return_value = None
driver = SeleniumWrapper(mocked_driver)
obj = driver.execute_script('return null')
self.assertIsNone(obj)
def test_wrapper_returns_None_in_silent_mode(self):
mocked_driver = mock.Mock(WebDriver)
mocked_driver.find_element_by_id.side_effect = TimeoutException
driver = SeleniumWrapper(mocked_driver)
self.assertRaises(NoSuchElementException, driver.by_id, 'hoge')
driver.silent = True
self.assertIsNone(driver.by_id('hoge'))
class TestSeleniumWrapperAliases(unittest.TestCase):
def setUp(self):
mocky = mock.Mock(WebDriver)
self.mock = mocky
@@ -144,12 +172,13 @@ class TestSeleniumWrapperAliases(unittest.TestCase):
def test_waitfor_raise_if_find_element_return_falsy_value(self):
self.mock.find_element_by_xpath.return_value = None
wrapper = SeleniumWrapper(self.mock)
self.assertRaises(NoSuchElementException, wrapper.waitfor, *['xpath', 'dummy'], **{'timeout':0.1})
self.assertRaises(NoSuchElementException, wrapper.waitfor, *['xpath', 'dummy'], **{'timeout': 0.1})
def test_waitfor_raise_if_find_elements_return_falsy_value(self):
self.mock.find_elements_by_xpath.return_value = []
wrapper = SeleniumWrapper(self.mock)
self.assertRaises(NoSuchElementException, wrapper.waitfor, *['xpath', 'dummy'], **{'eager':True, 'timeout':0.1})
self.assertRaises(NoSuchElementException, wrapper.waitfor, *['xpath', 'dummy'],
**{'eager': True, 'timeout': 0.1})
def test_waitfor_wraps_its_return_value_if_it_is_wrappable(self):
mock_elem = mock.Mock(WebElement)
@@ -163,6 +192,16 @@ class TestSeleniumWrapperAliases(unittest.TestCase):
wrapper = SeleniumWrapper(self.mock)
self.assertIsInstance(wrapper.waitfor("xpath", "dummy", eager=True), SeleniumContainerWrapper)
def test_attr_raise_if_invoked_from_webdriver_wrapped_object(self):
wrapper = SeleniumWrapper(self.mock)
self.assertRaises(AttributeError, wrapper.attr, 'hoge')
def test_attr_invoke_get_attribute_if_invoked_from_webelement_wrapped(self):
mock_elem = mock.Mock(WebElement)
mock_elem.get_attribute.return_value = True
wrapped = SeleniumWrapper(mock_elem)
self.assertTrue(wrapped.attr('hoge'))
def test_aliases_work_correctly(self):
mock_elem = mock.Mock(WebElement)
self.mock.find_element_by_xpath.return_value = mock_elem
@@ -193,44 +232,58 @@ class TestSeleniumWrapperAliases(unittest.TestCase):
wrapper = SeleniumWrapper(wrapped_elem)
self.assertIsInstance(wrapper.parent, SeleniumWrapper)
class TestSeleniumWrapperJavascriptSupport(unittest.TestCase):
class TestSeleniumWrapperJavascriptSupport(unittest.TestCase):
def setUp(self):
mocky = mock.Mock(WebDriver)
self.mock = mocky
def test_load_js_raise_if_given_argument_is_not_both_file_like_obj_or_path_to_file(self):
wrapper = SeleniumWrapper(self.mock)
self.assertRaises(AttributeError, wrapper.load_js, "/path/not/exists")
self.assertRaises(AttributeError, wrapper.load_js, 1)
def test_scroll_methods_raise_if_wrapped_is_not_webdriver(self):
wrapper = SeleniumWrapper(mock.Mock(WebElement))
self.assertRaises(AttributeError, wrapper.scroll_to, *[10, 10])
self.assertRaises(AttributeError, wrapper.scroll_by, *[10, 10])
self.assertRaises(AttributeError, wrapper.scroll_into_view, '#hoge')
def test_load_js_load_string_from_StringIO_because_it_respond_to_read_method(self):
f = StringIO.StringIO('hoge')
def test_scroll_into_view_raise_if_no_jquery_found(self):
wrapper = SeleniumWrapper(self.mock)
wrapper.load_js(f)
self.mock.execute_script.assert_called_once_with('hoge')
def test_script_returns_if_something_is_returned_by_execute_script(self):
self.mock.execute_script.return_value = [mock.Mock(WebElement)]
wrapper = SeleniumWrapper(self.mock)
self.assertIsInstance(wrapper.script('fuga'), SeleniumContainerWrapper)
self.mock.execute_script.return_value = mock.Mock(WebElement)
self.assertIsInstance(wrapper.script('fuga'), SeleniumWrapper)
self.mock.execute_script.return_value = None
self.assertIsNone(wrapper.script('fuga'))
self.assertRaises(AttributeError, wrapper.scroll_into_view, '#hoge')
def test_jquery_raise_if_nothing_found(self):
self.mock.execute_script.return_value = None
def test_scroll_into_view_execute_script_if_jquery_was_found(self):
wrapper = SeleniumWrapper(self.mock)
self.assertRaises(NoSuchElementException, wrapper.jquery, 'hoge')
wrapper.scroll_into_view('#hoge')
calls = [mock.call.execute_script("try{return $;}catch(e){}"),
mock.call.execute_script("try{$('#hoge') && $('#hoge')[0].scrollIntoView(true)}catch(e){}")]
self.mock.assert_has_calls(calls)
class TestSeleniumWrapperOptions(unittest.TestCase):
def setUp(self):
mocky = mock.Mock(WebDriver)
self.mock = mocky
def test_timeout_property_allows_int_and_float(self):
wrapper = SeleniumWrapper(self.mock)
wrapper.timeout = 0.1
self.assertEqual(wrapper.timeout, 0.1)
wrapper.timeout = 1
self.assertEqual(wrapper.timeout, 1)
def test_silent_property_raise_AttributeError_if_none_bool_given(self):
wrapper = SeleniumWrapper(self.mock)
try:
wrapper.silent = 1
except AttributeError:
pass
def suite():
suite = unittest.TestSuite()
#suite.addTests(unittest.makeSuite(TestSeleniumWrapperAliases))
#suite.addTests(unittest.makeSuite(TestSeleniumWrapper))
suite.addTests(unittest.makeSuite(TestSeleniumWrapperAliases))
suite.addTests(unittest.makeSuite(TestSeleniumWrapper))
suite.addTests(unittest.makeSuite(TestSeleniumWrapperJavascriptSupport))
return suite
if __name__ == "__main__":
s = suite()
unittest.TextTestRunner(verbosity=2).run(s)
+35
View File
@@ -0,0 +1,35 @@
[tox]
envlist = py26,py27,py32,py33,py34
[commondeps]
deps =
nose
mock
selenium
[testenv:py26]
basepython = python2.6
deps =
{[commondeps]deps}
unittest2
commands = nosetests
[testenv:py27]
basepython = python2.7
deps = {[commondeps]deps}
commands = nosetests
[testenv:py32]
basepython = python3.2
deps = {[commondeps]deps}
commands = nosetests
[testenv:py33]
basepython = python3.3
deps = {[commondeps]deps}
commands = nosetests
[testenv:py34]
basepython = python3.4
deps = {[commondeps]deps}
commands = nosetests