* refactors test logic into base test classes
* adds tests for views in konova app
* fixes bugs/warnings detected by testing
This commit is contained in:
mpeltriaux 2021-10-26 14:26:32 +02:00
parent 2553eb2825
commit bfe541f83e
4 changed files with 287 additions and 114 deletions

View File

@ -5,38 +5,45 @@ Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 26.10.21 Created on: 26.10.21
""" """
from django.test import TestCase, Client from django.test import Client
from django.contrib.auth.models import User, Group from django.contrib.auth.models import Group
from django.urls import reverse from django.urls import reverse
from intervention.models import Intervention, LegalData, ResponsibilityData from intervention.models import Intervention, LegalData, ResponsibilityData
from konova.management.commands.setup_data import GROUPS_DATA
from konova.models import Geometry from konova.models import Geometry
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
from konova.tests.test_views import BaseViewTestCase
from user.models import UserActionLogEntry, UserAction from user.models import UserActionLogEntry, UserAction
class ViewTestCase(TestCase): class ViewTestCase(BaseViewTestCase):
def setUp(self) -> None: intervention = None
# Create superuser and regular user
self.superuser = User.objects.create_superuser(
username="root",
email="root@root.com",
password="root",
)
self.user = User.objects.create_user(
username="user1",
email="user@root.com",
password="user1"
)
# Create groups
for group_data in GROUPS_DATA:
name = group_data.get("name")
Group.objects.get_or_create(
name=name,
)
def setUp(self) -> None:
super().setUp()
self.create_dummy_data()
# Prepare urls
self.index_url = reverse("intervention:index", args=())
self.new_url = reverse("intervention:new", args=())
self.new_id_url = reverse("intervention:new-id", args=())
self.detail_url = reverse("intervention:detail", args=(self.intervention.id,))
self.log_url = reverse("intervention:log", args=(self.intervention.id,))
self.edit_url = reverse("intervention:edit", args=(self.intervention.id,))
self.remove_url = reverse("intervention:remove", args=(self.intervention.id,))
self.share_url = reverse("intervention:share", args=(self.intervention.id, self.intervention.access_token,))
self.share_create_url = reverse("intervention:share-create", args=(self.intervention.id,))
self.run_check_url = reverse("intervention:run-check", args=(self.intervention.id,))
self.record_url = reverse("intervention:record", args=(self.intervention.id,))
self.report_url = reverse("intervention:report", args=(self.intervention.id,))
def create_dummy_data(self):
""" Creates an intervention which can be used for tests
Returns:
"""
# Create dummy data # Create dummy data
# Create log entry # Create log entry
action = UserActionLogEntry.objects.create( action = UserActionLogEntry.objects.create(
@ -49,7 +56,7 @@ class ViewTestCase(TestCase):
responsibility_data = ResponsibilityData.objects.create() responsibility_data = ResponsibilityData.objects.create()
geometry = Geometry.objects.create() geometry = Geometry.objects.create()
# Finally create main object, holding the other objects # Finally create main object, holding the other objects
intervention = Intervention.objects.create( self.intervention = Intervention.objects.create(
identifier="TEST", identifier="TEST",
title="Test_title", title="Test_title",
responsible=responsibility_data, responsible=responsibility_data,
@ -58,34 +65,19 @@ class ViewTestCase(TestCase):
geometry=geometry, geometry=geometry,
comment="Test", comment="Test",
) )
intervention.generate_access_token(make_unique=True) self.intervention.generate_access_token(make_unique=True)
# Prepare urls
self.index_url = reverse("intervention:index", args=())
self.new_url = reverse("intervention:new", args=())
self.new_id_url = reverse("intervention:new-id", args=())
self.detail_url = reverse("intervention:detail", args=(intervention.id,))
self.log_url = reverse("intervention:log", args=(intervention.id,))
self.edit_url = reverse("intervention:edit", args=(intervention.id,))
self.remove_url = reverse("intervention:remove", args=(intervention.id,))
self.share_url = reverse("intervention:share", args=(intervention.id, intervention.access_token,))
self.share_create_url = reverse("intervention:share-create", args=(intervention.id,))
self.run_check_url = reverse("intervention:run-check", args=(intervention.id,))
self.record_url = reverse("intervention:record", args=(intervention.id,))
self.report_url = reverse("intervention:report", args=(intervention.id,))
self.login_url = reverse("simple-sso-login")
def test_views_logged_in_no_groups(self): def test_views_logged_in_no_groups(self):
""" Check correct status code for all requests """ Check correct status code for all requests
Assertion: User logged in but has no groups Assumption: User logged in but has no groups
Returns: Returns:
""" """
# Login client # Login client
client = Client() client = Client()
client.login(username="root", password="root") client.login(username=self.superuser.username, password=self.superuser_pw)
success_urls = [ success_urls = [
self.index_url, self.index_url,
@ -104,18 +96,13 @@ class ViewTestCase(TestCase):
self.record_url, self.record_url,
] ]
for url in success_urls: self.assert_url_success(client, success_urls)
response = client.get(url) self.assert_url_fail(client, fail_urls)
self.assertEqual(response.status_code, 200, msg=f"Failed for {url}")
for url in fail_urls:
response = client.get(url)
self.assertEqual(response.status_code, 302, msg=f"Failed for {url}")
def test_views_anonymous_user(self): def test_views_anonymous_user(self):
""" Check correct status code for all requests """ Check correct status code for all requests
Assertion: User logged in but has no groups Assumption: User not logged in
Returns: Returns:
@ -126,23 +113,22 @@ class ViewTestCase(TestCase):
success_urls = [ success_urls = [
self.report_url, self.report_url,
] ]
fail_urls = [ login_redirect_base = f"{self.login_url}?next="
self.detail_url, fail_urls = {
self.index_url, self.detail_url: f"{login_redirect_base}{self.detail_url}",
self.log_url, self.index_url: f"{login_redirect_base}{self.index_url}",
self.new_id_url, self.log_url: f"{login_redirect_base}{self.log_url}",
self.new_url, self.new_id_url: f"{login_redirect_base}{self.new_id_url}",
self.edit_url, self.new_url: f"{login_redirect_base}{self.new_url}",
self.remove_url, self.edit_url: f"{login_redirect_base}{self.edit_url}",
self.share_url, self.remove_url: f"{login_redirect_base}{self.remove_url}",
self.share_create_url, self.share_url: f"{login_redirect_base}{self.share_url}",
self.run_check_url, self.share_create_url: f"{login_redirect_base}{self.share_create_url}",
self.record_url, self.run_check_url: f"{login_redirect_base}{self.run_check_url}",
] self.record_url: f"{login_redirect_base}{self.record_url}",
}
for url in success_urls: self.assert_url_success(client, success_urls)
response = client.get(url)
self.assertEqual(response.status_code, 200, msg=f"Failed for {url}")
for url in fail_urls: for url in fail_urls:
response = client.get(url, follow=True) response = client.get(url, follow=True)
@ -151,14 +137,14 @@ class ViewTestCase(TestCase):
def test_views_logged_in_default_group(self): def test_views_logged_in_default_group(self):
""" Check correct status code for all requests """ Check correct status code for all requests
Assertion: User logged in and is default group member Assumption: User logged in and is default group member
Returns: Returns:
""" """
# Login client # Login client
client = Client() client = Client()
client.login(username="root", password="root") client.login(username=self.superuser.username, password=self.superuser_pw)
# Add user to default group # Add user to default group
default_group = Group.objects.get(name=DEFAULT_GROUP) default_group = Group.objects.get(name=DEFAULT_GROUP)
@ -183,33 +169,24 @@ class ViewTestCase(TestCase):
self.share_url: self.detail_url self.share_url: self.detail_url
} }
for url in success_urls: self.assert_url_success(client, success_urls)
response = client.get(url) self.assert_url_fail(client, fail_urls)
self.assertEqual(response.status_code, 200, msg=f"Failed for {url}") self.assert_url_success_redirect(client, success_urls_redirect)
for url in fail_urls:
response = client.get(url)
self.assertEqual(response.status_code, 302, msg=f"Failed for {url}")
for url, redirect_to in success_urls_redirect.items():
response = client.get(url, follow=True)
# Expect redirects to the landing page
self.assertEqual(response.redirect_chain[0], (redirect_to, 302), msg=f"Failed for {url}")
def test_views_logged_in_zb_group(self): def test_views_logged_in_zb_group(self):
""" Check correct status code for all requests """ Check correct status code for all requests
Assertion: User logged in and is registration office member Assumption: User logged in and is registration office member
Returns: Returns:
""" """
# Login client # Login client
client = Client() client = Client()
client.login(username="root", password="root") client.login(username=self.superuser.username, password=self.superuser_pw)
# Add user to default group # Add user to default group
zb_group = Group.objects.get(name=ZB_GROUP) zb_group = self.groups.get(name=ZB_GROUP)
self.superuser.groups.set([zb_group]) self.superuser.groups.set([zb_group])
success_urls = [ success_urls = [
@ -231,30 +208,21 @@ class ViewTestCase(TestCase):
self.share_url: self.detail_url self.share_url: self.detail_url
} }
for url in success_urls: self.assert_url_success(client, success_urls)
response = client.get(url) self.assert_url_fail(client, fail_urls)
self.assertEqual(response.status_code, 200, msg=f"Failed for {url}") self.assert_url_success_redirect(client, success_urls_redirect)
for url in fail_urls:
response = client.get(url)
self.assertEqual(response.status_code, 302, msg=f"Failed for {url}")
for url, redirect_to in success_urls_redirect.items():
response = client.get(url, follow=True)
# Expect redirects to the landing page
self.assertEqual(response.redirect_chain[0], (redirect_to, 302), msg=f"Failed for {url}")
def test_views_logged_in_ets_group(self): def test_views_logged_in_ets_group(self):
""" Check correct status code for all requests """ Check correct status code for all requests
Assertion: User logged in and is registration office member Assumption: User logged in and is registration office member
Returns: Returns:
""" """
# Login client # Login client
client = Client() client = Client()
client.login(username="root", password="root") client.login(username=self.superuser.username, password=self.superuser_pw)
# Add user to default group # Add user to default group
ets_group = Group.objects.get(name=ETS_GROUP) ets_group = Group.objects.get(name=ETS_GROUP)
@ -279,15 +247,6 @@ class ViewTestCase(TestCase):
self.share_url: self.detail_url self.share_url: self.detail_url
} }
for url in success_urls: self.assert_url_success(client, success_urls)
response = client.get(url) self.assert_url_fail(client, fail_urls)
self.assertEqual(response.status_code, 200, msg=f"Failed for {url}") self.assert_url_success_redirect(client, success_urls_redirect)
for url in fail_urls:
response = client.get(url)
self.assertEqual(response.status_code, 302, msg=f"Failed for {url}")
for url, redirect_to in success_urls_redirect.items():
response = client.get(url, follow=True)
# Expect redirects to the landing page
self.assertEqual(response.redirect_chain[0], (redirect_to, 302), msg=f"Failed for {url}")

View File

@ -29,14 +29,13 @@ class EcoAccountAutocomplete(Select2QuerySetView):
deleted=None, deleted=None,
recorded__isnull=False, recorded__isnull=False,
users__in=[self.request.user], users__in=[self.request.user],
).order_by(
"identifier"
) )
if self.q: if self.q:
qs = qs.filter( qs = qs.filter(
identifier__icontains=self.q identifier__icontains=self.q
) )
qs = qs.order_by(
"identifier"
)
return qs return qs
@ -52,14 +51,13 @@ class InterventionAutocomplete(Select2QuerySetView):
qs = Intervention.objects.filter( qs = Intervention.objects.filter(
deleted=None, deleted=None,
users__in=[self.request.user], users__in=[self.request.user],
).order_by(
"identifier"
) )
if self.q: if self.q:
qs = qs.filter( qs = qs.filter(
identifier__icontains=self.q identifier__icontains=self.q
) )
qs = qs.order_by(
"identifier"
)
return qs return qs

7
konova/tests/__init__.py Normal file
View File

@ -0,0 +1,7 @@
"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 26.10.21
"""

209
konova/tests/test_views.py Normal file
View File

@ -0,0 +1,209 @@
"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 26.10.21
"""
from abc import abstractmethod
from django.contrib.auth.models import User, Group
from django.test import TestCase, Client
from django.urls import reverse
from konova.management.commands.setup_data import GROUPS_DATA
class BaseTestCase(TestCase):
""" Provides reusable functionality for specialized test cases
"""
users = None
groups = None
superuser = None
user = None
superuser_pw = "root"
user_pw = "root"
@abstractmethod
def setUp(self) -> None:
# To be implemented in the inheriting classes
raise NotImplementedError
def create_users(self):
# Create superuser and regular user
self.superuser = User.objects.create_superuser(
username="root",
email="root@root.com",
password=self.superuser_pw,
)
self.user = User.objects.create_user(
username="user1",
email="user@root.com",
password=self.user_pw
)
self.users = User.objects.all()
def create_groups(self):
# Create groups
for group_data in GROUPS_DATA:
name = group_data.get("name")
Group.objects.get_or_create(
name=name,
)
self.groups = Group.objects.all()
class Meta:
abstract = True
class BaseViewTestCase(BaseTestCase):
""" Wraps basic test functionality, reusable for every specialized ViewTestCase
"""
login_url = None
def setUp(self) -> None:
self.create_users()
self.create_groups()
self.login_url = reverse("simple-sso-login")
def assert_url_success(self, client: Client, urls: list):
""" Assert for all given urls a direct 200 response
Args:
client (Client): The performing client
urls (list): An iterable list of urls to be checked
Returns:
"""
for url in urls:
response = client.get(url)
self.assertEqual(response.status_code, 200, msg=f"Failed for {url}")
def assert_url_success_redirect(self, client: Client, urls: dict):
""" Assert for all given urls a 302 response to a certain location.
Assert the redirect being the expected behaviour.
Args:
client (Client): The performing client
urls (dict): An iterable dict of (urls, redirect_to_url) pairs to be checked
Returns:
"""
for url, redirect_to in urls.items():
response = client.get(url, follow=True)
# Expect redirects to the landing page
self.assertEqual(response.redirect_chain[0], (redirect_to, 302), msg=f"Failed for {url}")
def assert_url_fail(self, client: Client, urls: list):
""" Assert for all given urls a direct 302 response
Args:
client (Client): The performing client
urls (list): An iterable list of urls to be checked
Returns:
"""
for url in urls:
response = client.get(url)
self.assertEqual(response.status_code, 302, msg=f"Failed for {url}")
class KonovaViewTestCase(BaseViewTestCase):
""" Holds tests for all regular views, which are not app specific
"""
def setUp(self) -> None:
super().setUp()
self.home_url = reverse("home")
def test_views_logged_in_no_groups(self):
""" Check correct status code for all requests
Assumption: User logged in but has no groups
Returns:
"""
# User logged in
client = Client()
client.login(username=self.superuser.username, password=self.superuser_pw)
self.superuser.groups.set([])
success_urls = [
self.home_url
]
self.assert_url_success(client, success_urls)
def test_views_anonymous_user(self):
""" Check correct status code for all requests
Assumption: User logged in but has no groups
Returns:
"""
# User not logged in
client = Client()
urls = [
self.home_url
]
self.assert_url_fail(client, urls)
class AutocompleteTestCase(BaseViewTestCase):
def setUp(self) -> None:
super().setUp()
self.atcmplt_accs = reverse("accounts-autocomplete")
self.atcmplt_interventions = reverse("interventions-autocomplete")
self.atcmplt_code_comp_action = reverse("codes-compensation-action-autocomplete")
self.atcmplt_code_comp_funding = reverse("codes-compensation-funding-autocomplete")
self.atcmplt_code_comp_biotope = reverse("codes-biotope-autocomplete")
self.atcmplt_code_comp_law = reverse("codes-law-autocomplete")
self.atcmplt_code_comp_process = reverse("codes-process-type-autocomplete")
self.atcmplt_code_comp_reg_off = reverse("codes-registration-office-autocomplete")
self.atcmplt_code_comp_cons_off = reverse("codes-conservation-office-autocomplete")
def _test_views_anonymous_user(self):
# ATTENTION: As of the current state of django-autocomplete-light, there is no way to check on authenticated
# users in a way like @loing_required or anything else. The documentation considers to check on the user's
# authentication state during get_queryset() of the call. Therefore this test method here will stay here
# for future clarification but won't be run due to the prefix '_'
# User not logged in
client = Client()
urls = [
self.atcmplt_accs,
self.atcmplt_interventions,
self.atcmplt_code_comp_action,
self.atcmplt_code_comp_funding,
self.atcmplt_code_comp_biotope,
self.atcmplt_code_comp_law,
self.atcmplt_code_comp_process,
self.atcmplt_code_comp_reg_off,
self.atcmplt_code_comp_cons_off,
]
self.assert_url_fail(client, urls)
def test_views_logged_in_no_groups(self):
# User logged in
client = Client()
client.login(username=self.superuser.username, password=self.superuser_pw)
self.superuser.groups.set([])
urls = [
self.atcmplt_accs,
self.atcmplt_interventions,
self.atcmplt_code_comp_action,
self.atcmplt_code_comp_funding,
self.atcmplt_code_comp_biotope,
self.atcmplt_code_comp_law,
self.atcmplt_code_comp_process,
self.atcmplt_code_comp_reg_off,
self.atcmplt_code_comp_cons_off,
]
self.assert_url_success(client, urls)