changeset 6217:8d98924c58b1

tests: add as little code as possible in __init__.py kallithea/tests/__init__.py contained quite a lot of code, including the test base class TestController. This in itself may be considered bad practice. Specifically, this poses a problem when using pytest 3.0+, in which asserts in some files are not automatically rewritten to give improved assert output. That problem can be fixed by explicitly registering such files for assertion rewriting, but that register call should be executed _before_ said files are imported. I.e. if the register call is in kallithea/tests/__init__.py, assert calls in __init__.py itself can not be rewritten. Since the TestController base class does effectively contain asserts, and we do not want to execute the register call from somewhere outside the kallithea/tests directory, we need to move the TestController class to another file (kallithea/tests/base.py) so we can have a register call in __init__.py before loading base.py. While not strictly necessary to fix the mentioned pytest problem, we take the opportunity to fully clean __init__.py and move everything to the new kallithea/tests/base.py. While doing so, unnecessary imports are removed, and imports are ordered alphabetically. Explicit imports of symbols from modules that were already imported as a whole, are removed in favor of fully qualifying the references (e.g. tempfile._RandomNameSequence).
author Thomas De Schampheleire <thomas.de.schampheleire@gmail.com>
date Sun, 18 Sep 2016 21:44:21 +0200
parents 49c82acd30b2
children 790aeeddcab5
files kallithea/config/environment.py kallithea/lib/db_manage.py kallithea/lib/utils.py kallithea/tests/__init__.py kallithea/tests/api/api_base.py kallithea/tests/api/test_api_git.py kallithea/tests/api/test_api_hg.py kallithea/tests/base.py kallithea/tests/conftest.py kallithea/tests/fixture.py kallithea/tests/functional/test_admin.py kallithea/tests/functional/test_admin_auth_settings.py kallithea/tests/functional/test_admin_defaults.py kallithea/tests/functional/test_admin_gists.py kallithea/tests/functional/test_admin_notifications.py kallithea/tests/functional/test_admin_permissions.py kallithea/tests/functional/test_admin_repo_groups.py kallithea/tests/functional/test_admin_repos.py kallithea/tests/functional/test_admin_settings.py kallithea/tests/functional/test_admin_user_groups.py kallithea/tests/functional/test_admin_users.py kallithea/tests/functional/test_changelog.py kallithea/tests/functional/test_changeset.py kallithea/tests/functional/test_changeset_comments.py kallithea/tests/functional/test_compare.py kallithea/tests/functional/test_compare_local.py kallithea/tests/functional/test_feed.py kallithea/tests/functional/test_files.py kallithea/tests/functional/test_followers.py kallithea/tests/functional/test_forks.py kallithea/tests/functional/test_home.py kallithea/tests/functional/test_journal.py kallithea/tests/functional/test_login.py kallithea/tests/functional/test_my_account.py kallithea/tests/functional/test_pullrequests.py kallithea/tests/functional/test_repo_groups.py kallithea/tests/functional/test_search.py kallithea/tests/functional/test_summary.py kallithea/tests/models/common.py kallithea/tests/models/test_changeset_status.py kallithea/tests/models/test_diff_parsers.py kallithea/tests/models/test_notifications.py kallithea/tests/models/test_permissions.py kallithea/tests/models/test_repo_groups.py kallithea/tests/models/test_repos.py kallithea/tests/models/test_user_groups.py kallithea/tests/models/test_users.py kallithea/tests/other/manual_test_vcs_operations.py kallithea/tests/other/test_libs.py kallithea/tests/other/test_mail.py kallithea/tests/other/test_validators.py kallithea/tests/scripts/manual_test_concurrency.py kallithea/tests/vcs/__init__.py kallithea/tests/vcs/conf.py
diffstat 54 files changed, 274 insertions(+), 263 deletions(-) [+]
line wrap: on
line diff
--- a/kallithea/config/environment.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/config/environment.py	Sun Sep 18 21:44:21 2016 +0200
@@ -96,7 +96,7 @@
             config['sqlalchemy.url'] = os.environ.get('TEST_DB')
 
         from kallithea.lib.utils import create_test_env, create_test_index
-        from kallithea.tests import TESTS_TMP_PATH
+        from kallithea.tests.base import TESTS_TMP_PATH
         #set KALLITHEA_NO_TMP_PATH=1 to disable re-creating the database and
         #test repos
         if test_env:
--- a/kallithea/lib/db_manage.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/lib/db_manage.py	Sun Sep 18 21:44:21 2016 +0200
@@ -196,7 +196,7 @@
             self.create_user(username, password, email, True)
         else:
             log.info('creating admin and regular test users')
-            from kallithea.tests import TEST_USER_ADMIN_LOGIN, \
+            from kallithea.tests.base import TEST_USER_ADMIN_LOGIN, \
             TEST_USER_ADMIN_PASS, TEST_USER_ADMIN_EMAIL, \
             TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, \
             TEST_USER_REGULAR_EMAIL, TEST_USER_REGULAR2_LOGIN, \
--- a/kallithea/lib/utils.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/lib/utils.py	Sun Sep 18 21:44:21 2016 +0200
@@ -629,7 +629,7 @@
     install test repository into tmp dir
     """
     from kallithea.lib.db_manage import DbManage
-    from kallithea.tests import HG_REPO, GIT_REPO, TESTS_TMP_PATH
+    from kallithea.tests.base import HG_REPO, GIT_REPO, TESTS_TMP_PATH
 
     # PART ONE create db
     dbconf = config['sqlalchemy.url']
--- a/kallithea/tests/__init__.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/__init__.py	Sun Sep 18 21:44:21 2016 +0200
@@ -17,217 +17,6 @@
 
 Refer to docs/contributing.rst for details on running the test suite.
 """
-import os
-import re
-import time
-import logging
-import datetime
-import hashlib
-import tempfile
 
-from tempfile import _RandomNameSequence
-
-import pylons
-import pylons.test
-from pylons import config, url
-from pylons.i18n.translation import _get_translator
-from pylons.util import ContextObj
-
-from routes.util import URLGenerator
-from webtest import TestApp
 import pytest
 
-from kallithea.lib.compat import unittest
-from kallithea import is_windows
-from kallithea.model.db import Notification, User, UserNotification
-from kallithea.model.meta import Session
-from kallithea.lib.utils2 import safe_str
-
-
-os.environ['TZ'] = 'UTC'
-if not is_windows:
-    time.tzset()
-
-log = logging.getLogger(__name__)
-
-skipif = pytest.mark.skipif
-parametrize = pytest.mark.parametrize
-
-__all__ = [
-    'skipif', 'parametrize', 'environ', 'url', 'TestController',
-    'ldap_lib_installed', 'pam_lib_installed', 'invalidate_all_caches',
-    'TESTS_TMP_PATH', 'HG_REPO', 'GIT_REPO', 'NEW_HG_REPO', 'NEW_GIT_REPO',
-    'HG_FORK', 'GIT_FORK', 'TEST_USER_ADMIN_LOGIN', 'TEST_USER_ADMIN_PASS',
-    'TEST_USER_ADMIN_EMAIL', 'TEST_USER_REGULAR_LOGIN', 'TEST_USER_REGULAR_PASS',
-    'TEST_USER_REGULAR_EMAIL', 'TEST_USER_REGULAR2_LOGIN',
-    'TEST_USER_REGULAR2_PASS', 'TEST_USER_REGULAR2_EMAIL', 'TEST_HG_REPO',
-    'TEST_HG_REPO_CLONE', 'TEST_HG_REPO_PULL', 'TEST_GIT_REPO',
-    'TEST_GIT_REPO_CLONE', 'TEST_GIT_REPO_PULL', 'HG_REMOTE_REPO',
-    'GIT_REMOTE_REPO', 'SCM_TESTS',
-]
-
-# Invoke websetup with the current config file
-# SetupCommand('setup-app').run([config_file])
-
-environ = {}
-
-#SOME GLOBALS FOR TESTS
-
-TESTS_TMP_PATH = os.path.join(tempfile.gettempdir(), 'rc_test_%s' % _RandomNameSequence().next())
-TEST_USER_ADMIN_LOGIN = 'test_admin'
-TEST_USER_ADMIN_PASS = 'test12'
-TEST_USER_ADMIN_EMAIL = 'test_admin@example.com'
-
-TEST_USER_REGULAR_LOGIN = 'test_regular'
-TEST_USER_REGULAR_PASS = 'test12'
-TEST_USER_REGULAR_EMAIL = 'test_regular@example.com'
-
-TEST_USER_REGULAR2_LOGIN = 'test_regular2'
-TEST_USER_REGULAR2_PASS = 'test12'
-TEST_USER_REGULAR2_EMAIL = 'test_regular2@example.com'
-
-HG_REPO = u'vcs_test_hg'
-GIT_REPO = u'vcs_test_git'
-
-NEW_HG_REPO = u'vcs_test_hg_new'
-NEW_GIT_REPO = u'vcs_test_git_new'
-
-HG_FORK = u'vcs_test_hg_fork'
-GIT_FORK = u'vcs_test_git_fork'
-
-## VCS
-SCM_TESTS = ['hg', 'git']
-uniq_suffix = str(int(time.mktime(datetime.datetime.now().timetuple())))
-
-GIT_REMOTE_REPO = 'git://github.com/codeinn/vcs.git'
-
-TEST_GIT_REPO = os.path.join(TESTS_TMP_PATH, GIT_REPO)
-TEST_GIT_REPO_CLONE = os.path.join(TESTS_TMP_PATH, 'vcsgitclone%s' % uniq_suffix)
-TEST_GIT_REPO_PULL = os.path.join(TESTS_TMP_PATH, 'vcsgitpull%s' % uniq_suffix)
-
-
-HG_REMOTE_REPO = 'http://bitbucket.org/marcinkuzminski/vcs'
-
-TEST_HG_REPO = os.path.join(TESTS_TMP_PATH, HG_REPO)
-TEST_HG_REPO_CLONE = os.path.join(TESTS_TMP_PATH, 'vcshgclone%s' % uniq_suffix)
-TEST_HG_REPO_PULL = os.path.join(TESTS_TMP_PATH, 'vcshgpull%s' % uniq_suffix)
-
-TEST_DIR = tempfile.gettempdir()
-TEST_REPO_PREFIX = 'vcs-test'
-
-# cached repos if any !
-# comment out to get some other repos from bb or github
-GIT_REMOTE_REPO = os.path.join(TESTS_TMP_PATH, GIT_REPO)
-HG_REMOTE_REPO = os.path.join(TESTS_TMP_PATH, HG_REPO)
-
-#skip ldap tests if LDAP lib is not installed
-ldap_lib_installed = False
-try:
-    import ldap
-    ldap.API_VERSION
-    ldap_lib_installed = True
-except ImportError:
-    # means that python-ldap is not installed
-    pass
-
-try:
-    import pam
-    pam.PAM_TEXT_INFO
-    pam_lib_installed = True
-except ImportError:
-    pam_lib_installed = False
-
-def invalidate_all_caches():
-    """Invalidate all beaker caches currently configured.
-    Useful when manipulating IP permissions in a test and changes need to take
-    effect immediately.
-    Note: Any use of this function is probably a workaround - it should be
-    replaced with a more specific cache invalidation in code or test."""
-    from beaker.cache import cache_managers
-    for cache in cache_managers.values():
-        cache.clear()
-
-class NullHandler(logging.Handler):
-    def emit(self, record):
-        pass
-
-class TestController(object):
-    """Pytest-style test controller"""
-
-    # Note: pytest base classes cannot have an __init__ method
-
-    @pytest.fixture(autouse=True)
-    def app_fixture(self):
-        self.wsgiapp = pylons.test.pylonsapp
-        self.init_stack(self.wsgiapp.config)
-        self.app = TestApp(self.wsgiapp)
-        self.maxDiff = None
-        self.index_location = config['app_conf']['index_dir']
-        return self.app
-
-    def init_stack(self, config=None):
-        if not config:
-            config = pylons.test.pylonsapp.config
-        url._push_object(URLGenerator(config['routes.map'], environ))
-        pylons.app_globals._push_object(config['pylons.app_globals'])
-        pylons.config._push_object(config)
-        pylons.tmpl_context._push_object(ContextObj())
-        # Initialize a translator for tests that utilize i18n
-        translator = _get_translator(pylons.config.get('lang'))
-        pylons.translator._push_object(translator)
-        h = NullHandler()
-        logging.getLogger("kallithea").addHandler(h)
-
-    def remove_all_notifications(self):
-        # query().delete() does not (by default) trigger cascades
-        # ( http://docs.sqlalchemy.org/en/rel_0_7/orm/collections.html#passive-deletes )
-        # so delete the UserNotification first to ensure referential integrity.
-        UserNotification.query().delete()
-
-        Notification.query().delete()
-        Session().commit()
-
-    def log_user(self, username=TEST_USER_ADMIN_LOGIN,
-                 password=TEST_USER_ADMIN_PASS):
-        self._logged_username = username
-        response = self.app.post(url(controller='login', action='index'),
-                                 {'username': username,
-                                  'password': password})
-
-        if 'Invalid username or password' in response.body:
-            pytest.fail('could not login using %s %s' % (username, password))
-
-        assert response.status == '302 Found'
-        self.assert_authenticated_user(response, username)
-
-        response = response.follow()
-        return response.session['authuser']
-
-    def _get_logged_user(self):
-        return User.get_by_username(self._logged_username)
-
-    def assert_authenticated_user(self, response, expected_username):
-        cookie = response.session.get('authuser')
-        user = cookie and cookie.get('user_id')
-        user = user and User.get(user)
-        user = user and user.username
-        assert user == expected_username
-
-    def authentication_token(self):
-        return self.app.get(url('authentication_token')).body
-
-    def checkSessionFlash(self, response, msg=None, skip=0, _matcher=lambda msg, m: msg in m):
-        if 'flash' not in response.session:
-            pytest.fail(safe_str(u'msg `%s` not found - session has no flash:\n%s' % (msg, response)))
-        try:
-            level, m = response.session['flash'][-1 - skip]
-            if _matcher(msg, m):
-                return
-        except IndexError:
-            pass
-        pytest.fail(safe_str(u'msg `%s` not found in session flash (skipping %s): %s' %
-                           (msg, skip,
-                            ', '.join('`%s`' % m for level, m in response.session['flash']))))
-
-    def checkSessionFlashRegex(self, response, regex, skip=0):
-        self.checkSessionFlash(response, regex, skip=skip, _matcher=re.search)
--- a/kallithea/tests/api/api_base.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/api/api_base.py	Sun Sep 18 21:44:21 2016 +0200
@@ -20,7 +20,7 @@
 import random
 import mock
 
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 from kallithea.lib.compat import json
 from kallithea.lib.auth import AuthUser
--- a/kallithea/tests/api/test_api_git.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/api/test_api_git.py	Sun Sep 18 21:44:21 2016 +0200
@@ -12,7 +12,7 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from kallithea.tests import TestController, GIT_REPO
+from kallithea.tests.base import TestController, GIT_REPO
 from kallithea.tests.api.api_base import _BaseTestApi
 
 
--- a/kallithea/tests/api/test_api_hg.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/api/test_api_hg.py	Sun Sep 18 21:44:21 2016 +0200
@@ -12,7 +12,7 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from kallithea.tests import TestController, HG_REPO
+from kallithea.tests.base import TestController, HG_REPO
 from kallithea.tests.api.api_base import _BaseTestApi
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/tests/base.py	Sun Sep 18 21:44:21 2016 +0200
@@ -0,0 +1,222 @@
+# -*- coding: utf-8 -*-
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import datetime
+import logging
+import os
+import pytest
+import re
+import tempfile
+import time
+
+import pylons
+from pylons import config, url
+from pylons.i18n.translation import _get_translator
+from pylons.util import ContextObj
+from routes.util import URLGenerator
+from webtest import TestApp
+
+from kallithea import is_windows
+from kallithea.model.db import Notification, User, UserNotification
+from kallithea.model.meta import Session
+from kallithea.lib.utils2 import safe_str
+
+os.environ['TZ'] = 'UTC'
+if not is_windows:
+    time.tzset()
+
+log = logging.getLogger(__name__)
+
+skipif = pytest.mark.skipif
+parametrize = pytest.mark.parametrize
+
+__all__ = [
+    'skipif', 'parametrize', 'environ', 'url', 'TestController',
+    'ldap_lib_installed', 'pam_lib_installed', 'invalidate_all_caches',
+    'TESTS_TMP_PATH', 'HG_REPO', 'GIT_REPO', 'NEW_HG_REPO', 'NEW_GIT_REPO',
+    'HG_FORK', 'GIT_FORK', 'TEST_USER_ADMIN_LOGIN', 'TEST_USER_ADMIN_PASS',
+    'TEST_USER_ADMIN_EMAIL', 'TEST_USER_REGULAR_LOGIN', 'TEST_USER_REGULAR_PASS',
+    'TEST_USER_REGULAR_EMAIL', 'TEST_USER_REGULAR2_LOGIN',
+    'TEST_USER_REGULAR2_PASS', 'TEST_USER_REGULAR2_EMAIL', 'TEST_HG_REPO',
+    'TEST_HG_REPO_CLONE', 'TEST_HG_REPO_PULL', 'TEST_GIT_REPO',
+    'TEST_GIT_REPO_CLONE', 'TEST_GIT_REPO_PULL', 'HG_REMOTE_REPO',
+    'GIT_REMOTE_REPO', 'SCM_TESTS',
+]
+
+# Invoke websetup with the current config file
+# SetupCommand('setup-app').run([config_file])
+
+environ = {}
+
+#SOME GLOBALS FOR TESTS
+
+TESTS_TMP_PATH = os.path.join(tempfile.gettempdir(), 'rc_test_%s' % tempfile._RandomNameSequence().next())
+TEST_USER_ADMIN_LOGIN = 'test_admin'
+TEST_USER_ADMIN_PASS = 'test12'
+TEST_USER_ADMIN_EMAIL = 'test_admin@example.com'
+
+TEST_USER_REGULAR_LOGIN = 'test_regular'
+TEST_USER_REGULAR_PASS = 'test12'
+TEST_USER_REGULAR_EMAIL = 'test_regular@example.com'
+
+TEST_USER_REGULAR2_LOGIN = 'test_regular2'
+TEST_USER_REGULAR2_PASS = 'test12'
+TEST_USER_REGULAR2_EMAIL = 'test_regular2@example.com'
+
+HG_REPO = u'vcs_test_hg'
+GIT_REPO = u'vcs_test_git'
+
+NEW_HG_REPO = u'vcs_test_hg_new'
+NEW_GIT_REPO = u'vcs_test_git_new'
+
+HG_FORK = u'vcs_test_hg_fork'
+GIT_FORK = u'vcs_test_git_fork'
+
+## VCS
+SCM_TESTS = ['hg', 'git']
+uniq_suffix = str(int(time.mktime(datetime.datetime.now().timetuple())))
+
+GIT_REMOTE_REPO = 'git://github.com/codeinn/vcs.git'
+
+TEST_GIT_REPO = os.path.join(TESTS_TMP_PATH, GIT_REPO)
+TEST_GIT_REPO_CLONE = os.path.join(TESTS_TMP_PATH, 'vcsgitclone%s' % uniq_suffix)
+TEST_GIT_REPO_PULL = os.path.join(TESTS_TMP_PATH, 'vcsgitpull%s' % uniq_suffix)
+
+
+HG_REMOTE_REPO = 'http://bitbucket.org/marcinkuzminski/vcs'
+
+TEST_HG_REPO = os.path.join(TESTS_TMP_PATH, HG_REPO)
+TEST_HG_REPO_CLONE = os.path.join(TESTS_TMP_PATH, 'vcshgclone%s' % uniq_suffix)
+TEST_HG_REPO_PULL = os.path.join(TESTS_TMP_PATH, 'vcshgpull%s' % uniq_suffix)
+
+TEST_DIR = tempfile.gettempdir()
+TEST_REPO_PREFIX = 'vcs-test'
+
+# cached repos if any !
+# comment out to get some other repos from bb or github
+GIT_REMOTE_REPO = os.path.join(TESTS_TMP_PATH, GIT_REPO)
+HG_REMOTE_REPO = os.path.join(TESTS_TMP_PATH, HG_REPO)
+
+#skip ldap tests if LDAP lib is not installed
+ldap_lib_installed = False
+try:
+    import ldap
+    ldap.API_VERSION
+    ldap_lib_installed = True
+except ImportError:
+    # means that python-ldap is not installed
+    pass
+
+try:
+    import pam
+    pam.PAM_TEXT_INFO
+    pam_lib_installed = True
+except ImportError:
+    pam_lib_installed = False
+
+def invalidate_all_caches():
+    """Invalidate all beaker caches currently configured.
+    Useful when manipulating IP permissions in a test and changes need to take
+    effect immediately.
+    Note: Any use of this function is probably a workaround - it should be
+    replaced with a more specific cache invalidation in code or test."""
+    from beaker.cache import cache_managers
+    for cache in cache_managers.values():
+        cache.clear()
+
+class NullHandler(logging.Handler):
+    def emit(self, record):
+        pass
+
+class TestController(object):
+    """Pytest-style test controller"""
+
+    # Note: pytest base classes cannot have an __init__ method
+
+    @pytest.fixture(autouse=True)
+    def app_fixture(self):
+        self.wsgiapp = pylons.test.pylonsapp
+        self.init_stack(self.wsgiapp.config)
+        self.app = TestApp(self.wsgiapp)
+        self.maxDiff = None
+        self.index_location = config['app_conf']['index_dir']
+        return self.app
+
+    def init_stack(self, config=None):
+        if not config:
+            config = pylons.test.pylonsapp.config
+        url._push_object(URLGenerator(config['routes.map'], environ))
+        pylons.app_globals._push_object(config['pylons.app_globals'])
+        pylons.config._push_object(config)
+        pylons.tmpl_context._push_object(ContextObj())
+        # Initialize a translator for tests that utilize i18n
+        translator = _get_translator(pylons.config.get('lang'))
+        pylons.translator._push_object(translator)
+        h = NullHandler()
+        logging.getLogger("kallithea").addHandler(h)
+
+    def remove_all_notifications(self):
+        # query().delete() does not (by default) trigger cascades
+        # ( http://docs.sqlalchemy.org/en/rel_0_7/orm/collections.html#passive-deletes )
+        # so delete the UserNotification first to ensure referential integrity.
+        UserNotification.query().delete()
+
+        Notification.query().delete()
+        Session().commit()
+
+    def log_user(self, username=TEST_USER_ADMIN_LOGIN,
+                 password=TEST_USER_ADMIN_PASS):
+        self._logged_username = username
+        response = self.app.post(url(controller='login', action='index'),
+                                 {'username': username,
+                                  'password': password})
+
+        if 'Invalid username or password' in response.body:
+            pytest.fail('could not login using %s %s' % (username, password))
+
+        assert response.status == '302 Found'
+        self.assert_authenticated_user(response, username)
+
+        response = response.follow()
+        return response.session['authuser']
+
+    def _get_logged_user(self):
+        return User.get_by_username(self._logged_username)
+
+    def assert_authenticated_user(self, response, expected_username):
+        cookie = response.session.get('authuser')
+        user = cookie and cookie.get('user_id')
+        user = user and User.get(user)
+        user = user and user.username
+        assert user == expected_username
+
+    def authentication_token(self):
+        return self.app.get(url('authentication_token')).body
+
+    def checkSessionFlash(self, response, msg=None, skip=0, _matcher=lambda msg, m: msg in m):
+        if 'flash' not in response.session:
+            pytest.fail(safe_str(u'msg `%s` not found - session has no flash:\n%s' % (msg, response)))
+        try:
+            level, m = response.session['flash'][-1 - skip]
+            if _matcher(msg, m):
+                return
+        except IndexError:
+            pass
+        pytest.fail(safe_str(u'msg `%s` not found in session flash (skipping %s): %s' %
+                           (msg, skip,
+                            ', '.join('`%s`' % m for level, m in response.session['flash']))))
+
+    def checkSessionFlashRegex(self, response, regex, skip=0):
+        self.checkSessionFlash(response, regex, skip=skip, _matcher=re.search)
+
--- a/kallithea/tests/conftest.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/conftest.py	Sun Sep 18 21:44:21 2016 +0200
@@ -10,7 +10,7 @@
 from kallithea.model.user import UserModel
 from kallithea.model.meta import Session
 from kallithea.model.db import Setting, User, UserIpMap
-from kallithea.tests import invalidate_all_caches, TEST_USER_REGULAR_LOGIN
+from kallithea.tests.base import invalidate_all_caches, TEST_USER_REGULAR_LOGIN
 
 
 def pytest_configure():
--- a/kallithea/tests/fixture.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/fixture.py	Sun Sep 18 21:44:21 2016 +0200
@@ -17,7 +17,7 @@
 """
 import os
 import time
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.model.db import Repository, User, RepoGroup, UserGroup, Gist
 from kallithea.model.meta import Session
 from kallithea.model.repo import RepoModel
--- a/kallithea/tests/functional/test_admin.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_admin.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,7 +1,7 @@
 import os
 import csv
 import datetime
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.model.db import UserLog
 from kallithea.model.meta import Session
 from kallithea.lib.utils2 import safe_unicode
--- a/kallithea/tests/functional/test_admin_auth_settings.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_admin_auth_settings.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,4 +1,4 @@
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.model.db import Setting
 
 
--- a/kallithea/tests/functional/test_admin_defaults.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_admin_defaults.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,4 +1,4 @@
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.model.db import Setting
 
 
--- a/kallithea/tests/functional/test_admin_gists.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_admin_gists.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,4 +1,4 @@
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.model.gist import GistModel
 from kallithea.model.meta import Session
 from kallithea.model.db import User, Gist
--- a/kallithea/tests/functional/test_admin_notifications.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_admin_notifications.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,4 +1,4 @@
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.model.db import User
 
 from kallithea.model.user import UserModel
--- a/kallithea/tests/functional/test_admin_permissions.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_admin_permissions.py	Sun Sep 18 21:44:21 2016 +0200
@@ -3,7 +3,7 @@
 from kallithea.model.db import User, UserIpMap
 from kallithea.model.user import UserModel
 from kallithea.model.meta import Session
-from kallithea.tests import *
+from kallithea.tests.base import *
 
 class TestAdminPermissionsController(TestController):
 
--- a/kallithea/tests/functional/test_admin_repo_groups.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_admin_repo_groups.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,4 +1,4 @@
-from kallithea.tests import *
+from kallithea.tests.base import *
 
 class TestRepoGroupsController(TestController):
     pass
--- a/kallithea/tests/functional/test_admin_repos.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_admin_repos.py	Sun Sep 18 21:44:21 2016 +0200
@@ -11,7 +11,7 @@
 from kallithea.model.db import Repository, RepoGroup, UserRepoToPerm, User, \
     Permission, Ui
 from kallithea.model.user import UserModel
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.model.repo_group import RepoGroupModel
 from kallithea.model.repo import RepoModel
 from kallithea.model.meta import Session
--- a/kallithea/tests/functional/test_admin_settings.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_admin_settings.py	Sun Sep 18 21:44:21 2016 +0200
@@ -3,7 +3,7 @@
 import tempfile
 
 from kallithea.model.db import Setting, Ui
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 
 fixture = Fixture()
--- a/kallithea/tests/functional/test_admin_user_groups.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_admin_user_groups.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.model.db import UserGroup, UserGroupToPerm, Permission
 from kallithea.model.meta import Session
 
--- a/kallithea/tests/functional/test_admin_users.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_admin_users.py	Sun Sep 18 21:44:21 2016 +0200
@@ -15,7 +15,7 @@
 from sqlalchemy.orm.exc import NoResultFound, ObjectDeletedError
 
 import pytest
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 from kallithea.controllers.admin.users import UsersController
 from kallithea.model.db import User, Permission, UserIpMap, UserApiKeys
--- a/kallithea/tests/functional/test_changelog.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_changelog.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,4 +1,4 @@
-from kallithea.tests import *
+from kallithea.tests.base import *
 
 
 class TestChangelogController(TestController):
--- a/kallithea/tests/functional/test_changeset.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_changeset.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,4 +1,4 @@
-from kallithea.tests import *
+from kallithea.tests.base import *
 
 class TestChangesetController(TestController):
 
--- a/kallithea/tests/functional/test_changeset_comments.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_changeset_comments.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,4 +1,4 @@
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.model.db import ChangesetComment, Notification, \
     UserNotification
 from kallithea.model.meta import Session
--- a/kallithea/tests/functional/test_compare.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_compare.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.model.repo import RepoModel
 from kallithea.model.meta import Session
 from kallithea.tests.fixture import Fixture
--- a/kallithea/tests/functional/test_compare_local.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_compare_local.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-from kallithea.tests import *
+from kallithea.tests.base import *
 
 class TestCompareController(TestController):
 
--- a/kallithea/tests/functional/test_feed.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_feed.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,4 +1,4 @@
-from kallithea.tests import *
+from kallithea.tests.base import *
 
 class TestFeedController(TestController):
 
--- a/kallithea/tests/functional/test_files.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_files.py	Sun Sep 18 21:44:21 2016 +0200
@@ -2,7 +2,7 @@
 import os
 import posixpath
 import mimetypes
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.model.db import Repository
 from kallithea.model.meta import Session
 from kallithea.tests.fixture import Fixture
--- a/kallithea/tests/functional/test_followers.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_followers.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,4 +1,4 @@
-from kallithea.tests import *
+from kallithea.tests.base import *
 
 
 class TestFollowersController(TestController):
--- a/kallithea/tests/functional/test_forks.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_forks.py	Sun Sep 18 21:44:21 2016 +0200
@@ -2,7 +2,7 @@
 
 import unittest
 
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 
 from kallithea.model.db import Repository
--- a/kallithea/tests/functional/test_home.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_home.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,4 +1,4 @@
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 from kallithea.model.meta import Session
 from kallithea.model.db import Repository
--- a/kallithea/tests/functional/test_journal.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_journal.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,4 +1,4 @@
-from kallithea.tests import *
+from kallithea.tests.base import *
 import datetime
 
 
--- a/kallithea/tests/functional/test_login.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_login.py	Sun Sep 18 21:44:21 2016 +0200
@@ -5,7 +5,7 @@
 
 import mock
 
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 from kallithea.lib.utils2 import generate_api_key
 from kallithea.lib.auth import check_password
--- a/kallithea/tests/functional/test_my_account.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_my_account.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 
 from kallithea.model.db import User, UserFollowing, Repository, UserApiKeys
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 from kallithea.lib import helpers as h
 from kallithea.model.user import UserModel
--- a/kallithea/tests/functional/test_pullrequests.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_pullrequests.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,6 +1,6 @@
 import re
 
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 from kallithea.model.meta import Session
 
--- a/kallithea/tests/functional/test_repo_groups.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_repo_groups.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,4 +1,4 @@
-from kallithea.tests import *
+from kallithea.tests.base import *
 
 
 class TestRepoGroupsController(TestController):
--- a/kallithea/tests/functional/test_search.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_search.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,6 +1,6 @@
 import mock
 import os
-from kallithea.tests import *
+from kallithea.tests.base import *
 
 
 class TestSearchController(TestController):
--- a/kallithea/tests/functional/test_summary.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/functional/test_summary.py	Sun Sep 18 21:44:21 2016 +0200
@@ -12,7 +12,7 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 from kallithea.model.db import Repository
 from kallithea.model.repo import RepoModel
--- a/kallithea/tests/models/common.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/models/common.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,4 +1,4 @@
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 
 from kallithea.model.repo_group import RepoGroupModel
--- a/kallithea/tests/models/test_changeset_status.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/models/test_changeset_status.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,4 +1,4 @@
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.model.changeset_status import ChangesetStatusModel
 from kallithea.model.db import ChangesetStatus as CS
 
--- a/kallithea/tests/models/test_diff_parsers.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/models/test_diff_parsers.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,4 +1,4 @@
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.lib.diffs import DiffProcessor, NEW_FILENODE, DEL_FILENODE, \
     MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE, COPIED_FILENODE
 from kallithea.tests.fixture import Fixture
--- a/kallithea/tests/models/test_notifications.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/models/test_notifications.py	Sun Sep 18 21:44:21 2016 +0200
@@ -4,7 +4,7 @@
 import mock
 import routes.util
 
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.lib import helpers as h
 from kallithea.model.db import User, Notification, UserNotification
 from kallithea.model.user import UserModel
--- a/kallithea/tests/models/test_permissions.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/models/test_permissions.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,4 +1,4 @@
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 from kallithea.model.repo_group import RepoGroupModel
 from kallithea.model.repo import RepoModel
--- a/kallithea/tests/models/test_repo_groups.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/models/test_repo_groups.py	Sun Sep 18 21:44:21 2016 +0200
@@ -2,7 +2,7 @@
 import pytest
 from sqlalchemy.exc import IntegrityError
 
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 
 from kallithea.model.repo_group import RepoGroupModel
--- a/kallithea/tests/models/test_repos.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/models/test_repos.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,5 +1,5 @@
 import pytest
-from kallithea.tests import *
+from kallithea.tests.base import *
 
 from kallithea.model.meta import Session
 from kallithea.tests.fixture import Fixture
--- a/kallithea/tests/models/test_user_groups.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/models/test_user_groups.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,6 +1,6 @@
 from kallithea.model.db import User, UserGroup
 
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 
 from kallithea.model.user_group import UserGroupModel
--- a/kallithea/tests/models/test_users.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/models/test_users.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,5 +1,5 @@
 import pytest
-from kallithea.tests import *
+from kallithea.tests.base import *
 
 from kallithea.model.db import User, UserGroup, UserGroupMember, UserEmailMap, \
     Permission
--- a/kallithea/tests/other/manual_test_vcs_operations.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/other/manual_test_vcs_operations.py	Sun Sep 18 21:44:21 2016 +0200
@@ -40,7 +40,7 @@
 from tempfile import _RandomNameSequence
 from subprocess import Popen, PIPE
 
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.tests.fixture import Fixture
 from kallithea.model.db import User, Repository, UserIpMap, CacheInvalidation
 from kallithea.model.meta import Session
--- a/kallithea/tests/other/test_libs.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/other/test_libs.py	Sun Sep 18 21:44:21 2016 +0200
@@ -28,7 +28,7 @@
 import datetime
 import hashlib
 import mock
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.lib.utils2 import AttributeDict
 from kallithea.model.db import Repository
 
--- a/kallithea/tests/other/test_mail.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/other/test_mail.py	Sun Sep 18 21:44:21 2016 +0200
@@ -1,7 +1,7 @@
 import mock
 
 import kallithea
-from kallithea.tests import *
+from kallithea.tests.base import *
 from kallithea.model.db import User
 
 class smtplib_mock(object):
--- a/kallithea/tests/other/test_validators.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/other/test_validators.py	Sun Sep 18 21:44:21 2016 +0200
@@ -3,7 +3,7 @@
 import pytest
 import tempfile
 
-from kallithea.tests import *
+from kallithea.tests.base import *
 
 from kallithea.model import validators as v
 from kallithea.model.user_group import UserGroupModel
--- a/kallithea/tests/scripts/manual_test_concurrency.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/scripts/manual_test_concurrency.py	Sun Sep 18 21:44:21 2016 +0200
@@ -44,7 +44,7 @@
 from kallithea.model.db import User, Repository, Ui
 from kallithea.lib.auth import get_crypt_password
 
-from kallithea.tests import HG_REPO
+from kallithea.tests.base import HG_REPO
 from kallithea.config.environment import load_environment
 
 rel_path = dirname(dirname(dirname(dirname(os.path.abspath(__file__)))))
--- a/kallithea/tests/vcs/__init__.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/vcs/__init__.py	Sun Sep 18 21:44:21 2016 +0200
@@ -23,7 +23,7 @@
 from kallithea.tests.vcs.conf import *
 from kallithea.tests.vcs.utils import SCMFetcher
 
-from kallithea.tests import *
+from kallithea.tests.base import *
 
 
 def setup_package():
--- a/kallithea/tests/vcs/conf.py	Mon Sep 19 22:39:26 2016 +0200
+++ b/kallithea/tests/vcs/conf.py	Sun Sep 18 21:44:21 2016 +0200
@@ -84,4 +84,4 @@
 TEST_USER_CONFIG_FILE = _dest
 
 #overide default configurations with kallithea ones
-from kallithea.tests import *
+from kallithea.tests.base import *