From 788fb3efe6d085714a5af242ab4d9eff1ead5bd2 Mon Sep 17 00:00:00 2001 From: Arona Jones Date: Sun, 7 Feb 2021 00:05:47 +0000 Subject: [PATCH] Yet more test shenanigans Can you tell I'm getting fed up? --- PyRIGS/settings.py | 1 - PyRIGS/tests/test_commands.py | 27 +++++++++++ PyRIGS/tests/test_unit.py | 78 ++++++++++++++++++++++++++------ RIGS/tests/conftest.py | 26 +++++++---- RIGS/tests/test_functional.py | 3 +- RIGS/tests/test_interaction.py | 5 +- RIGS/tests/test_unit.py | 19 -------- assets/tests/conftest.py | 17 +++++-- assets/tests/test_access.py | 71 ----------------------------- assets/tests/test_interaction.py | 1 + assets/tests/test_unit.py | 21 --------- conftest.py | 19 ++++---- pytest.ini | 3 +- 13 files changed, 135 insertions(+), 156 deletions(-) create mode 100644 PyRIGS/tests/test_commands.py delete mode 100644 assets/tests/test_access.py diff --git a/PyRIGS/settings.py b/PyRIGS/settings.py index 44794b4c..9faa95af 100644 --- a/PyRIGS/settings.py +++ b/PyRIGS/settings.py @@ -94,7 +94,6 @@ ROOT_URLCONF = 'PyRIGS.urls' WSGI_APPLICATION = 'PyRIGS.wsgi.application' # Database -# https://docs.djangoproject.com/en/1.7/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', diff --git a/PyRIGS/tests/test_commands.py b/PyRIGS/tests/test_commands.py new file mode 100644 index 00000000..01cd9bcc --- /dev/null +++ b/PyRIGS/tests/test_commands.py @@ -0,0 +1,27 @@ +import pytest +from django.core.management import call_command +from django.template.defaultfilters import striptags +from django.urls.exceptions import NoReverseMatch + +from RIGS.models import Event +from assets.models import Asset + + +@pytest.mark.parametrize("command", ['generateSampleAssetsData', 'generateSampleRIGSData', 'generateSampleUserData', 'deleteSampleData']) +def test_production_exception(command): + from django.core.management.base import CommandError + with pytest.raises(CommandError, match=".*production"): + call_command(command) + + +def test_sample_data(settings): + settings.DEBUG = True + call_command('generateSampleData') + assert Asset.objects.all().count() > 50 + assert Event.objects.all().count() > 100 + call_command('deleteSampleData') + assert Asset.objects.all().count() == 0 + assert Event.objects.all().count() == 0 + # Cleanup + call_command('flush', '--noinput') + call_command('migrate') diff --git a/PyRIGS/tests/test_unit.py b/PyRIGS/tests/test_unit.py index 9b78d725..2cf70472 100644 --- a/PyRIGS/tests/test_unit.py +++ b/PyRIGS/tests/test_unit.py @@ -1,12 +1,15 @@ -from PyRIGS import urls -from django.core.management import call_command import pytest -from django.urls import URLPattern, URLResolver, reverse -from django.urls.exceptions import NoReverseMatch -from django.test.utils import override_settings -from pytest_django.asserts import assertContains, assertRedirects, assertTemplateUsed, assertInHTML +from django.core.management import call_command from django.template.defaultfilters import striptags -from assets import models +from django.urls import URLPattern, URLResolver +from django.urls import reverse +from django.urls.exceptions import NoReverseMatch +from pytest_django.asserts import assertRedirects, assertContains, assertNotContains +from pytest_django.asserts import assertTemplateUsed, assertInHTML + +from PyRIGS import urls +from RIGS.models import Event +from assets.models import Asset def find_urls_recursive(patterns): @@ -34,13 +37,18 @@ def get_request_url(url): print("Couldn't test url " + pattern) -@pytest.fixture(scope='class', autouse=True) -def run_sample_data(django_db_blocker): # We need stuff setup so we don't get 404 errors everywhere +@pytest.fixture(scope='module', autouse=True) +def sample_data(django_db_blocker): with django_db_blocker.unblock(): from django.conf import settings settings.DEBUG = True call_command('generateSampleData') + assert Asset.objects.all().count() > 50 + assert Event.objects.all().count() > 100 settings.DEBUG = False + yield + call_command('flush', '--noinput') + call_command('migrate') def test_unauthenticated(client): # Nothing should be available to the unauthenticated @@ -73,8 +81,50 @@ def test_page_titles(admin_client): # print(response.content.decode(), file=open('output.html', 'w')) -def test_delete_sample_data(settings): - settings.DEBUG = True - call_command('deleteSampleData') - assert models.Asset.objects.all().count() == 0 - assert models.Supplier.objects.all().count() == 0 +def test_basic_access(client): + client.logout() + assert client.login(username="basic", password="basic") + + url = reverse('asset_list') + response = client.get(url) + # Check edit and duplicate buttons NOT shown in list + assertNotContains(response, 'Edit') + assertNotContains(response, + 'Duplicate') # If this line is randomly failing, check the debug toolbar HTML hasn't crept in + + url = reverse('asset_detail', kwargs={'pk': 1}) + response = client.get(url) + assertNotContains(response, 'Purchase Details') + assertNotContains(response, 'View Revision History') + + urlz = {'asset_history', 'asset_update', 'asset_duplicate'} + for url_name in urlz: + request_url = reverse(url_name, kwargs={'pk': 1}) + response = client.get(request_url, follow=True) + assert response.status_code == 403 + + request_url = reverse('supplier_create') + response = client.get(request_url, follow=True) + assert response.status_code == 403 + + request_url = reverse('supplier_update', kwargs={'pk': 1}) + response = client.get(request_url, follow=True) + assert response.status_code == 403 + client.logout() + + +def test_keyholder_access(client): + client.logout() + assert client.login(username="keyholder", password="keyholder") + + url = reverse('asset_list') + response = client.get(url) + # Check edit and duplicate buttons shown in list + assertContains(response, 'Edit') + assertContains(response, 'Duplicate') + + url = reverse('asset_detail', kwargs={'pk': 1}) + response = client.get(url) + assertContains(response, 'Purchase Details') + assertContains(response, 'View Revision History') + client.logout() diff --git a/RIGS/tests/conftest.py b/RIGS/tests/conftest.py index ed6252ff..ca240749 100644 --- a/RIGS/tests/conftest.py +++ b/RIGS/tests/conftest.py @@ -3,19 +3,16 @@ import pytest from django.utils import timezone -@pytest.fixture(autouse=True) -def vat_rate(db): - return models.VatRate.objects.create(start_at='2014-03-05', rate=0.20, comment='test1') - - @pytest.fixture def basic_event(db): - return models.Event.objects.create(name="TE E1", start_date=timezone.now()) + event = models.Event.objects.create(name="TE E1", start_date=timezone.now()) + yield event + event.delete() @pytest.fixture def ra(basic_event, admin_user): - return models.RiskAssessment.objects.create(event=basic_event, nonstandard_equipment=False, nonstandard_use=False, + ra = models.RiskAssessment.objects.create(event=basic_event, nonstandard_equipment=False, nonstandard_use=False, contractors=False, other_companies=False, crew_fatigue=False, big_power=False, power_mic=admin_user, generators=False, other_companies_power=False, nonstandard_equipment_power=False, @@ -24,24 +21,30 @@ def ra(basic_event, admin_user): area_outside_of_control=True, barrier_required=True, nonstandard_emergency_procedure=True, special_structures=False, suspended_structures=False, outside=False) + yield ra + ra.delete() @pytest.fixture def venue(db): - return models.Venue.objects.create(name="Venue 1") + venue = models.Venue.objects.create(name="Venue 1") + yield venue + venue.delete() @pytest.fixture # TODO parameterise with Event sizes def checklist(basic_event, venue, admin_user): - return models.EventChecklist.objects.create(event=basic_event, power_mic=admin_user, safe_parking=False, + checklist = models.EventChecklist.objects.create(event=basic_event, power_mic=admin_user, safe_parking=False, safe_packing=False, exits=False, trip_hazard=False, warning_signs=False, ear_plugs=False, hs_location="Locked away safely", extinguishers_location="Somewhere, I forgot", earthing=False, pat=False, date=timezone.now(), venue=venue) + yield checklist + checklist.delete() @pytest.fixture def many_events(db, scope="class"): - return { + many_events = { # produce 7 normal events - 5 current 1: models.Event.objects.create(name="TE E1", start_date=date.today() + timedelta(days=6), description="start future no end"), @@ -90,3 +93,6 @@ def many_events(db, scope="class"): status=models.Event.CANCELLED, description="non rig today cancelled"), } + yield many_events + for event in many_events: + event.delete() diff --git a/RIGS/tests/test_functional.py b/RIGS/tests/test_functional.py index a554aad3..d156a61a 100644 --- a/RIGS/tests/test_functional.py +++ b/RIGS/tests/test_functional.py @@ -9,7 +9,6 @@ from django.test import TestCase from django.urls import reverse import PyRIGS.tests.base -import PyRIGS.tests.test_unit from RIGS import models from pytest_django.asserts import assertContains, assertNotContains, assertFormError @@ -109,7 +108,7 @@ def test_duplicate_warning(client, admin_user): assertContains(response, 'amount has changed') -@pytest.mark.django_db(transaction=True) +@pytest.mark.django_db def test_email_sent(admin_client, admin_user, mailoutbox): event = setup_event() auth_data, hmac, url = setup_mail(event, admin_user) diff --git a/RIGS/tests/test_interaction.py b/RIGS/tests/test_interaction.py index 62e19136..2d7c63ec 100644 --- a/RIGS/tests/test_interaction.py +++ b/RIGS/tests/test_interaction.py @@ -652,7 +652,6 @@ class TestCalendar(BaseRigboardTest): @screenshot_failure_cls -@pytest.mark.xfail(reason="Bootstrap select handling broken for some reason, pending rewrite", run=False) class TestHealthAndSafety(BaseRigboardTest): def setUp(self): super().setUp() @@ -871,8 +870,8 @@ class TestHealthAndSafety(BaseRigboardTest): self.page.hs_location = "The Moon" self.page.extinguishers_location = "With the rest of the fire" # If we do this first the search fails, for ... reasons - self.page.power_mic.search(self.profile.name) - # self.page.power_mic.toggle() + self.page.power_mic.search("Test") # FIXME + self.page.power_mic.toggle() self.assertFalse(self.page.power_mic.is_open) vehicle_name = 'Brian' diff --git a/RIGS/tests/test_unit.py b/RIGS/tests/test_unit.py index eea61081..a24a5209 100644 --- a/RIGS/tests/test_unit.py +++ b/RIGS/tests/test_unit.py @@ -1,14 +1,12 @@ from datetime import date from django.core.exceptions import ObjectDoesNotExist -from django.core.management import call_command from django.test import TestCase from django.test.utils import override_settings from django.urls import reverse, reverse_lazy from django.utils import timezone from pytest_django.asserts import assertRedirects, assertNotContains, assertContains -import PyRIGS.tests.test_unit from PyRIGS.tests.base import assert_times_almost_equal, assert_oembed, login from RIGS import models @@ -369,20 +367,3 @@ def test_ra_redirect(admin_client, admin_user, ra): response = admin_client.get(request_url, follow=True) assertRedirects(response, expected_url, status_code=302, target_status_code=200) - - -def test_production_exception(): - from django.core.management.base import CommandError - with pytest.raises(CommandError): - call_command("generateSampleRIGSData") - - -@pytest.mark.django_db(transaction=True) -def test_generate_sample_data(settings): - settings.DEBUG = True - # Run the management command and check there are no exceptions - call_command('generateSampleUserData') - call_command('generateSampleRIGSData') - - # Check there are lots of events - assert models.Event.objects.all().count() > 100 diff --git a/assets/tests/conftest.py b/assets/tests/conftest.py index 8111fef9..334b7bb6 100644 --- a/assets/tests/conftest.py +++ b/assets/tests/conftest.py @@ -5,22 +5,31 @@ import datetime @pytest.fixture def category(db): - return models.AssetCategory.objects.create(name="Sound") + category = models.AssetCategory.objects.create(name="Sound") + yield category + category.delete() @pytest.fixture def status(db): - return models.AssetStatus.objects.create(name="Broken", should_show=True) + status = models.AssetStatus.objects.create(name="Broken", should_show=True) + yield status + status.delete() @pytest.fixture def test_cable(db, category, status): connector = models.Connector.objects.create(description="16A IEC", current_rating=16, voltage_rating=240, num_pins=3) cable_type = models.CableType.objects.create(circuits=11, cores=3, plug=connector, socket=connector) - return models.Asset.objects.create(asset_id="9666", description="125A -> Jack", comments="The cable from Hell...", status=status, category=category, date_acquired=datetime.date(2006, 6, 6), is_cable=True, cable_type=cable_type, length=10, csa="1.5") + cable = models.Asset.objects.create(asset_id="9666", description="125A -> Jack", comments="The cable from Hell...", status=status, category=category, date_acquired=datetime.date(2006, 6, 6), is_cable=True, cable_type=cable_type, length=10, csa="1.5") + yield cable + connector.delete() + cable_type.delete() + cable.delete() @pytest.fixture def test_asset(db, category, status): asset = models.Asset.objects.create(asset_id="91991", description="Spaceflower", status=status, category=category, date_acquired=datetime.date(1991, 12, 26)) - return asset + yield asset + asset.delete() diff --git a/assets/tests/test_access.py b/assets/tests/test_access.py deleted file mode 100644 index 8fd7300c..00000000 --- a/assets/tests/test_access.py +++ /dev/null @@ -1,71 +0,0 @@ -import datetime - -import pytest -from django.core.management import call_command -from django.test import override_settings -from django.test.utils import override_settings -from django.urls import reverse -from pytest_django.asserts import assertFormError, assertRedirects, assertContains, assertNotContains - -from PyRIGS.tests.base import assert_oembed, login - -from assets import models - -from django.utils import timezone - - -@pytest.fixture(scope='class', autouse=True) -def run_sample_data(django_db_blocker): # We need stuff setup so we don't get 404 errors everywhere - with django_db_blocker.unblock(): - from django.conf import settings - settings.DEBUG = True - call_command('generateSampleUserData') - call_command('generateSampleAssetsData') - settings.DEBUG = False - - -class TestAccess(): - def test_basic_access(client): - client.logout() - assert client.login(username="basic", password="basic") - - url = reverse('asset_list') - response = client.get(url) - # Check edit and duplicate buttons NOT shown in list - assertNotContains(response, 'Edit') - assertNotContains(response, 'Duplicate') # If this line is randomly failing, check the debug toolbar HTML hasn't crept in - - url = reverse('asset_detail', kwargs={'pk': 1}) - response = client.get(url) - assertNotContains(response, 'Purchase Details') - assertNotContains(response, 'View Revision History') - - urls = {'asset_history', 'asset_update', 'asset_duplicate'} - for url_name in urls: - request_url = reverse(url_name, kwargs={'pk': 1}) - response = client.get(request_url, follow=True) - assert response.status_code == 403 - - request_url = reverse('supplier_create') - response = client.get(request_url, follow=True) - assert response.status_code == 403 - - request_url = reverse('supplier_update', kwargs={'pk': 1}) - response = client.get(request_url, follow=True) - assert response.status_code == 403 - - - def test_keyholder_access(client): - client.logout() - assert client.login(username="keyholder", password="keyholder") - - url = reverse('asset_list') - response = client.get(url) - # Check edit and duplicate buttons shown in list - assertContains(response, 'Edit') - assertContains(response, 'Duplicate') - - url = reverse('asset_detail', kwargs={'pk': 1}) - response = client.get(url) - assertContains(response, 'Purchase Details') - assertContains(response, 'View Revision History') diff --git a/assets/tests/test_interaction.py b/assets/tests/test_interaction.py index 22be4275..eb45129e 100644 --- a/assets/tests/test_interaction.py +++ b/assets/tests/test_interaction.py @@ -313,6 +313,7 @@ class TestAssetAudit(AutoLoginTest): # Now do it properly self.page.modal.description = new_desc = "A BIG hammer" self.page.modal.submit() + self.driver.implicitly_wait(4) self.wait.until(animation_is_finished()) submit_time = timezone.now() # Check data is correct diff --git a/assets/tests/test_unit.py b/assets/tests/test_unit.py index e0e7919c..b07ec86d 100644 --- a/assets/tests/test_unit.py +++ b/assets/tests/test_unit.py @@ -1,7 +1,6 @@ import datetime import pytest -from django.core.management import call_command from django.urls import reverse from pytest_django.asserts import assertFormError, assertRedirects, assertContains, assertNotContains @@ -130,23 +129,3 @@ def assert_asset_form_errors(response): assertFormError(response, 'form', 'date_sold', 'Cannot sell an item before it is acquired') assertFormError(response, 'form', 'purchase_price', 'A price cannot be negative') assertFormError(response, 'form', 'salvage_value', 'A price cannot be negative') - - -def test_production_exception(client): - from django.core.management.base import CommandError - - with pytest.raises(CommandError, match=".*production"): - call_command('generateSampleAssetsData') - call_command('deleteSampleData') - - -@pytest.mark.django_db(transaction=True) -def test_generate_sample_data(settings): - settings.DEBUG = True - print(models.AssetCategory.objects.all()) - # Run the management command and check there are no exceptions - call_command('generateSampleAssetsData') - - # Check there are lots - assert models.Asset.objects.all().count() > 50 - assert models.Supplier.objects.all().count() > 50 diff --git a/conftest.py b/conftest.py index f7e19ea0..4aab1e06 100644 --- a/conftest.py +++ b/conftest.py @@ -1,6 +1,10 @@ from django.conf import settings import django import pytest +from django.core.management import call_command +from RIGS.models import VatRate +import random +from django.db import connection def pytest_configure(): @@ -13,7 +17,6 @@ def pytest_configure(): @pytest.fixture(scope='session') def splinter_webdriver(): - """Override splinter webdriver name.""" return 'chrome' @@ -22,12 +25,8 @@ def splinter_screenshot_dir(): return 'screenshots/' -def _has_transactional_marker(item): - db_marker = item.get_closest_marker("django_db") - if db_marker and db_marker.kwargs.get("transaction"): - return 1 - return 0 - - -def pytest_collection_modifyitems(items): # Always run database-mulching tests last - items.sort(key=_has_transactional_marker) +@pytest.fixture(autouse=True) # Also enables DB access for all tests as a useful side effect +def vat_rate(db): + vat_rate = VatRate.objects.create(start_at='2014-03-05', rate=0.20, comment='test1') + yield vat_rate + vat_rate.delete() \ No newline at end of file diff --git a/pytest.ini b/pytest.ini index 7593bba4..8ffd8613 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,4 +1,5 @@ [pytest] DJANGO_SETTINGS_MODULE = PyRIGS.settings filterwarnings = - ignore:.*site-packages.*:DeprecationWarning \ No newline at end of file + ignore:.*site-packages.*:DeprecationWarning +addopts = --create-db