UPD: more tests.

This commit is contained in:
2019-03-21 17:59:35 +01:00
parent ff32ffbc1e
commit 1bcd479304
2 changed files with 592 additions and 26 deletions

View File

@@ -1,12 +1,14 @@
import datetime
import os
import sys
import time
import urllib
from unittest import skip
from unittest import skip, SkipTest
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.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
@@ -157,14 +159,27 @@ class FormsTestCase(TestCase):
class SeleniumTestCase(StaticLiveServerTestCase):
def setUp(self):
super(SeleniumTestCase, self).setUp()
self.selenium = webdriver.Firefox()
if not hasattr(self, 'quit_selenium'):
self.quit_selenium = True
window_width = 1024
window_height = 768
def __init__(self, *args, **kwargs):
super(SeleniumTestCase, self).__init__(*args, **kwargs)
self._driver = None
self._driver_options = webdriver.FirefoxOptions()
self.quit_selenium = None
@property
def selenium(self):
if self._driver is None:
self._driver = webdriver.Firefox(options=self._driver_options)
if self.quit_selenium is None:
self.quit_selenium = True
if self.window_width and self.window_height:
self._driver.set_window_size(self.window_width, self.window_height)
return self._driver
def tearDown(self):
if hasattr(self, 'quit_selenium') and self.quit_selenium:
if self.quit_selenium:
self.selenium.quit()
super(SeleniumTestCase, self).tearDown()
@@ -172,37 +187,37 @@ class SeleniumTestCase(StaticLiveServerTestCase):
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 get(self, location):
return self.selenium.get(self.complete_url(location))
def wait_on(self, driver, ec_name, ec_argument, timeout=30):
ec = getattr(EC, ec_name)
return WebDriverWait(driver, timeout).until(ec(ec_argument))
def wait_on_presence(self, driver, locator, timeout=30):
return WebDriverWait(driver, timeout).until(EC.presence_of_element_located(locator))
ec_name = 'presence_of_element_located'
return self.wait_on(driver, ec_name, locator, timeout)
def wait_until_stale(self, driver, element, timeout=30):
ec_name = 'staleness_of'
return self.wait_on(driver, ec_name, element, timeout)
class ScreenshotTestCase(SeleniumTestCase):
screenshot_prefix = ''
window_width = 1024
window_height = 768
locations = ()
@classmethod
def setUpClass(cls):
super(ScreenshotTestCase, cls).setUpClass()
def __init__(self, *args, **kwargs):
super(ScreenshotTestCase, self).__init__(*args, **kwargs)
# 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()
if self.window_width and self.window_height:
self.selenium.set_window_size(self.window_width, self.window_height)
self.screenshot_path = screenshot_base_dir
self.screenshot_sequences = {}
def sanitize_filename(self, location):
return urllib.quote(location).replace('/', '--')
def save_screenshot(self, title=None, sequence=None):
def save_screenshot(self, title=None, sequence=None, resize=True):
if sequence is None:
sequence = ''
else:
@@ -230,10 +245,20 @@ class ScreenshotTestCase(SeleniumTestCase):
path = os.path.join(self.screenshot_path, self.sanitize_filename(base_name))
if not os.path.isdir(self.screenshot_path):
os.makedirs(self.screenshot_path, 0700)
restore_size = False
if resize:
window_size = self.selenium.get_window_size()
deco_height = self.selenium.execute_script('return window.outerHeight - window.innerHeight')
doc_height = self.selenium.execute_script('return document.body.scrollHeight')
if (window_size['height'] - deco_height) < doc_height:
self.selenium.set_window_size(window_size['width'], doc_height + deco_height)
restore_size = True
self.selenium.save_screenshot(path)
def get(self, location):
return self.selenium.get(self.complete_url(location))
if restore_size:
self.selenium.set_window_size(window_size['width'], window_size['height'])
@skip_unless_tag_option()
@tag('screenshots')

View File

@@ -0,0 +1,541 @@
# -*- coding: utf-8 -*-
import datetime
import time
from django.apps import apps
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from django.test import tag
from django.urls import reverse
from django.utils.translation import ugettext
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from dav_base.tests.generic import skip_unless_tag_option, ScreenshotTestCase
TEST_PASSWORD = u'me||ön 2'
TEST_EVENT_DATA_S = {
'mode': 'training',
'sport': 'S',
'ski_lift': True,
'first_day': '24.12.2019',
'last_day': '26.12.2019',
'country': 'CH',
'location': u'St. Antönien',
'transport_other': 'Helikopter',
'meeting_point': 'dav',
'meeting_time': '10:29',
'return_arrival_time': '20:14',
'arrival_previous_day': True,
'basecamp': u'Grand Hôtel',
'accommodation': 'NONE',
'meals_other': u'Fünf-Sterne-Küche per Zimmerservice und Minibar',
'requirements_add': u'Fußnoten: https://de.wikipedia.org/wiki/Heliskiing',
'pre_meeting_1': '10.12.2019 18:35',
'trainer_firstname': u'Trainer1 Ö.',
'trainer_familyname': u'Ä. Tourenleiter',
'trainer_email': 'trainer@localhost',
'trainer_2_fullname': u'Trainer2 Überflieger',
'trainer_3_fullname': u'Trainer3 Weißalles',
'deadline': 'month',
'charge': '1800',
'additional_costs': None,
'course_topic_1': u'Grundkentnisse in der neusten Willy-Bögner-Kollektion',
'course_topic_2': u'Ein- und Aussteigen am Heliköpter',
'course_topic_3': u'Cocktailkunde für dekadentes Après-Ski',
'course_topic_4': u'Und vieles möhr',
'course_goal_1': [
u'Güt aussehen',
u'Lässig sein',
u'Geld scheißen',
],
'title': u'Heli-Sking-Kurs für Snobs',
'description': [
u'Hier steht jetzt so allerhand Scheiß.',
u'z.B. eine ÜRL: https://de.wikipedia.org (leider öhne Ümläüte)',
u'oder eine E-Mail-Ädresse: heinzel@alpenverein-karlsruhe.de'
],
'internal_note': [
u'Automatisierter Software Test',
u'Viele Grüße',
u' heinzel =u}',
],
}
TEST_EVENT_DATA_W = {
'level': 'advanced',
'first_day': '21.6.2019',
'alt_first_day': '22.06.2019',
'terrain': 'flats',
'location': u'Karlsruhe (Schloßpark)',
'transport': 'public',
'meeting_point_other': u'Bahnhof der Schloßgartenbahn',
'departure_time': '07:00',
'departure_ride': u'Schloßgartenbahn in Richtung Schloßgartenbahnbahnhof',
'return_departure_time': '19',
'return_arrival_time': '19:10',
'trainer_phone': u'+555 666 AB (Büro)',
'title': u'Wanderung durch den Karlsruher Schloßpark',
'description': [
u'Hier steht jetzt so allerhand Scheiß.',
u'z.B. eine ÜRL: https://de.wikipedia.org (leider öhne Ümläüte)',
u'oder eine E-Mail-Ädresse: heinzel@alpenverein-karlsruhe.de'
],
'internal_note': [
u'Automatisierter Software Test',
u'Viele Grüße',
u' heinzel =u}',
],
}
@skip_unless_tag_option()
@tag('screenshots')
class TestCase(ScreenshotTestCase):
screenshot_prefix = 'dav_events-'
def create_user_for_role(self, role_name, first_name, last_name):
user = None
setting_name = 'groups_{}'.format(role_name)
app_config = apps.get_app_config('dav_events')
group_names = getattr(app_config.settings, setting_name)
if group_names:
group_name = group_names[0]
group = Group(name=group_name)
group.save()
user_model = get_user_model()
email = '{}@localhost'.format(role_name)
user_name = email
password = TEST_PASSWORD
user = user_model.objects.create_user(username=user_name, password=password, email=user_name,
first_name=first_name, last_name=last_name)
user.groups.add(group)
return user
def setUp(self):
super(TestCase, self).setUp()
self.manager_super = self.create_user_for_role('manager_super', 'Manager Super', 'Tourenreferent')
self.manager_w = self.create_user_for_role('manager_w', 'Manager W', 'BereichsleiterWandern')
self.manager_s = self.create_user_for_role('manager_s', 'Manager S', 'BereichsleiterSki')
self.publisher_print = self.create_user_for_role('publisher_print', 'Publisher Print', 'RedaktionPrint')
self.publisher_web = self.create_user_for_role('publisher_web', 'Publisher Web', 'RedaktionWeb')
self.publisher_facebook = self.create_user_for_role('publisher_facebook', 'Publisher Facebook', 'RedaktionFacebook')
def login(self, username, password):
self.get(reverse('dav_auth:login'))
c = self.selenium
username_field = self.wait_on_presence(c, (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(password)
password_field.send_keys(Keys.RETURN)
self.wait_until_stale(c, password_field)
def logout(self):
self.get(reverse('dav_auth:logout'))
def create_event(self, event_data, auth=False, screenshots=True):
data = event_data
c = self.selenium
c.get(self.complete_url(reverse('dav_events:root')))
if auth:
sequence_name = 'create_event_auth'
button = self.wait_on_presence(c, (By.ID, 'btn-events-list'))
button.click()
button = self.wait_on_presence(c, (By.ID, 'btn-event-create'))
if screenshots:
self.save_screenshot('event_list_before', sequence=sequence_name)
else:
sequence_name = 'create_event_unauth'
button = self.wait_on_presence(c, (By.ID, 'btn-event-create'))
button.click()
self.wait_until_stale(c, button)
if screenshots:
self.save_screenshot('mode_form', sequence=sequence_name)
if 'mode' in data:
field = c.find_element_by_id('id_mode')
radio = field.find_element_by_css_selector('input[value=\'{}\']'.format(data['mode']))
radio.click()
if 'sport' in data:
field = c.find_element_by_id('id_sport')
radio = field.find_element_by_css_selector('input[value=\'{}\']'.format(data['sport']))
radio.click()
if 'level' in data:
field = c.find_element_by_id('id_level')
radio = field.find_element_by_css_selector('input[value=\'{}\']'.format(data['level']))
radio.click()
if 'ski_lift' in data and data['ski_lift']:
field = c.find_element_by_id('id_ski_lift')
field.click()
field = c.find_element_by_css_selector('input#id_first_day_widget')
field.send_keys(data['first_day'])
td = c.find_element_by_css_selector('div.datetimepicker-days td.active')
td.click()
field = c.find_element_by_css_selector('input#id_last_day_widget')
field.click()
if screenshots:
self.save_screenshot('last_date_widget', sequence=sequence_name)
if 'last_day' in data:
field.send_keys(data['last_day'])
if 'alt_first_day' in data:
field = c.find_element_by_css_selector('input#id_alt_first_day_widget')
field.send_keys(data['alt_first_day'])
if 'alt_last_day' in data:
field = c.find_element_by_css_selector('input#id_alt_last_day_widget')
field.send_keys(data['alt_last_day'])
button = c.find_element_by_id('btn-form-next')
button.click()
self.wait_until_stale(c, button)
if screenshots:
self.save_screenshot('location_form', sequence=sequence_name)
if 'country' in data:
field = c.find_element_by_id('id_country')
Select(field).select_by_value(data['country'])
if 'terrain' in data:
field = c.find_element_by_id('id_terrain')
Select(field).select_by_value(data['terrain'])
if 'location' in data:
field = c.find_element_by_id('id_location')
field.send_keys(data['location'])
if 'transport_other' in data:
field = c.find_element_by_id('id_transport_other')
field.send_keys(data['transport_other'])
if 'transport' in data:
field = c.find_element_by_id('id_transport')
Select(field).select_by_value(data['transport'])
button = c.find_element_by_id('btn-form-next')
button.click()
self.wait_until_stale(c, button)
if screenshots:
self.save_screenshot('journey_form', sequence=sequence_name)
if 'meeting_point_other' in data:
field = c.find_element_by_id('id_meeting_point_other')
field.send_keys(data['meeting_point_other'])
if 'meeting_point' in data:
field = c.find_element_by_id('id_meeting_point')
Select(field).select_by_value(data['meeting_point'])
if 'meeting_time' in data:
field = c.find_element_by_css_selector('input#id_meeting_time_widget')
field.send_keys(data['meeting_time'])
if 'departure_time' in data:
field = c.find_element_by_css_selector('input#id_departure_time_widget')
field.send_keys(data['departure_time'])
if 'departure_ride' in data:
field = c.find_element_by_id('id_departure_ride')
field.send_keys(data['departure_ride'])
if 'return_departure_time' in data:
field = c.find_element_by_css_selector('input#id_return_departure_time_widget')
field.send_keys(data['return_departure_time'])
if 'return_arrival_time' in data:
field = c.find_element_by_css_selector('input#id_return_arrival_time_widget')
field.send_keys(data['return_arrival_time'])
if 'arrival_previous_day' in data and data['arrival_previous_day']:
field = c.find_element_by_id('id_arrival_previous_day')
field.click()
button = c.find_element_by_id('btn-form-next')
button.click()
self.wait_until_stale(c, button)
if 'last_day' in data:
if screenshots:
self.save_screenshot('accommodation_form', sequence=sequence_name)
if 'basecamp' in data:
field = c.find_element_by_id('id_basecamp')
field.send_keys(data['basecamp'])
if 'accommodation' in data:
field = c.find_element_by_id('id_accommodation')
Select(field).select_by_value(data['accommodation'])
if 'meals_other' in data:
field = c.find_element_by_id('id_meals_other')
field.send_keys(data['meals_other'])
button = c.find_element_by_id('btn-form-next')
button.click()
self.wait_until_stale(c, button)
if screenshots:
self.save_screenshot('requirements_form', sequence=sequence_name)
if 'requirements_add' in data:
field = c.find_element_by_id('id_requirements')
field.send_keys(Keys.RETURN)
if isinstance(data['requirements_add'], list):
field.send_keys(Keys.RETURN.join(data['requirements_add']))
else:
field.send_keys(data['requirements_add'])
if 'pre_meeting_1' in data:
field = c.find_element_by_css_selector('input#id_pre_meeting_1_widget')
field.send_keys(data['pre_meeting_1'])
if 'pre_meeting_2' in data:
field = c.find_element_by_css_selector('input#id_pre_meeting_2_widget')
field.send_keys(data['pre_meeting_2'])
button = c.find_element_by_id('btn-form-next')
button.click()
self.wait_until_stale(c, button)
if screenshots:
self.save_screenshot('trainer_form', sequence=sequence_name)
if 'trainer_firstname' in data:
field = self.wait_on_presence(c, (By.ID, 'id_trainer_firstname'))
field.send_keys(data['trainer_firstname'])
if 'trainer_familyname' in data:
field = c.find_element_by_id('id_trainer_familyname')
field.send_keys(data['trainer_familyname'])
if 'trainer_email' in data:
field = c.find_element_by_id('id_trainer_email')
field.send_keys(data['trainer_email'])
if 'trainer_phone' in data:
field = c.find_element_by_id('id_trainer_phone')
field.send_keys(data['trainer_phone'])
if 'trainer_2_fullname' in data:
field = c.find_element_by_id('id_trainer_2_fullname')
field.send_keys(data['trainer_2_fullname'])
if 'trainer_3_fullname' in data:
field = c.find_element_by_id('id_trainer_3_fullname')
field.send_keys(data['trainer_3_fullname'])
button = c.find_element_by_id('btn-form-next')
button.click()
self.wait_until_stale(c, button)
if screenshots:
self.save_screenshot('registration_form', sequence=sequence_name)
if 'deadline' in data:
field = c.find_element_by_id('id_deadline')
radio = field.find_element_by_css_selector('input[value=\'{}\']'.format(data['deadline']))
radio.click()
button = c.find_element_by_id('btn-form-next')
button.click()
self.wait_until_stale(c, button)
if screenshots:
self.save_screenshot('charges_form', sequence=sequence_name)
if 'charge' in data:
field = c.find_element_by_id('id_charge')
field.clear()
field.send_keys(data['charge'])
if 'additional_costs' in data:
field = c.find_element_by_id('id_additional_costs')
field.clear()
if data['additional_costs'] is not None:
field.send_keys(data['additional_costs'])
button = c.find_element_by_id('btn-form-next')
button.click()
self.wait_until_stale(c, button)
if 'mode' in data and data['mode'] == 'training':
if screenshots:
self.save_screenshot('training_form', sequence=sequence_name)
field = c.find_element_by_id('id_course_topic_1')
if isinstance(data['course_topic_1'], list):
field.send_keys(Keys.RETURN.join(data['course_topic_1']))
else:
field.send_keys(data['course_topic_1'])
if 'course_topic_2' in data:
field = c.find_element_by_id('id_course_topic_2')
field.send_keys(data['course_topic_2'])
if 'course_topic_3' in data:
button = c.find_element_by_id('btn-topic-add')
button.click()
field = c.find_element_by_id('id_course_topic_3')
field.send_keys(data['course_topic_3'])
if 'course_topic_4' in data:
button.click()
field = c.find_element_by_id('id_course_topic_4')
field.send_keys(data['course_topic_4'])
field = c.find_element_by_id('id_course_goal_1')
if isinstance(data['course_goal_1'], list):
field.send_keys(Keys.RETURN.join(data['course_goal_1']))
else:
field.send_keys(data['course_goal_1'])
if 'course_goal_2' in data:
field = c.find_element_by_id('id_course_goal_2')
field.send_keys(data['course_goal_2'])
if 'course_goal_3' in data:
button = c.find_element_by_id('btn-goal-add')
button.click()
field = c.find_element_by_id('id_course_goal_3')
field.send_keys(data['course_goal_3'])
if 'course_goal_4' in data:
button.click()
field = c.find_element_by_id('id_course_goal_4')
field.send_keys(data['course_goal_4'])
button = c.find_element_by_id('btn-form-next')
button.click()
self.wait_until_stale(c, button)
if screenshots:
self.save_screenshot('description_form', sequence=sequence_name)
if 'title' in data:
field = c.find_element_by_id('id_title')
field.clear()
field.send_keys(data['title'])
field = c.find_element_by_id('id_description')
if isinstance(data['description'], list):
field.send_keys(Keys.RETURN.join(data['description']))
else:
field.send_keys(data['description'])
button = c.find_element_by_id('btn-form-next')
button.click()
self.wait_until_stale(c, button)
if screenshots:
self.save_screenshot('summary_form', sequence=sequence_name)
button = c.find_element_by_id('btn-form-back')
button.click()
self.wait_until_stale(c, button)
for i in range(0, 11):
try:
button = c.find_element_by_id('btn-form-next')
button.click()
self.wait_until_stale(c, button)
except NoSuchElementException:
break
else:
self.fail('Too many sub forms')
if 'internal_note' in data:
field = c.find_element_by_id('id_internal_note')
if isinstance(data['internal_note'], list):
field.send_keys(Keys.RETURN.join(data['internal_note']))
else:
field.send_keys(data['internal_note'])
button = c.find_element_by_id('btn-form-submit')
button.click()
self.wait_until_stale(c, button)
if not auth:
if screenshots:
self.save_screenshot('user_and_event_created_set_password', sequence=sequence_name)
field = c.find_element_by_id('id_new_password')
field.send_keys(TEST_PASSWORD)
field = c.find_element_by_id('id_new_password_repeat')
field.send_keys(TEST_PASSWORD)
field.send_keys(Keys.RETURN)
self.wait_until_stale(c, field)
if screenshots:
self.save_screenshot('finished', sequence=sequence_name)
else:
if screenshots:
self.save_screenshot('event_list_after', sequence=sequence_name)
def accept_event(self, title, screenshots=True):
c = self.selenium
sequence_name = 'accept_event'
c.get(self.complete_url(reverse('dav_events:root')))
button = self.wait_on_presence(c, (By.ID, 'btn-events-list'))
button.click()
self.wait_until_stale(c, button)
if screenshots:
self.save_screenshot('event_list_before', sequence=sequence_name)
link = c.find_element_by_link_text(title)
link.click()
self.wait_until_stale(c, link)
if screenshots:
self.save_screenshot('event_details', sequence=sequence_name)
button = c.find_element_by_id('btn-accept')
button.click()
time.sleep(.5)
if screenshots:
self.save_screenshot('accept_modal', sequence=sequence_name)
button = c.find_element_by_css_selector('#modal-accept-dialog a.btn-success')
button.click()
self.wait_until_stale(c, button)
if screenshots:
self.save_screenshot('accepted', sequence=sequence_name)
link = c.find_element_by_link_text(ugettext('Veranstaltungsliste'))
link.click()
self.wait_until_stale(c, link)
if screenshots:
self.save_screenshot('event_list_after', sequence=sequence_name)
def test_screenshots(self):
#self.quit_selenium = False
c = self.selenium
self.get(reverse('dav_events:root'))
self.save_screenshot('home')
self.create_event(TEST_EVENT_DATA_S, auth=False)
self.create_event(TEST_EVENT_DATA_W, auth=True)
link = c.find_element_by_link_text(TEST_EVENT_DATA_W['title'])
link.click()
self.wait_until_stale(c, link)
self.save_screenshot('owner_event_details')
self.logout()
self.login(self.manager_s.username, TEST_PASSWORD)
self.accept_event(TEST_EVENT_DATA_S['title'])
self.logout()
self.login(self.manager_super.username, TEST_PASSWORD)
self.accept_event(TEST_EVENT_DATA_W['title'])
self.logout()