Good day everyone.
I would like to ask you if this incorrect behaviour is something known.
First, I am using Django 1.8.2, Python 3.4.3, Python Tools for Visual Studio 2.2RC, VS2013, Windows 8.1, msysgit 1.9.5.
A made a unit test which was supposed to fail, and it did fail from the visual studio test runner, but it was successfully passed when I ran it from the command line using manage.py test command.
I run tests in command as follows: manage.py test --settings=monodemo.settings.dev_russ
This assert does not fail in Django test runner when my Form View (CBV) has a success_url='dashboard:dashboard':
self.assertEqual(self.client.session[SESSION_KEY], str(user.pk))
But it does fail in VS and it should because the return status code was 400 in any case. In visual studio unit tests, it was raising KeyError:'_auth_user_id'.
Also, I realised that I forgot to add 'dashboard' project into installed_apps but it was not affecting the result of the test.
My dependencies:
Django==1.8.2
psycopg2==2.6 (taken from here http://www.stickpeople.com/projects/python/win-psycopg/ and then manually installed into the virtual environment; direct download link: http://www.stickpeople.com/projects/python/win-psycopg/2.6.0/psycopg2-2.6.0.win32-py3.4-pg9.4.1-release.exe )
Unipath==1.1
Please advise if this is something to worry or if I have improperly configured something.
Thank you all in advance!
Ruslan (Russ) Bazhenov
I have attached pretty much all the related code down there. (Tried to exclude what was not related, though)
#monodemo/registration/tests/base.py
import django
from django.test import TestCase
from django.test.utils import setup_test_environment
from django.contrib.auth.models import User
class AbstractTestCase(TestCase):
"""Utility base class for all tests for this app as it contains helper functions"""
@classmethod
def setUpClass(cls):
"""One time Django setup sequence.
It is needed for correct testing outside of django test runner
For example in the UnitTest test runner or the one used in VS"""
setup_test_environment()
django.setup()
super().setUpClass()
def prepare_user(self, username):
"""Creates, saves and returns test user"""
# An interesting observation
# By default a user iscreated ACTIVE
return User.objects.create_user(username=username,
email='test@example.com',
password='glassfish100500'
)
#monodemo/registration/tests/test_views.py
from django.core.urlresolvers import reverse
from django.contrib.auth import SESSION_KEY
from registration.forms import UserLoginForm
from .base import AbstractTestCase
class LoginViewTests(AbstractTestCase):
"""Tests for the Registration app views."""
def test_can_login(self):
"""Verifies that a user can authenticate"""
user = super().prepare_user('Sucker')
email = 'test@example.com'
password = 'glassfish100500'
response = self.client.post(reverse('home_page'), data={'email':email,
'password':password,
'remember_me':True
})
self.assertEqual(self.client.session[SESSION_KEY], str(user.pk))
#monodemo/registration/views.py
from django.views.generic import FormView
from django.contrib.auth import login
from registration.forms import UserLoginForm
class LoginView(FormView):
"""User authentication view"""
template_name = 'registration/registration_login.html'
form_class = UserLoginForm
success_url = 'dashboard:dashboard'
def form_valid(self, form):
"""Logs a verified user in after form is validated"""
user = form.get_user()
login(self.request, user)
return super().form_valid(form)
#monodemo/registration/forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth import authenticate
class UserLoginForm(forms.Form):
"""Verifies login details"""
email = forms.EmailField(widget=forms.TextInput(attrs={'class': 'text',
'placeholder': 'Email',
}))
password = forms.CharField(max_length=128,
widget=forms.PasswordInput(attrs={'class': 'text',
'placeholder': 'Password',
}))
remember_me = forms.BooleanField(required=False,
label='remember me',
widget=forms.CheckboxInput(attrs={'class': 'checkbox',}))
def clean(self):
"""User verification. Other data does not require validation
because it will be handled by authenticate()
"""
cleaned_data = super(UserLoginForm, self).clean()
email = cleaned_data.get("email")
password = cleaned_data.get("password")
try:
user = User.objects.get(email=email)
except (User.DoesNotExist, User.MultipleObjectsReturned):
raise forms.ValidationError("The email address or password were incorrect")
user = authenticate(username=user.username, password=password)
if user is None:
raise forms.ValidationError("The email address or password were incorrect")
if user.is_active != True:
raise forms.ValidationError("The email address or password were incorrect")
# Dirty hack or fancy Python?
def get_user():
return user
self.get_user = get_user
#monodemo/monodemo/urls.py
from django.conf.urls import include, url
from django.contrib import admin
from registration.views import LoginView
urlpatterns = [
url(r'^$', LoginView.as_view(), name='home_page'),
url(r'^auth/', include('registration.urls', namespace='registration')),
url(r'^dashboard/', include('dashboard.urls', namespace='dashboard')),
url(r'^admin/', include(admin.site.urls)),
]
#monodemo/registration/urls.py
from django.conf.urls import include, url
urlpatterns = [
]
#monodemo/dashboard/urls.py
from django.conf.urls import url
from .views import LoginView
urlpatterns = [
url(r'^$', LoginView.as_view(), name='dashboard'),
]
#monodemo/dashboard/views.py
from django.views.generic import TemplateView
class LoginView(TemplateView):
template_name = 'dashboard/base_dashboard.html'
#monodemo/monodemo/settings/base.py
import json
from django.core.exceptions import ImproperlyConfigured
from unipath import Path
BASE_DIR = Path(__file__).ancestor(3)
MEDIA_ROOT = BASE_DIR.child("media")
STATIC_ROOT = BASE_DIR.child("static")
STATIC_URL = "/static/"
STATICFILES_DIRS = (
BASE_DIR.child("assets"),
)
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
# JSON-based secrets module
with open(BASE_DIR.child("monodemo", "settings", "secrets.json")) as f:
secrets = json.loads(f.read())
def get_secret(setting, secrets=secrets):
"""Get the secret variable or return explicit exception."""
try:
return secrets[setting]
except KeyError:
error_msg = "Set the {0} environment variable".format(setting)
raise ImproperlyConfigured(error_msg)
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = get_secret("SECRET_KEY")
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'registration'
)
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',
'django.middleware.security.SecurityMiddleware',
)
ROOT_URLCONF = 'monodemo.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': (
BASE_DIR.child("templates"),
),
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.contrib.auth.context_processors.auth',
'django.template.context_processors.request',
'django.template.context_processors.debug',
'django.template.context_processors.i18n',
'django.template.context_processors.media',
'django.template.context_processors.static',
'django.template.context_processors.tz',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'monodemo.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': get_secret("NAME"),
'USER': get_secret("USER"),
'PASSWORD': get_secret("PASSWORD"),
}
}
# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/
LANGUAGE_CODE = 'en-GB'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
#monodemo/monodemo/settings/local.py
from .base import *
DEBUG = True
#monodemo/monodemo/settings/dev_russ.py
from .local import *
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/b9d700ec-504f-4d06-be43-cd418fb13c27%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
No comments:
Post a Comment