[Python-modules-commits] [django-session-security] 07/09: Test stabilization and Django upgrade
Jean-Michel Vourgère
nirgal at moszumanska.debian.org
Sun Jan 17 04:55:43 UTC 2016
This is an automated email from the git hooks/post-receive script.
nirgal pushed a commit to tag 2.3.1
in repository django-session-security.
commit 629cb112d5d6a1c12133331fae55e5b3cba5e298
Author: jpic <jamespic at gmail.com>
Date: Wed Dec 23 02:45:10 2015 +0100
Test stabilization and Django upgrade
This commit introduces django-sbo-selenium, which is AWESOME so far,
apparently it should give use saucelabs support for free so we should be
able to test on a variety of browser when this is set up on travis.
---
.travis.yml | 13 +-
circle.yml | 1 -
.../fixtures/session_security_test_user.json | 20 +++
session_security/tests/project/__init__.py | 0
session_security/tests/project/settings.py | 117 +++++++++++++++++
.../tests/project}/static/jquery.js | 0
.../tests/project}/templates/404.html | 0
.../tests/project}/templates/500.html | 0
.../tests/project}/templates/admin/base_site.html | 0
.../tests/project}/templates/home.html | 0
.../tests/project}/urls.py | 15 ++-
session_security/tests/project/wsgi.py | 16 +++
session_security/tests/test_base.py | 68 +++-------
session_security/tests/test_middleware.py | 8 +-
session_security/tests/test_script.py | 143 ++++++---------------
session_security/tests/test_views.py | 6 +-
session_security/urls.py | 4 +-
test_project/test_project/settings.py | 1 +
tox.ini | 31 ++---
19 files changed, 254 insertions(+), 189 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 5739112..f1266b2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,23 +4,20 @@ python:
- "2.7"
env:
matrix:
- - TOXENV=py27-django16
- TOXENV=py27-django17
- TOXENV=py27-django18
- TOXENV=py27-django19
- - TOXENV=py34-django16
+ - TOXENV=py27-django110
- TOXENV=py34-django17
- TOXENV=py34-django18
- TOXENV=py34-django19
-before_script:
- - "export DISPLAY=:99.0"
- - "sh -e /etc/init.d/xvfb start"
- - sleep 3 # give xvfb some time to start
+ - TOXENV=py34-django110
install:
- - pip install tox --use-mirrors
+ - pip install -U pip
+ - pip install tox
- pip freeze
script:
- - CI=1 tox
+ - tox
notifications:
irc:
channels:
diff --git a/circle.yml b/circle.yml
deleted file mode 120000
index e623fa5..0000000
--- a/circle.yml
+++ /dev/null
@@ -1 +0,0 @@
-.travis.yml
\ No newline at end of file
diff --git a/session_security/fixtures/session_security_test_user.json b/session_security/fixtures/session_security_test_user.json
new file mode 100644
index 0000000..7d1d88c
--- /dev/null
+++ b/session_security/fixtures/session_security_test_user.json
@@ -0,0 +1,20 @@
+[
+{
+ "fields": {
+ "username": "test",
+ "first_name": "",
+ "last_name": "",
+ "is_active": true,
+ "is_superuser": true,
+ "is_staff": true,
+ "last_login": "2016-01-02T18:58:21.335Z",
+ "groups": [],
+ "user_permissions": [],
+ "password": "pbkdf2_sha256$20000$TQkBIr0aXufO$+gnQDKfj7Gr1S1USQLULGIH0dXZAvmwVAv8OgoREkEE=",
+ "email": "t at tt.tt",
+ "date_joined": "2016-01-02T18:58:14.790Z"
+ },
+ "model": "auth.user",
+ "pk": 1
+}
+]
diff --git a/session_security/tests/project/__init__.py b/session_security/tests/project/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/session_security/tests/project/settings.py b/session_security/tests/project/settings.py
new file mode 100644
index 0000000..def47de
--- /dev/null
+++ b/session_security/tests/project/settings.py
@@ -0,0 +1,117 @@
+"""
+Django settings for project project.
+
+Generated by 'django-admin startproject' using Django 1.8.3.dev20150604012123.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/dev/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/dev/ref/settings/
+"""
+
+# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
+import os
+
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/dev/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = '#vhyi-*846#q09+him)ogenb#j7^3(w5($c8c1@)sy781(!8fm'
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+ALLOWED_HOSTS = []
+
+
+# Application definition
+
+INSTALLED_APPS = (
+ 'django.contrib.admin',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.messages',
+ 'django.contrib.staticfiles',
+ 'session_security',
+ 'sbo_selenium',
+)
+
+MIDDLEWARE_CLASSES = (
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.common.CommonMiddleware',
+ 'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+ 'session_security.middleware.SessionSecurityMiddleware',
+)
+
+ROOT_URLCONF = 'session_security.tests.project.urls'
+
+TEMPLATE_DIRS = [os.path.join(BASE_DIR, 'templates')]
+TEMPLATE_CONTEXT_PROCESSORS = [
+ 'django.core.context_processors.request',
+ 'django.core.context_processors.debug',
+ 'django.contrib.auth.context_processors.auth',
+]
+
+TEMPLATES = [
+ {
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'DIRS': TEMPLATE_DIRS,
+ 'APP_DIRS': True,
+ 'OPTIONS': {
+ 'context_processors': [
+ 'django.template.context_processors.debug',
+ 'django.template.context_processors.request',
+ 'django.contrib.auth.context_processors.auth',
+ ]
+ },
+ },
+]
+
+STATICFILES_DIRS = (
+ os.path.join(BASE_DIR, 'static'),
+)
+
+WSGI_APPLICATION = 'session_security.tests.project.wsgi.application'
+
+
+# Database
+# https://docs.djangoproject.com/en/dev/ref/settings/#databases
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.sqlite3',
+ 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
+ }
+}
+
+
+# Internationalization
+# https://docs.djangoproject.com/en/dev/topics/i18n/
+
+LANGUAGE_CODE = 'en-us'
+
+TIME_ZONE = 'UTC'
+
+USE_I18N = True
+
+USE_L10N = True
+
+USE_TZ = True
+
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/dev/howto/static-files/
+
+STATIC_URL = '/static/'
+
+SESSION_SECURITY_EXPIRE_AFTER=10
+SESSION_SECURITY_WARN_AFTER=5
diff --git a/test_project/static/jquery.js b/session_security/tests/project/static/jquery.js
similarity index 100%
rename from test_project/static/jquery.js
rename to session_security/tests/project/static/jquery.js
diff --git a/test_project/templates/404.html b/session_security/tests/project/templates/404.html
similarity index 100%
rename from test_project/templates/404.html
rename to session_security/tests/project/templates/404.html
diff --git a/test_project/templates/500.html b/session_security/tests/project/templates/500.html
similarity index 100%
rename from test_project/templates/500.html
rename to session_security/tests/project/templates/500.html
diff --git a/test_project/templates/admin/base_site.html b/session_security/tests/project/templates/admin/base_site.html
similarity index 100%
rename from test_project/templates/admin/base_site.html
rename to session_security/tests/project/templates/admin/base_site.html
diff --git a/test_project/templates/home.html b/session_security/tests/project/templates/home.html
similarity index 100%
rename from test_project/templates/home.html
rename to session_security/tests/project/templates/home.html
diff --git a/test_project/test_project/urls.py b/session_security/tests/project/urls.py
similarity index 77%
rename from test_project/test_project/urls.py
rename to session_security/tests/project/urls.py
index 09d6e66..a89d543 100644
--- a/test_project/test_project/urls.py
+++ b/session_security/tests/project/urls.py
@@ -1,6 +1,11 @@
import time
-from django.conf.urls import patterns, include, url
+from django.conf.urls import include, url
+
+try:
+ from django.conf.urls import patterns
+except ImportError:
+ patterns = None
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
@@ -15,10 +20,14 @@ class SleepView(generic.TemplateView):
time.sleep(int(request.GET.get('seconds', 0)))
return super(SleepView, self).get(request, *args, **kwargs)
-urlpatterns = patterns('',
+
+urlpatterns = [
url(r'^$', generic.TemplateView.as_view(template_name='home.html')),
url(r'^sleep/$', login_required(
SleepView.as_view(template_name='home.html')), name='sleep'),
url(r'^admin/', include(admin.site.urls)),
url(r'session_security/', include('session_security.urls')),
-)
+]
+
+if patterns:
+ urlpatterns = patterns('', *urlpatterns)
diff --git a/session_security/tests/project/wsgi.py b/session_security/tests/project/wsgi.py
new file mode 100644
index 0000000..6cf673d
--- /dev/null
+++ b/session_security/tests/project/wsgi.py
@@ -0,0 +1,16 @@
+"""
+WSGI config for project project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/dev/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
+
+application = get_wsgi_application()
diff --git a/session_security/tests/test_base.py b/session_security/tests/test_base.py
index 1ffb9e5..19027b7 100644
--- a/session_security/tests/test_base.py
+++ b/session_security/tests/test_base.py
@@ -1,34 +1,23 @@
import os
import time
+import atexit
from django.contrib.auth.models import User
-try:
- from django.contrib.staticfiles.testing import StaticLiveServerTestCase as \
- LiveServerTestCase
-except ImportError:
- from django.test import LiveServerTestCase
+from sbo_selenium import SeleniumTestCase
+
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
+from selenium.webdriver.phantomjs.webdriver import WebDriver
+from selenium.webdriver import Remote
+from django.contrib.staticfiles.testing import StaticLiveServerTestCase
-if os.environ.get('CI', False):
- from selenium.webdriver.phantomjs.webdriver import WebDriver
-else:
- from selenium.webdriver.chrome.webdriver import WebDriver
from selenium.common.exceptions import NoSuchElementException
from session_security.settings import WARN_AFTER, EXPIRE_AFTER
-def get_or_create_test_admin():
- u, c = User.objects.get_or_create(username='test')
-
- if c:
- u.is_staff = True
- u.set_password('test')
- u.save()
-
- return u
+WAIT_TIME = 5 if not os.environ.get('CI', False) else 30
class SettingsMixin(object):
@@ -36,42 +25,25 @@ class SettingsMixin(object):
# Give some time for selenium lag
self.min_warn_after = WARN_AFTER
self.max_warn_after = EXPIRE_AFTER * 0.9
+ self.min_expire_after = EXPIRE_AFTER
self.max_expire_after = EXPIRE_AFTER * 1.5
+ super(SettingsMixin, self).setUp()
-class BaseLiveServerTestCase(SettingsMixin, LiveServerTestCase):
- def setUp(self):
- super(BaseLiveServerTestCase, self).setUp()
- get_or_create_test_admin()
- self.browser = WebDriver()
- self.do_admin_login('test', 'test')
-
- def tearDown(self):
- self.browser.quit()
+class BaseLiveServerTestCase(SettingsMixin, StaticLiveServerTestCase,
+ SeleniumTestCase):
- def do_admin_login(self, username, password):
- self.browser.get('%s%s' % (self.live_server_url, '/admin/'))
- username_input = self.browser.find_element_by_name("username")
- username_input.send_keys(username)
- password_input = self.browser.find_element_by_name("password")
- password_input.send_keys(password)
- self.browser.find_element_by_xpath('//input[@value="Log in"]').click()
+ fixtures = ['session_security_test_user']
- def new_window(self, name='other'):
- self.browser.execute_script('window.open("/admin/", "'+ name +'")')
- self.browser.switch_to_window(self.browser.window_handles[1])
- while self.warning_element() is False:
- time.sleep(0.1)
- self.browser.switch_to_window(self.browser.window_handles[0])
+ def setUp(self):
+ super(BaseLiveServerTestCase, self).setUp()
+ self.get('/admin/')
+ self.sel.find_element_by_name('username').send_keys('test')
+ self.sel.find_element_by_name('password').send_keys('test')
+ self.sel.find_element_by_xpath('//input[@value="Log in"]').click()
+ self.sel.execute_script('window.open("/admin/", "other")')
def press_space(self):
- a = ActionChains(self.browser)
+ a = ActionChains(self.sel)
a.key_down(Keys.SPACE)
a.perform()
-
- def wait_for_pages_loaded(self):
- for win in self.browser.window_handles:
- self.browser.switch_to_window(win)
-
- while self.browser.execute_script('window.sessionSecurity === undefined'):
- time.sleep(0.1)
diff --git a/session_security/tests/test_middleware.py b/session_security/tests/test_middleware.py
index 5263019..fe0ba7a 100644
--- a/session_security/tests/test_middleware.py
+++ b/session_security/tests/test_middleware.py
@@ -2,16 +2,18 @@ import time
import unittest
from django.test.client import Client
+from django import test
from session_security.utils import set_last_activity
from datetime import datetime, timedelta
-from .test_base import get_or_create_test_admin, SettingsMixin
+from .test_base import SettingsMixin
-class MiddlewareTestCase(SettingsMixin, unittest.TestCase):
+class MiddlewareTestCase(SettingsMixin, test.TestCase):
+ fixtures = ['session_security_test_user']
+
def setUp(self):
super(MiddlewareTestCase, self).setUp()
- get_or_create_test_admin()
self.client = Client()
def test_auto_logout(self):
diff --git a/session_security/tests/test_script.py b/session_security/tests/test_script.py
index ebfa4be..dacda88 100644
--- a/session_security/tests/test_script.py
+++ b/session_security/tests/test_script.py
@@ -1,126 +1,57 @@
-from datetime import datetime
+import datetime
import time
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.firefox.webdriver import WebDriver
from selenium.common.exceptions import NoSuchElementException
+from selenium.webdriver.support.ui import WebDriverWait
+from selenium.webdriver.support import expected_conditions
+from selenium.webdriver.common.by import By
-from .test_base import BaseLiveServerTestCase
+from .test_base import BaseLiveServerTestCase, WAIT_TIME
-class ScriptTestCase(BaseLiveServerTestCase):
- def warning_element(self):
- try:
- return self.browser.find_elements_by_css_selector(
- '#session_security_warning')[0]
- except IndexError:
- return False
-
- def deadline_passed(self, now, deadline):
- return (datetime.now() - now).seconds > deadline
-
- def assertWarningShows(self, max_seconds):
- now = datetime.now()
-
- for win in self.browser.window_handles:
- self.browser.switch_to_window(win)
-
- while self.warning_element() is False:
- time.sleep(0.1)
-
- if self.deadline_passed(now, max_seconds):
- self.fail('Warning did not make it into DOM')
-
- for win in self.browser.window_handles:
- self.browser.switch_to_window(win)
-
- while self.warning_element().is_displayed() is False:
- time.sleep(0.1)
-
- if self.deadline_passed(now, max_seconds):
- self.fail('Warning did not make it into DOM')
-
- def assertWarningHides(self, max_seconds):
- now = datetime.now()
- for win in self.browser.window_handles:
- self.browser.switch_to_window(win)
-
- while self.warning_element().is_displayed() is not False:
- time.sleep(0.1)
-
- if self.deadline_passed(now, max_seconds):
- self.fail('Warning did not hide')
-
- def assertExpires(self, max_seconds):
- now = datetime.now()
-
- for win in self.browser.window_handles:
- self.browser.switch_to_window(win)
-
- while self.warning_element() is not False:
- time.sleep(0.1)
-
- if self.deadline_passed(now, max_seconds):
- self.fail('Warning did not make it out of DOM')
+class ScriptTestCase(BaseLiveServerTestCase):
+ def test_warning_shows_and_session_expires(self):
+ start = datetime.datetime.now()
- def assertWarningShown(self):
- for win in self.browser.window_handles:
- self.browser.switch_to_window(win)
- self.assertTrue(self.warning_element().is_displayed())
+ for win in self.sel.window_handles:
+ self.sel.switch_to_window(win)
+ self.wait_until_visible('#session_security_warning')
+ self.assert_visible('#session_security_warning')
- def assertWarningHidden(self):
- for win in self.browser.window_handles:
- self.browser.switch_to_window(win)
- self.assertFalse(self.warning_element().is_displayed())
+ end = datetime.datetime.now()
+ delta = end - start
- def assertWarningNotInPage(self):
- for win in self.browser.window_handles:
- self.browser.switch_to_window(win)
- self.assertTrue(self.warning_element() is False)
+ self.assertGreaterEqual(delta.seconds, self.min_warn_after)
+ self.assertLessEqual(delta.seconds, self.max_warn_after)
+ for win in self.sel.window_handles:
+ self.sel.switch_to_window(win)
+ self.wait_until_visible('#id_password')
- def test_single_window_inactivity(self):
- self.wait_for_pages_loaded()
- self.assertWarningHidden()
- self.assertWarningShows(self.max_warn_after)
- self.assertExpires(self.max_expire_after)
+ delta = datetime.datetime.now() - start
+ self.assertGreaterEqual(delta.seconds, self.min_expire_after)
+ self.assertLessEqual(delta.seconds, self.max_expire_after)
- def test_single_dont_show_warning(self):
- self.wait_for_pages_loaded()
- self.assertWarningHidden()
- time.sleep(self.min_warn_after * 0.5)
+ def test_activity_hides_warning(self):
+ self.wait_until_visible('#session_security_warning')
self.press_space()
- self.assertWarningHidden()
- time.sleep(self.min_warn_after * 0.5)
- self.assertWarningHidden()
- def test_single_hide_warning(self):
- self.assertWarningShows(self.max_warn_after)
- self.press_space()
- self.assertWarningHides(self.min_warn_after * 0.8)
+ for win in self.sel.window_handles:
+ self.sel.switch_to_window(win)
+ self.wait_until_hidden('#session_security_warning')
+ self.assert_not_visible('#session_security_warning')
- def test_double_window_inactivity(self):
- self.new_window()
- #self.wait_for_pages_loaded()
- self.assertWarningHidden()
- self.assertWarningShows(self.max_warn_after)
- self.assertExpires(self.max_expire_after)
-
- def test_double_dont_show_warning(self):
- self.new_window()
- self.wait_for_pages_loaded()
- self.assertWarningHidden()
- time.sleep(self.min_warn_after * 0.5)
+ def test_activity_prevents_warning(self):
+ time.sleep(self.min_warn_after * .7)
self.press_space()
- self.assertWarningHidden()
- time.sleep(self.min_warn_after * 0.5)
- self.assertWarningHidden()
- def test_double_hide_warning(self):
- self.new_window()
- self.assertWarningShows(self.max_warn_after)
- # Not fixing a race condition here ^^
- time.sleep(1)
- self.press_space()
- self.assertWarningHides(self.min_warn_after * 0.9)
+ start = datetime.datetime.now()
+ for win in self.sel.window_handles:
+ self.sel.switch_to_window(win)
+ self.wait_until_visible('#session_security_warning')
+ self.assert_visible('#session_security_warning')
+ delta = datetime.datetime.now() - start
+ self.assertGreaterEqual(delta.seconds, self.min_warn_after)
diff --git a/session_security/tests/test_views.py b/session_security/tests/test_views.py
index 3b85bb8..c451551 100644
--- a/session_security/tests/test_views.py
+++ b/session_security/tests/test_views.py
@@ -8,18 +8,18 @@ import unittest
from django.test.utils import override_settings
from django.test.client import Client
+from django import test
from unittest_data_provider import data_provider
from session_security.utils import set_last_activity
from session_security import settings
-from .test_base import get_or_create_test_admin
+class ViewsTestCase(test.TestCase):
+ fixtures = ['session_security_test_user']
-class ViewsTestCase(unittest.TestCase):
def setUp(self):
- get_or_create_test_admin()
self.client = Client()
def test_anonymous(self):
diff --git a/session_security/urls.py b/session_security/urls.py
index ee202c9..110fd66 100644
--- a/session_security/urls.py
+++ b/session_security/urls.py
@@ -15,9 +15,9 @@ ie::
"""
try:
- from django.conf.urls import url, patterns
+ from django.conf.urls import url
except ImportError:
- from django.conf.urls.defaults import url, patterns
+ from django.conf.urls.defaults import url
from .views import PingView
diff --git a/test_project/test_project/settings.py b/test_project/test_project/settings.py
index 866edd6..f1843f0 100644
--- a/test_project/test_project/settings.py
+++ b/test_project/test_project/settings.py
@@ -145,6 +145,7 @@ INSTALLED_APPS = (
# Uncomment the next line to enable the admin:
'django.contrib.admin',
'session_security',
+ 'sbo_selenium',
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
)
diff --git a/tox.ini b/tox.ini
index f8557bc..c6f47a4 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,26 +1,27 @@
[tox]
-envlist = py{27,34}-django{16,17,18,19}
+envlist = py{27,34}-django{17,18,19,110}
[testenv]
usedevelop = true
-changedir = test_project
-
commands =
- ./manage.py test {posargs:session_security}
-
+ coverage run {envbindir}/django-admin selenium --browser=phantomjs session_security
deps =
- django16: Django>=1.6,<1.7
- django17: Django>=1.7,<1.8
- django18: Django>=1.8,<1.9
- django19: Django>=1.9a1
six
unittest-data-provider
selenium
-
-whitelist_externals =
-
+ https://github.com/jpic/sbo-selenium/archive/django110.tar.gz
+ coverage
+ django17: Django>=1.7,<1.8
+ django18: Django>=1.8,<1.9
+ django19: Django>=1.9,<1.10
+ django110: https://github.com/django/django/archive/master.tar.gz
setenv =
- PYTHONPATH=test_project
- DJANGO_SETTINGS_MODULE=test_project.settings
+ PIP_ALLOW_EXTERNAL=true
+ DJANGO_SETTINGS_MODULE=session_security.tests.project.settings
+passenv = CI DISPLAY DBDIFF_* TEST_* TOX_* SAUCE_*
-passenv = CI DISPLAY
+[testenv:checkqa]
+basepython = python2.7
+commands = pep8 --ignore E128 --exclude project session_security
+deps =
+ pep8
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/django-session-security.git
More information about the Python-modules-commits
mailing list