# -*- coding: utf-8 -*-
"""
Inheritance Diagram
-------------------
.. inheritance-diagram:: kotti.testing
"""
import os
from os.path import join, dirname
from unittest import TestCase
from pytest import mark
from pyramid import testing
from pyramid.events import NewResponse
from pyramid.security import ALL_PERMISSIONS
from zope.deprecation.deprecation import deprecate
import transaction
# re-enable deprecation warnings during test runs
# however, let the `ImportWarning` produced by Babel's
# `localedata.py` vs `localedata/` show up once...
from warnings import catch_warnings
with catch_warnings():
from babel import localedata
import compiler
localedata, compiler # make pyflakes happy... :p
# py.test markers (see http://pytest.org/latest/example/markers.html)
user = mark.user
BASE_URL = 'http://localhost:6543'
[docs]class Dummy(dict):
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
[docs]class DummyRequest(testing.DummyRequest):
is_xhr = False
POST = dict()
user = None
referrer = None
def is_response(self, ob):
return (hasattr(ob, 'app_iter') and hasattr(ob, 'headerlist') and
hasattr(ob, 'status'))
def asset(name):
import kotti
return open(join(dirname(kotti.__file__), 'tests', name), 'rb')
def includeme_login(config):
config.add_view(
login_view,
name='login',
renderer='kotti:templates/login.pt')
def includeme_layout(config):
# override edit master layout with view master layout
config.override_asset(
to_override='kotti:templates/edit/master.pt',
override_with='kotti:templates/view/master.pt')
def login_view(request):
return {}
def dummy_search(search_term, request):
return u"Not found. Sorry!"
def testing_db_url():
return os.environ.get('KOTTI_TEST_DB_STRING', 'sqlite://')
def _initTestingDB():
from sqlalchemy import create_engine
from kotti import get_settings
from kotti.resources import initialize_sql
database_url = testing_db_url()
get_settings()['sqlalchemy.url'] = database_url
session = initialize_sql(create_engine(database_url), drop_all=True)
return session
def _populator():
from kotti import DBSession
from kotti.resources import Document
from kotti.populate import populate
populate()
for doc in DBSession.query(Document)[1:]:
DBSession.delete(doc)
transaction.commit()
def _turn_warnings_into_errors(): # pragma: no cover
# turn all warnings into errors, but let the `ImportWarning`
# produced by Babel's `localedata.py` vs `localedata/` show up once...
from babel import localedata
localedata # make pyflakes happy... :p
from warnings import filterwarnings
filterwarnings("error")
def setUp(init_db=True, **kwargs):
# _turn_warnings_into_errors()
from kotti import _resolve_dotted
from kotti import conf_defaults
tearDown()
settings = conf_defaults.copy()
settings['kotti.secret'] = 'secret'
settings['kotti.secret2'] = 'secret2'
settings['kotti.populators'] = 'kotti.testing._populator'
settings.update(kwargs.get('settings', {}))
settings = _resolve_dotted(settings)
kwargs['settings'] = settings
config = testing.setUp(**kwargs)
config.add_default_renderers()
if init_db:
_initTestingDB()
transaction.begin()
return config
def tearDown():
from kotti import events
from kotti import security
from kotti.message import _inject_mailer
# These should arguable use the configurator, so they don't need
# to be torn down separately:
events.clear()
security.reset()
_inject_mailer[:] = []
transaction.abort()
testing.tearDown()
[docs]class UnitTestBase(TestCase):
[docs] def setUp(self, **kwargs):
self.config = setUp(**kwargs)
[docs] def tearDown(self):
tearDown()
[docs]class EventTestBase(TestCase):
[docs] def setUp(self, **kwargs):
super(EventTestBase, self).setUp(**kwargs)
self.config.include('kotti.events')
# Functional ----
def _functional_includeme(config):
from kotti import DBSession
def expire(event):
DBSession.flush()
DBSession.expire_all()
config.add_subscriber(expire, NewResponse)
def _zope_testbrowser_pyquery(self):
from pyquery import PyQuery
return PyQuery(
self.contents.replace('xmlns="http://www.w3.org/1999/xhtml', ''))
def setUpFunctional(global_config=None, **settings):
from kotti import main
import wsgi_intercept.zope_testbrowser
from webtest import TestApp
tearDown()
_settings = {
'sqlalchemy.url': testing_db_url(),
'kotti.secret': 'secret',
'kotti.site_title': 'Website des Kottbusser Tors', # for mailing
'kotti.populators': 'kotti.testing._populator',
'mail.default_sender': 'kotti@localhost',
'pyramid.includes': 'kotti.testing._functional_includeme',
}
_settings.update(settings)
host, port = BASE_URL.split(':')[-2:]
app = main({}, **_settings)
wsgi_intercept.add_wsgi_intercept(host[2:], int(port), lambda: app)
Browser = wsgi_intercept.zope_testbrowser.WSGI_Browser
Browser.pyquery = property(_zope_testbrowser_pyquery)
return dict(
Browser=Browser,
browser=Browser(),
test_app=TestApp(app),
)
[docs]class FunctionalTestBase(TestCase):
BASE_URL = BASE_URL
[docs] def setUp(self, **kwargs):
self.__dict__.update(setUpFunctional(**kwargs))
[docs] def tearDown(self):
tearDown()
def login(self, login=u'admin', password=u'secret'):
return self.test_app.post(
'/@@login',
{'login': login, 'password': password, 'submit': 'submit'},
status=302,
)
@deprecate('login_testbrowser is deprecated as of Kotti 0.7. Please use '
'the `browser` funcarg in conjunction with the `@user` '
'decorator.')
def login_testbrowser(self, login=u'admin', password=u'secret'):
browser = self.Browser()
browser.open(BASE_URL + '/edit')
browser.getControl("Username or email").value = login
browser.getControl("Password").value = password
browser.getControl(name="submit").click()
return browser
[docs]class TestingRootFactory(dict):
__name__ = '' # root is required to have an empty name!
__parent__ = None
__acl__ = [('Allow', 'role:admin', ALL_PERMISSIONS)]
def __init__(self, request):
super(TestingRootFactory, self).__init__()
def dummy_view(context, request):
return {}
def include_testing_view(config):
config.add_view(
dummy_view,
context=TestingRootFactory,
renderer='kotti:tests/testing_view.pt',
)
config.add_view(
dummy_view,
name='secured',
permission='view',
context=TestingRootFactory,
renderer='kotti:tests/testing_view.pt',
)
def setUpFunctionalStrippedDownApp(global_config=None, **settings):
# An app that doesn't use Nodes at all
_settings = {
'kotti.base_includes': (
'kotti kotti.views kotti.views.login kotti.views.users'),
'kotti.use_tables': 'principals',
'kotti.populators': 'kotti.populate.populate_users',
'pyramid.includes': 'kotti.testing.include_testing_view',
'kotti.root_factory': 'kotti.testing.TestingRootFactory',
'kotti.site_title': 'My Stripped Down Kotti',
}
_settings.update(settings)
return setUpFunctional(global_config, **_settings)
def registerDummyMailer():
from pyramid_mailer.mailer import DummyMailer
from kotti.message import _inject_mailer
mailer = DummyMailer()
_inject_mailer.append(mailer)
return mailer
# set up deprecation warnings
from zope.deprecation.deprecation import deprecated # noqa
for item in UnitTestBase, EventTestBase, FunctionalTestBase, _initTestingDB:
name = getattr(item, '__name__', item)
deprecated(name, 'Unittest-style tests are deprecated as of Kotti 0.7. '
'Please use pytest function arguments instead.')