Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

run tests against all drivers. #44

Merged
merged 1 commit into from Apr 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion ftw/testbrowser/exceptions.py
Expand Up @@ -58,7 +58,7 @@ def __init__(self, query_info=None):


class ZServerRequired(BrowserException):
"""The `webdav` method can only be used with a running ZServer.
"""The requests driver can only be used with a running ZServer.
Use the `plone.app.testing.PLONE_ZSERVER` testing layer.
"""

Expand Down
20 changes: 14 additions & 6 deletions ftw/testbrowser/testing.py
Expand Up @@ -2,6 +2,8 @@
from ftw.builder.testing import BUILDER_LAYER
from ftw.builder.testing import functional_session_factory
from ftw.builder.testing import set_builder_session_factory
from ftw.testbrowser import MECHANIZE_BROWSER_FIXTURE
from ftw.testbrowser import REQUESTS_BROWSER_FIXTURE
from plone.app.testing import applyProfile
from plone.app.testing import FunctionalTesting
from plone.app.testing import PLONE_FIXTURE
Expand Down Expand Up @@ -44,12 +46,18 @@ def setUpPloneSite(self, portal):


BROWSER_FIXTURE = BrowserLayer()
BROWSER_FUNCTIONAL_TESTING = FunctionalTesting(

MECHANIZE_TESTING = FunctionalTesting(
bases=(BROWSER_FIXTURE,
set_builder_session_factory(functional_session_factory)),
name="ftw.testbrowser:functional")
BROWSER_ZSERVER_FUNCTIONAL_TESTING = FunctionalTesting(
set_builder_session_factory(functional_session_factory),
MECHANIZE_BROWSER_FIXTURE),
name='ftw.testbrowser:functional:mechanize')

REQUESTS_TESTING = FunctionalTesting(
bases=(BROWSER_FIXTURE,
set_builder_session_factory(functional_session_factory),
PLONE_ZSERVER),
name="ftw.testbrowser:functional:zserver")
PLONE_ZSERVER,
REQUESTS_BROWSER_FIXTURE),
name='ftw.testbrowser:functional:requests')

DEFAULT_TESTING = MECHANIZE_TESTING
13 changes: 10 additions & 3 deletions ftw/testbrowser/tests/__init__.py
@@ -1,16 +1,23 @@
from ftw.testbrowser.testing import BROWSER_FUNCTIONAL_TESTING
from plone.app.testing import FunctionalTesting
from plone.app.testing import setRoles
from plone.app.testing import TEST_USER_ID
from unittest2 import TestCase
import transaction


class FunctionalTestCase(TestCase):
layer = BROWSER_FUNCTIONAL_TESTING

def setUp(self):
self.portal = self.layer['portal']

def grant(self, *roles):
setRoles(self.portal, TEST_USER_ID, list(roles))
transaction.commit()
if isinstance(self.layer, FunctionalTesting):
transaction.commit()

def sync_transaction(self):
# Especially with the requests driver we sometimes need to sync
# the transaction in order to get hold of new transactions committed
# on another thread.
if isinstance(self.layer, FunctionalTesting):
transaction.begin()
68 changes: 68 additions & 0 deletions ftw/testbrowser/tests/alldrivers.py
@@ -0,0 +1,68 @@
from ftw.testbrowser.core import LIB_MECHANIZE
from ftw.testbrowser.core import LIB_REQUESTS
from ftw.testbrowser.testing import MECHANIZE_TESTING
from ftw.testbrowser.testing import REQUESTS_TESTING
from unittest2 import skip
import sys


def all_drivers(testcase):
"""Decorator for test classes so that the tests are run against all drivers.
"""

module = sys.modules[testcase.__module__]
drivers = (('Mechanize', MECHANIZE_TESTING, LIB_MECHANIZE),
('Requests', REQUESTS_TESTING, LIB_REQUESTS))
testcase._testbrowser_abstract_testclass = True

for postfix, layer, constant in drivers:
name = testcase.__name__ + postfix
custom = {'layer': layer,
'__module__': testcase.__module__,
'_testbrowser_abstract_testclass': False}

subclass = type(name, (testcase,), custom)
for attrname in dir(subclass):
method = getattr(subclass, attrname, None)
func = getattr(method, 'im_func', None)
if getattr(func, '_testbrowser_skip_driver', None) == constant:
reason = func._testbrowser_skip_reason
setattr(subclass, attrname, skip(reason)(method))

setattr(module, name, subclass)

setattr(module, 'load_tests', load_tests)
return testcase


def skip_driver(driver_constant, reason):
"""When the test class is for "all_drivers", the "skip_driver" decorator
allows to skip one test method for one driver.
"""
def decorator(func):
func._testbrowser_skip_driver = driver_constant
func._testbrowser_skip_reason = reason
return func
return decorator


def load_tests(loader, tests, _):
"""The load_tests function is copied into each test using the all_drivers
decorator, so that it can filter out the original base class from the test
discover while keeping it in the globals so that superclass calls keep
working.
"""
result = []

for test_suite in tests:
if not tuple(test_suite):
# empty
continue

test_class = type(tuple(test_suite)[0])
if getattr(test_class, '_testbrowser_abstract_testclass', False):
# skip abstract class
continue

result.append(test_suite)
return loader.suiteClass(result)
101 changes: 17 additions & 84 deletions ftw/testbrowser/tests/test_browser.py
Expand Up @@ -4,8 +4,9 @@
from ftw.testbrowser.exceptions import BlankPage
from ftw.testbrowser.exceptions import BrowserNotSetUpException
from ftw.testbrowser.pages import plone
from ftw.testbrowser.testing import BROWSER_ZSERVER_FUNCTIONAL_TESTING
from ftw.testbrowser.tests import FunctionalTestCase
from ftw.testbrowser.tests.alldrivers import all_drivers
from ftw.testbrowser.tests.alldrivers import skip_driver
from plone.app.testing import SITE_OWNER_NAME
from plone.app.testing import TEST_USER_ID
from plone.app.testing import TEST_USER_NAME
Expand Down Expand Up @@ -33,17 +34,11 @@
'secure': False}


@all_drivers
class TestBrowserCore(FunctionalTestCase):
layer = BROWSER_ZSERVER_FUNCTIONAL_TESTING

@browsing
def test_contents_MECHANIZE(self, browser):
browser.open()
self.assert_starts_with('<!DOCTYPE html>', browser.contents.strip())

@browsing
def test_contents_REQUESTS(self, browser):
browser.request_library = LIB_REQUESTS
def test_contents(self, browser):
browser.open()
self.assert_starts_with('<!DOCTYPE html>', browser.contents.strip())

Expand Down Expand Up @@ -81,13 +76,7 @@ def test_json_raises_when_parsing_not_possible(self, browser):
self.assertEquals('No JSON object could be decoded', str(cm.exception))

@browsing
def test_headers_MECHANIZE(self, browser):
browser.open()
self.assertDictContainsSubset({'content-language': 'en'}, browser.headers)

@browsing
def test_headers_REQUESTS(self, browser):
browser.request_library = LIB_REQUESTS
def test_headers(self, browser):
browser.open()
self.assertDictContainsSubset({'content-language': 'en'}, browser.headers)

Expand All @@ -97,35 +86,32 @@ def test_headers_with_open_html(self, browser):
self.assertEquals({}, browser.headers)

@browsing
def test_cookies_MECHANIZE(self, browser):
browser.open(view='login_form')
browser.fill({'Login Name': TEST_USER_NAME,
'Password': TEST_USER_PASSWORD}).submit()
self.assertDictContainsSubset(AC_COOKIE_INFO,
browser.cookies.get('__ac', None))

@browsing
def test_cookies_REQUESTS(self, browser):
browser.request_library = LIB_REQUESTS
def test_cookies(self, browser):
browser.open(view='login_form')
browser.fill({'Login Name': TEST_USER_NAME,
'Password': TEST_USER_PASSWORD}).submit()
self.assertDictContainsSubset(AC_COOKIE_INFO,
browser.cookies.get('__ac', None))

@browsing
def test_url_MECHANIZE(self, browser):
def test_url(self, browser):
browser.open(view='login_form')
self.assertEquals('/'.join((self.layer['portal'].absolute_url(),
'login_form')),
browser.url)

@skip_driver(LIB_REQUESTS, """
The behavior in this situation is not consistent between mechanize
and requests drivers.
While mechanize raises a NotFound, requests treats 404s as valid responses,
therefore it is correct to be at this URL even when it is a 404.
""")
@browsing
def test_url_is_None_when_previous_request_had_exception(self, browser):
browser.open()
with self.assertRaises(NotFound):
browser.open(view='this/path/does/not/exist')
self.assertIsNone(browser.url)
self.assertIsNone(browser.url)

@browsing
def test_base_url_is_base_url_tag(self, browser):
Expand All @@ -145,50 +131,18 @@ def test_base_url_falls_back_to_page_url(self, browser):
browser.login(SITE_OWNER_NAME).open(view_url)
self.assertEquals(view_url, browser.base_url)

@browsing
def test_base_url_with_open_html(self, browser):
browser.open_html('<html><head>'
'<base href="http://nohost/foo/bar" />'
'</head></html>')
self.assertEquals('http://nohost/foo/bar', browser.base_url)

@browsing
def test_base_url_is_None_when_unkown(self, browser):
browser.open_html('<html><head></head></html>')
self.assertIsNone(browser.base_url)

@browsing
def test_url_REQUESTS(self, browser):
browser.request_library = LIB_REQUESTS
browser.open(view='login_form')
self.assertEquals('/'.join((self.layer['portal'].absolute_url(),
'login_form')),
browser.url)

@browsing
def test_url_is_None_with_open_html(self, browser):
browser.open_html('<html><head></head></html>')
self.assertIsNone(browser.url)

@browsing
def test_cloning_copies_cookies_MECHBROWSER(self, browser):
browser.open(view='login_form').fill(
{'Login Name': TEST_USER_NAME,
'Password': TEST_USER_PASSWORD}).submit()
self.assertTrue(browser.css('#user-name'))

with browser.clone() as subbrowser:
subbrowser.open()
self.assertTrue(subbrowser.css('#user-name'))
subbrowser.find('Log out').click()
self.assertFalse(subbrowser.css('#user-name'))

browser.reload()
self.assertTrue(browser.css('#user-name'))

@browsing
def test_cloning_copies_cookies_REQUESTS(self, browser):
browser.request_library = LIB_REQUESTS
def test_cloning_copies_cookies(self, browser):
browser.open(view='login_form').fill(
{'Login Name': TEST_USER_NAME,
'Password': TEST_USER_PASSWORD}).submit()
Expand All @@ -204,19 +158,7 @@ def test_cloning_copies_cookies_REQUESTS(self, browser):
self.assertTrue(browser.css('#user-name'))

@browsing
def test_cloning_a_browser_copies_headers_MECHBROWSER(self, browser):
browser.login().open()
self.assertEquals(TEST_USER_ID, plone.logged_in())

with browser.clone() as subbrowser:
subbrowser.open()
self.assertEquals(TEST_USER_ID, plone.logged_in(subbrowser))
subbrowser.login(SITE_OWNER_NAME).reload()
self.assertEquals(SITE_OWNER_NAME, plone.logged_in(subbrowser))

@browsing
def test_cloning_a_browser_copies_headers_REQUESTS(self, browser):
browser.request_library = LIB_REQUESTS
def test_cloning_a_browser_copies_headers(self, browser):
browser.login().open()
self.assertEquals(TEST_USER_ID, plone.logged_in())

Expand All @@ -226,17 +168,8 @@ def test_cloning_a_browser_copies_headers_REQUESTS(self, browser):
subbrowser.login(SITE_OWNER_NAME).reload()
self.assertEquals(SITE_OWNER_NAME, plone.logged_in(subbrowser))

browser.reload()
self.assertEquals(TEST_USER_ID, plone.logged_in())

@browsing
def test_opening_preserves_global_request_MECHANIZE(self, browser):
browser.open()
self.assertIsNotNone(getRequest())

@browsing
def test_opening_preserves_global_request_REQUESTS(self, browser):
browser.request_library = LIB_REQUESTS
def test_opening_preserves_global_request(self, browser):
browser.open()
self.assertIsNotNone(getRequest())

Expand Down
2 changes: 2 additions & 0 deletions ftw/testbrowser/tests/test_context.py
Expand Up @@ -3,8 +3,10 @@
from ftw.testbrowser import browsing
from ftw.testbrowser.exceptions import ContextNotFound
from ftw.testbrowser.tests import FunctionalTestCase
from ftw.testbrowser.tests.alldrivers import all_drivers


@all_drivers
class TestBrowserContext(FunctionalTestCase):

def setUp(self):
Expand Down
27 changes: 8 additions & 19 deletions ftw/testbrowser/tests/test_cookies.py
@@ -1,12 +1,14 @@
from ftw.testbrowser import browsing
from ftw.testbrowser.core import LIB_REQUESTS
from ftw.testbrowser.testing import BROWSER_ZSERVER_FUNCTIONAL_TESTING
from ftw.testbrowser.core import LIB_MECHANIZE
from ftw.testbrowser.tests import FunctionalTestCase
from ftw.testbrowser.tests.alldrivers import all_drivers
from ftw.testbrowser.tests.alldrivers import skip_driver
from plone.app.testing import TEST_USER_NAME
from plone.app.testing import TEST_USER_PASSWORD


class TestMechanizeCookies(FunctionalTestCase):
@all_drivers
class TestCookies(FunctionalTestCase):

@browsing
def test_cookies(self, browser):
Expand All @@ -21,24 +23,11 @@ def test_cookies(self, browser):
browser.cookies['__ac'])


class TestZServerHeaders(FunctionalTestCase):
layer = BROWSER_ZSERVER_FUNCTIONAL_TESTING

@browsing
def test_cookies(self, browser):
browser.open(view='login_form')
browser.fill({'Login Name': TEST_USER_NAME,
'Password': TEST_USER_PASSWORD}).submit()

self.assertIn('__ac', browser.cookies)
self.assertDictContainsSubset(
{'expires': None,
'path': '/'},
browser.cookies['__ac'])

@skip_driver(LIB_MECHANIZE, """
The `webdav` method can only be used with a running ZServer.
""")
@browsing
def test_webdav_cookies(self, browser):
browser.request_library = LIB_REQUESTS
browser.open(view='login_form')
browser.fill({'Login Name': TEST_USER_NAME,
'Password': TEST_USER_PASSWORD}).submit()
Expand Down