UPD: improved tests.

This commit is contained in:
2019-03-13 18:38:58 +01:00
parent c39f09709b
commit 848db26516
7 changed files with 369 additions and 52 deletions

View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
from django.contrib.auth import get_user_model
from django.core import mail as django_mail
from django.test import TestCase
@@ -6,7 +7,7 @@ from ..emails import PasswordSetEmail
TEST_USERNAME = 'user'
TEST_PASSWORD = 'mellon12'
TEST_PASSWORD = u'me||ön 2'
TEST_EMAIL = 'root@localhost'

View File

@@ -2,14 +2,16 @@
from unittest import skip
from django.contrib.auth import get_user_model
from django.core import mail as django_mail
from django.utils.translation import ugettext
from dav_base.tests.generic import FormDataSet, FormsTestCase
from ..forms import LoginForm, SetPasswordForm, ResetPasswordForm
TEST_USERNAME = 'root@localhost'
TEST_PASSWORD = 'mellon12'
TEST_PASSWORD = u'me||ön 2'
TEST_EMAIL = TEST_USERNAME
USERNAME_MAX_LENGTH = 254
class LoginFormTestCase(FormsTestCase):
@@ -22,42 +24,57 @@ class LoginFormTestCase(FormsTestCase):
model = get_user_model()
self.user = model.objects.create_user(username=TEST_USERNAME, password=TEST_PASSWORD, email=TEST_EMAIL)
def test_login_username_empty(self):
def test_length(self):
form = self.form_class()
self.assertEqual(form.fields['username'].max_length, USERNAME_MAX_LENGTH)
self.assertEqual(form.fields['password'].max_length, None)
def test_labels(self):
form = self.form_class()
self.assertEqual(form.fields['username'].label, ugettext(u'E-Mail-Adresse'))
self.assertEqual(form.fields['password'].label, ugettext(u'Password'))
def test_required(self):
form = self.form_class()
self.assertTrue(form.fields['username'].required)
self.assertTrue(form.fields['password'].required)
def test_username_empty(self):
data_sets = [
FormDataSet({'username': '', 'password': self.test_password},
expected_errors=[('username', 'required')]),
]
super(LoginFormTestCase, self).test_invalid_data(data_sets=data_sets)
def test_login_password_empty(self):
def test_password_empty(self):
data_sets = [
FormDataSet({'username': self.test_username, 'password': ''},
expected_errors=[('password', 'required')]),
]
super(LoginFormTestCase, self).test_invalid_data(data_sets=data_sets)
def test_login_username_too_long(self):
def test_username_too_long(self):
data_sets = [
FormDataSet({'username': 'u' * 255, 'password': self.test_password},
FormDataSet({'username': 'u' * USERNAME_MAX_LENGTH + 'u', 'password': self.test_password},
expected_errors=[('username', 'max_length')]),
]
super(LoginFormTestCase, self).test_invalid_data(data_sets=data_sets)
def test_login_invalid_username(self):
def test_invalid_username(self):
data_sets = [
FormDataSet({'username': self.test_username[::-1], 'password': self.test_password},
expected_errors=[('__all__', 'invalid_login')]),
]
super(LoginFormTestCase, self).test_invalid_data(data_sets=data_sets)
def test_login_invalid_password(self):
def test_invalid_password(self):
data_sets = [
FormDataSet({'username': self.test_username, 'password': self.test_password[::-1]},
expected_errors=[('__all__', 'invalid_login')]),
]
super(LoginFormTestCase, self).test_invalid_data(data_sets=data_sets)
def test_login_inactive_user(self):
def test_inactive_user(self):
self.user.is_active = False
self.user.save()
data_sets = [
@@ -66,7 +83,7 @@ class LoginFormTestCase(FormsTestCase):
]
super(LoginFormTestCase, self).test_invalid_data(data_sets=data_sets)
def test_login_valid_credentials(self):
def test_valid_credentials(self):
data_sets = [
FormDataSet({'username': self.test_username, 'password': self.test_password}),
]
@@ -83,49 +100,55 @@ class SetPasswordFormTestCase(FormsTestCase):
model = get_user_model()
self.user = model.objects.create_user(username=TEST_USERNAME, password=TEST_PASSWORD, email=TEST_EMAIL)
def test_set_password_mismatch(self):
def test_required(self):
form = self.form_class(user=self.user)
self.assertTrue(form.fields['new_password'].required)
self.assertTrue(form.fields['new_password_repeat'].required)
self.assertFalse(form.fields['send_password_mail'].required)
def test_mismatch(self):
data_sets = [
FormDataSet({'new_password': 'mellon12', 'new_password_repeat': 'mellon13'},
[('new_password_repeat', 'password_mismatch')]),
]
super(SetPasswordFormTestCase, self).test_invalid_data(data_sets=data_sets, form_kwargs={'user': self.user})
def test_set_password_empty(self):
def test_empty(self):
data_sets = [
FormDataSet({'new_password': '', 'new_password_repeat': ''},
[('new_password', 'required')]),
]
super(SetPasswordFormTestCase, self).test_invalid_data(data_sets=data_sets, form_kwargs={'user': self.user})
def test_set_password_too_short(self):
def test_too_short(self):
data_sets = [
FormDataSet({'new_password': 'mellon', 'new_password_repeat': 'mellon'},
[('new_password', 'password_too_short')]),
]
super(SetPasswordFormTestCase, self).test_invalid_data(data_sets=data_sets, form_kwargs={'user': self.user})
def test_set_password_entirely_numeric(self):
def test_entirely_numeric(self):
data_sets = [
FormDataSet({'new_password': '1357924680', 'new_password_repeat': '1357924680'},
[('new_password', 'password_entirely_numeric')]),
]
super(SetPasswordFormTestCase, self).test_invalid_data(data_sets=data_sets, form_kwargs={'user': self.user})
def test_set_password_too_similar(self):
def test_too_similar(self):
data_sets = [
FormDataSet({'new_password': self.test_username, 'new_password_repeat': self.test_username},
[('new_password', 'password_too_similar')]),
]
super(SetPasswordFormTestCase, self).test_invalid_data(data_sets=data_sets, form_kwargs={'user': self.user})
def test_set_password_too_common(self):
def test_too_common(self):
data_sets = [
FormDataSet({'new_password': 'password', 'new_password_repeat': 'password'},
[('new_password', 'password_too_common')]),
]
super(SetPasswordFormTestCase, self).test_invalid_data(data_sets=data_sets, form_kwargs={'user': self.user})
def test_set_password_valid(self):
def test_valid(self):
data_sets = [
FormDataSet({'new_password': 'mellon12', 'new_password_repeat': 'mellon12'}),
FormDataSet({'new_password': 'mellon12', 'new_password_repeat': 'mellon12', 'send_password_mail': True}),
@@ -134,7 +157,7 @@ class SetPasswordFormTestCase(FormsTestCase):
]
super(SetPasswordFormTestCase, self).test_valid_data(data_sets=data_sets, form_kwargs={'user': self.user})
def test_set_password_save(self):
def test_save(self):
new_passwords = [
u'"ä§ Mellon12'
'mellon12' * 128,
@@ -149,7 +172,7 @@ class SetPasswordFormTestCase(FormsTestCase):
self.assertTrue(self.client.login(username=self.test_username, password=new_password))
@skip('Function is implemented in SetPasswordView instead of SetPasswordForm')
def test_set_password_save_with_mail(self):
def test_save_with_mail(self):
new_passwords = [
u'"ä§ Mellon12'
'mellon12' * 128,
@@ -178,5 +201,17 @@ class ResetPasswordFormTestCase(FormsTestCase):
)
invalid_data_sets = (
FormDataSet({'username': ''}, expected_errors=[('username', 'required')]),
FormDataSet({'username': 'u' * 255}, expected_errors=[('username', 'max_length')]),
FormDataSet({'username': 'u' * USERNAME_MAX_LENGTH + 'u'}, expected_errors=[('username', 'max_length')]),
)
def test_length(self):
form = self.form_class()
self.assertEqual(form.fields['username'].max_length, USERNAME_MAX_LENGTH)
def test_labels(self):
form = self.form_class()
self.assertEqual(form.fields['username'].label, ugettext(u'E-Mail-Adresse'))
def test_required(self):
form = self.form_class()
self.assertTrue(form.fields['username'].required)

View File

@@ -1,19 +1,190 @@
# -*- coding: utf-8 -*-
from django.contrib.auth import get_user_model
from django.test import tag
from django.urls import reverse
from django.utils.translation import ugettext
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from dav_base.tests.generic import skip_unless_tag_option, ScreenshotTestCase
TEST_USERNAME = 'root@localhost'
TEST_PASSWORD = u'me||ön 2'
TEST_EMAIL = TEST_USERNAME
#@skip_unless_tag_option()
#@tag('screenshots')
@skip_unless_tag_option()
@tag('screenshots')
class TestCase(ScreenshotTestCase):
def test_some(self):
screenshot_prefix = 'dav_auth-'
def setUp(self):
super(TestCase, self).setUp()
# Need a test user
self.test_username = TEST_USERNAME
self.test_password = TEST_PASSWORD
model = get_user_model()
self.user = model.objects.create_user(username=TEST_USERNAME, password=TEST_PASSWORD, email=TEST_EMAIL)
def test_screenshots(self):
sequence_name = 'walkthrough'
# Go to login page via login button on root page -> save plain login form
c = self.selenium
c.get(self.complete_url('/'))
link = c.find_element_by_css_selector('#login-widget a')
link.click()
self.save_screenshot('login-form')
link = c.find_element_by_link_text('Passwort vergessen?')
self.wait_on_presence(c, (By.ID, 'id_username'))
self.save_screenshot(sequence=sequence_name)
# Fill in a password -> Save dots in password field
username_field = c.find_element_by_id('id_username')
username_field.clear()
username_field.send_keys('username')
password_field = c.find_element_by_id('id_password')
password_field.clear()
password_field.send_keys(self.test_password)
self.save_screenshot(sequence=sequence_name)
# Wrong username -> save error message
username_field = c.find_element_by_id('id_username')
username_field.clear()
username_field.send_keys(self.test_username[::-1])
password_field = c.find_element_by_id('id_password')
password_field.clear()
password_field.send_keys(self.test_password)
password_field.send_keys(Keys.RETURN)
alert_button = self.wait_on_presence(c, (By.CSS_SELECTOR, 'form .alert-danger button.close'))
self.save_screenshot(sequence=sequence_name)
alert_button.click()
# Wrong password -> save error message
username_field = c.find_element_by_id('id_username')
username_field.clear()
username_field.send_keys(self.test_username)
password_field = c.find_element_by_id('id_password')
password_field.clear()
password_field.send_keys(self.test_password[::-1])
password_field.send_keys(Keys.RETURN)
alert_button = self.wait_on_presence(c, (By.CSS_SELECTOR, 'form .alert-danger button.close'))
self.save_screenshot(sequence=sequence_name)
alert_button.click()
# Login of inactive user -> save error message
self.user.is_active = False
self.user.save()
username_field = c.find_element_by_id('id_username')
username_field.clear()
username_field.send_keys(self.test_username)
password_field = c.find_element_by_id('id_password')
password_field.clear()
password_field.send_keys(self.test_password)
password_field.send_keys(Keys.RETURN)
alert_button = self.wait_on_presence(c, (By.CSS_SELECTOR, 'form .alert-danger button.close'))
self.save_screenshot(sequence=sequence_name)
alert_button.click()
# Reactivate test user again
self.user.is_active = True
self.user.save()
# Login -> save success message
username_field = c.find_element_by_id('id_username')
username_field.clear()
username_field.send_keys(self.test_username)
password_field = c.find_element_by_id('id_password')
password_field.clear()
password_field.send_keys(self.test_password)
password_field.send_keys(Keys.RETURN)
alert_button = self.wait_on_presence(c, (By.CSS_SELECTOR, '#messages .alert-success button.close'))
self.save_screenshot(sequence=sequence_name)
alert_button.click()
# Open user dropdown menu -> save menu
dropdown_button = self.wait_on_presence(c, (By.ID, 'user_dropdown_button'))
dropdown_button.click()
self.save_screenshot(sequence=sequence_name)
# Click on 'set password' -> save set password page
user_menu = c.find_element_by_css_selector('#login-widget ul')
link = user_menu.find_element_by_partial_link_text(ugettext(u'Passwort ändern'))
link.click()
self.save_screenshot('reset-password-form')
self.wait_on_presence(c, (By.ID, 'id_new_password'))
self.save_screenshot(sequence=sequence_name)
# Fill in a password -> Save dots in password field
password_field = c.find_element_by_id('id_new_password')
password_field.clear()
password_field.send_keys(self.test_password)
password2_field = c.find_element_by_id('id_new_password_repeat')
password2_field.clear()
password2_field.send_keys(self.test_password)
self.save_screenshot(sequence=sequence_name)
# New passwords mismatch -> save error message
password_field = c.find_element_by_id('id_new_password')
password_field.clear()
password_field.send_keys(self.test_password)
password2_field = c.find_element_by_id('id_new_password_repeat')
password2_field.clear()
password2_field.send_keys(self.test_password[::-1])
password2_field.send_keys(Keys.RETURN)
self.wait_until_stale(c, password2_field)
self.save_screenshot(sequence=sequence_name)
# New passwords too common and too short -> save error message
password = 'abcdef'
password_field = c.find_element_by_id('id_new_password')
password_field.clear()
password_field.send_keys(password)
password2_field = c.find_element_by_id('id_new_password_repeat')
password2_field.clear()
password2_field.send_keys(password)
password2_field.send_keys(Keys.RETURN)
self.wait_until_stale(c, password2_field)
self.save_screenshot(sequence=sequence_name)
# New passwords entirely_numeric -> save error message
password = '9126735804'
password_field = c.find_element_by_id('id_new_password')
password_field.clear()
password_field.send_keys(password)
password2_field = c.find_element_by_id('id_new_password_repeat')
password2_field.clear()
password2_field.send_keys(password)
password2_field.send_keys(Keys.RETURN)
self.wait_until_stale(c, password2_field)
self.save_screenshot(sequence=sequence_name)
# New passwords too similar -> save error message
password = self.test_username
password_field = c.find_element_by_id('id_new_password')
password_field.clear()
password_field.send_keys(password)
password2_field = c.find_element_by_id('id_new_password_repeat')
password2_field.clear()
password2_field.send_keys(password)
password2_field.send_keys(Keys.RETURN)
self.wait_until_stale(c, password2_field)
self.save_screenshot(sequence=sequence_name)
# Change password -> save success message
password = self.test_password[::-1]
password_field = c.find_element_by_id('id_new_password')
password_field.clear()
password_field.send_keys(password)
password2_field = c.find_element_by_id('id_new_password_repeat')
password2_field.clear()
password2_field.send_keys(password)
password2_field.send_keys(Keys.RETURN)
self.wait_until_stale(c, password2_field)
self.save_screenshot(sequence=sequence_name)
# Click on 'logout' -> save page
dropdown_button = self.wait_on_presence(c, (By.ID, 'user_dropdown_button'))
dropdown_button.click()
user_menu = c.find_element_by_css_selector('#login-widget ul')
link = user_menu.find_element_by_partial_link_text(ugettext(u'Logout'))
link.click()
self.wait_until_stale(c, user_menu)
self.save_screenshot(sequence=sequence_name)

View File

@@ -1,7 +1,18 @@
# -*- coding: utf-8 -*-
from django.test import SimpleTestCase
from django.contrib.auth import get_user_model
from django.test import SimpleTestCase, tag
from django.utils.translation import ugettext
from django.urls import reverse
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from unittest import skip
from dav_base.tests.generic import SeleniumTestCase
TEST_USERNAME = 'root@localhost'
TEST_PASSWORD = u'me||ön 2'
TEST_EMAIL = TEST_USERNAME
class TemplatesTestCase(SimpleTestCase):
@@ -12,3 +23,58 @@ class TemplatesTestCase(SimpleTestCase):
html = u'<a href="{url}">{text}</a>'.format(url=reset_url, text=text)
response = self.client.get(login_url)
self.assertInHTML(html, response.content)
@tag('browser')
class TestCase(SeleniumTestCase):
def setUp(self):
super(TestCase, self).setUp()
# Need a test user
self.test_username = TEST_USERNAME
self.test_password = TEST_PASSWORD
model = get_user_model()
self.user = model.objects.create_user(username=TEST_USERNAME, password=TEST_PASSWORD, email=TEST_EMAIL)
def _login(self, driver):
url = self.complete_url(reverse('dav_auth:login'))
driver.get(url)
username_field = self.wait_on_presence(driver, (By.ID, "id_username"))
username_field.clear()
username_field.send_keys(self.test_username)
password_field = driver.find_element_by_id('id_password')
password_field.clear()
password_field.send_keys(self.test_password)
password_field.send_keys(Keys.RETURN)
self.wait_on_presence(driver, (By.CSS_SELECTOR, "#messages .alert-success"))
return driver
def test_login_button_in_root_page(self):
c = self.selenium
c.get(self.complete_url('/'))
try:
link = c.find_element_by_css_selector('#login-widget a')
except NoSuchElementException as e:
self.fail(str(e))
def test_required_fields_in_login_form(self):
c = self.selenium
location = reverse('dav_auth:login')
c.get(self.complete_url(location))
field = c.find_element_by_id('id_username')
self.assertEqual(field.get_attribute('required'), u'true')
field = c.find_element_by_id('id_password')
self.assertEqual(field.get_attribute('required'), u'true')
def test_required_fields_in_set_password_form(self):
c = self._login(self.selenium)
c.get(self.complete_url(reverse('dav_auth:set_password')))
field = self.wait_on_presence(c, (By.ID, "id_new_password"))
self.assertEqual(field.get_attribute('required'), u'true')
field = c.find_element_by_id('id_new_password_repeat')
self.assertEqual(field.get_attribute('required'), u'true')
field = c.find_element_by_id('id_send_password_mail')
self.assertEqual(field.get_attribute('required'), None)

View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
from django.apps import apps
from django.contrib.auth import get_user_model
from django.core import mail as django_mail
@@ -9,7 +10,7 @@ from django.urls import reverse
from ..forms import LoginForm, SetPasswordForm, ResetPasswordForm
TEST_USERNAME = 'root@localhost'
TEST_PASSWORD = 'mellon12'
TEST_PASSWORD = u'me||ön 2'
TEST_EMAIL = TEST_USERNAME
@@ -34,6 +35,7 @@ class ViewsTestCase(TestCase):
cls.set_password_message = ugettext(u'Passwort gespeichert.')
def setUp(self):
super(TestCase, self).setUp()
# Need a test user
self.test_username = TEST_USERNAME
self.test_password = TEST_PASSWORD
@@ -47,6 +49,11 @@ class ViewsTestCase(TestCase):
self.assertIn('form', response.context)
self.assertIsInstance(response.context['form'], LoginForm)
field = response.context['form'].fields['username']
self.assertTrue(field.required)
field = response.context['form'].fields['password']
self.assertTrue(field.required)
def test_integrated_login_inactive_user(self):
user = self.user
user.is_active = False
@@ -179,6 +186,9 @@ class ViewsTestCase(TestCase):
self.assertIn('form', response.context)
self.assertIsInstance(response.context['form'], ResetPasswordForm)
field = response.context['form'].fields['username']
self.assertTrue(field.required)
def test_reset_password_integrated_post(self):
location = self.reset_password_url

View File

@@ -7,6 +7,8 @@ from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from django.test import SimpleTestCase, TestCase, tag
from django.urls import reverse
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def skip_unless_tag_option():
@@ -126,7 +128,33 @@ class FormsTestCase(TestCase):
self.assertIn(code, error_codes)
class ScreenshotTestCase(StaticLiveServerTestCase):
class SeleniumTestCase(StaticLiveServerTestCase):
def setUp(self):
super(SeleniumTestCase, self).setUp()
self.selenium = webdriver.Firefox()
if not hasattr(self, 'quit_selenium'):
self.quit_selenium = True
def tearDown(self):
if hasattr(self, 'quit_selenium') and self.quit_selenium:
self.selenium.quit()
super(SeleniumTestCase, self).tearDown()
def complete_url(self, location):
base_url = self.live_server_url
return '{}/{}'.format(base_url, location.lstrip('/'))
def wait_until_stale(self, driver, element, timeout=30):
return WebDriverWait(driver, timeout).until(EC.staleness_of(element))
def wait_on_presence(self, driver, locator, timeout=30):
return WebDriverWait(driver, timeout).until(EC.presence_of_element_located(locator))
class ScreenshotTestCase(SeleniumTestCase):
screenshot_prefix = ''
window_width = 1024
window_height = 768
locations = ()
@classmethod
@@ -136,18 +164,12 @@ class ScreenshotTestCase(StaticLiveServerTestCase):
# screenshot_base_dir = os.path.join('/', 'tmp', 'test-screenshots')
screenshot_base_dir = 'test-screenshots'
cls.screenshot_path = screenshot_base_dir
cls.screenshot_sequences = {}
def setUp(self):
super(ScreenshotTestCase, self).setUp()
self.selenium = webdriver.Firefox()
self.selenium.set_window_size(1024, 768)
def tearDown(self):
self.selenium.quit()
super(ScreenshotTestCase, self).tearDown()
def complete_url(self, location):
return '{}/{}'.format(self.live_server_url, location.lstrip('/'))
if self.window_width and self.window_height:
self.selenium.set_window_size(self.window_width, self.window_height)
def sanitize_filename(self, location):
location = location.lstrip('/')
@@ -156,21 +178,32 @@ class ScreenshotTestCase(StaticLiveServerTestCase):
r = urllib.quote(location, '')
return r
def save_screenshot(self, name=None):
if self.screenshot_path:
if name is None:
location = self.selenium.current_url
if location.startswith(self.live_server_url):
location = location[len(self.live_server_url):]
name = location
def save_screenshot(self, name=None, sequence=None):
if name is not None:
pass
elif sequence is not None:
if sequence in self.screenshot_sequences:
self.screenshot_sequences[sequence] += 1
else:
self.screenshot_sequences[sequence] = 1
n = self.screenshot_sequences[sequence]
name = '%s-%04d' % (sequence, n)
else:
location = self.selenium.current_url
if location.startswith(self.live_server_url):
location = location[len(self.live_server_url):]
name = location
now = datetime.datetime.now()
base_name = '{timestamp}-{name}.png'.format(name=self.sanitize_filename(name),
timestamp=now.strftime('%Y%m%d-%H%M%S'))
path = os.path.join(self.screenshot_path, base_name)
if not os.path.isdir(self.screenshot_path):
os.makedirs(self.screenshot_path, 0700)
self.selenium.save_screenshot(path)
now = datetime.datetime.now()
base_name = '{timestamp}-{prefix}{name}.png'.format(
prefix=self.screenshot_prefix,
name=self.sanitize_filename(name),
timestamp=now.strftime('%Y%m%d-%H%M%S')
)
path = os.path.join(self.screenshot_path, base_name)
if not os.path.isdir(self.screenshot_path):
os.makedirs(self.screenshot_path, 0700)
self.selenium.save_screenshot(path)
@skip_unless_tag_option()
@tag('screenshots')

View File

@@ -2,6 +2,7 @@ from .generic import ScreenshotTestCase
class TestCase(ScreenshotTestCase):
screenshot_prefix = 'dav_base-'
locations = (
'/',
'404',