diff --git a/.gitignore b/.gitignore
index 1512d933..7049a276 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+db.sqlite3
.tox/
*.pyc
*.egg-info
diff --git a/README.rst b/README.rst
index 45acb599..b4472220 100644
--- a/README.rst
+++ b/README.rst
@@ -545,9 +545,18 @@ following url::
Now if you go to the /test/ url you will see your SAML attributes and also
a link to do a global logout.
-You can also run the unit tests with the following command::
+Unit tests
+==========
+You can also run the unit tests as follows::
+
+ pip install -r requirements-dev.txt
+ python3 tests/manage.py migrate
+
python tests/run_tests.py
+ # or
+ pytest tests/* -x --pdb
+
If you have `tox`_ installed you can simply call tox inside the root directory
and it will run the tests in multiple versions of Python.
diff --git a/djangosaml2/tests/__init__.py b/djangosaml2/tests/__init__.py
index 2c210d27..663967bb 100644
--- a/djangosaml2/tests/__init__.py
+++ b/djangosaml2/tests/__init__.py
@@ -16,11 +16,9 @@
import base64
import datetime
-import mock
import re
import sys
-
-from unittest import skip
+from unittest import mock, skip
from django.conf import settings
from django.contrib.auth import SESSION_KEY, get_user_model
@@ -29,16 +27,17 @@
from django.template import Context, Template
from django.test import TestCase
from django.test.client import RequestFactory
+from saml2.config import SPConfig
+from saml2.s_utils import decode_base64_and_inflate, deflate_and_base64_encode
+
from djangosaml2 import views
from djangosaml2.cache import OutstandingQueriesCache
from djangosaml2.conf import get_config
from djangosaml2.signals import post_authenticated
from djangosaml2.tests import conf
-from djangosaml2.tests.utils import SAMLPostFormParser
from djangosaml2.tests.auth_response import auth_response
+from djangosaml2.tests.utils import SAMLPostFormParser
from djangosaml2.views import finish_logout
-from saml2.config import SPConfig
-from saml2.s_utils import decode_base64_and_inflate, deflate_and_base64_encode
try:
from django.urls import reverse
@@ -129,7 +128,11 @@ def test_unsigned_post_authn_request(self):
response_parser = SAMLPostFormParser()
response_parser.feed(response.content.decode('utf-8'))
saml_request = response_parser.saml_request_value
- expected_request = """http://sp.example.com/saml2/metadata/"""
+
+ if PY_VERSION < (3, 8):
+ expected_request = """http://sp.example.com/saml2/metadata/"""
+ else:
+ expected_request = """http://sp.example.com/saml2/metadata/"""
self.assertIsNotNone(saml_request)
self.assertSAMLRequestsEquals(
diff --git a/requirements-dev.txt b/requirements-dev.txt
new file mode 100644
index 00000000..125b4602
--- /dev/null
+++ b/requirements-dev.txt
@@ -0,0 +1,2 @@
+pytest
+pytest-django
diff --git a/tests/settings.py b/tests/settings.py
index a42e19c1..9ef59280 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -25,6 +25,9 @@
ALLOWED_HOSTS = []
INSTALLED_APPS = (
+ #'accounts',
+ 'testprofiles',
+
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
@@ -33,7 +36,6 @@
'django.contrib.staticfiles',
'djangosaml2',
- 'testprofiles',
)
MIDDLEWARE = (
diff --git a/tests/testprofiles/migrations/0001_initial.py b/tests/testprofiles/migrations/0001_initial.py
new file mode 100644
index 00000000..fa7b4208
--- /dev/null
+++ b/tests/testprofiles/migrations/0001_initial.py
@@ -0,0 +1,60 @@
+# Generated by Django 3.0.5 on 2020-05-01 14:54
+
+import django.contrib.auth.models
+import django.contrib.auth.validators
+from django.db import migrations, models
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('auth', '0011_update_proxy_permissions'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='RequiredFieldUser',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('email', models.EmailField(max_length=254, unique=True)),
+ ('email_verified', models.BooleanField()),
+ ],
+ ),
+ migrations.CreateModel(
+ name='StandaloneUserModel',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('username', models.CharField(max_length=30, unique=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='TestUser',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('password', models.CharField(max_length=128, verbose_name='password')),
+ ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
+ ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
+ ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
+ ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')),
+ ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
+ ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
+ ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
+ ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
+ ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
+ ('age', models.CharField(blank=True, max_length=100)),
+ ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
+ ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
+ ],
+ options={
+ 'verbose_name': 'user',
+ 'verbose_name_plural': 'users',
+ 'abstract': False,
+ },
+ managers=[
+ ('objects', django.contrib.auth.models.UserManager()),
+ ],
+ ),
+ ]
diff --git a/tests/testprofiles/migrations/__init__.py b/tests/testprofiles/migrations/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tox.ini b/tox.ini
index 921ab538..9c94d89e 100644
--- a/tox.ini
+++ b/tox.ini
@@ -7,9 +7,8 @@ commands =
python tests/run_tests.py
deps =
- mock
- django22: Django>=2.2,<3.0
- django30: Django>=3.0,<3.1
+ django2.2: django~=2.2
+ django3.0: django~=3.0
djangomaster: https://github.com/django/django/archive/master.tar.gz
.[test]