""" We are using unittest for troggle. Note that the database has not been parsed from the source files when these tests are run, so any path that relies on data being in the database will fail. The simple redirections to files which exist, e.g. in /expoweb/ /expofiles/ /expofiles/documents/ etc. will test fine. But paths like this: /survey_scans/ /caves/ which rely on database resolution will fail unless a fixture has been set up for them. https://docs.djangoproject.com/en/3.2/topics/testing/tools/ """ import re import subprocess import unittest from django.test import Client, SimpleTestCase, TestCase class SimpleTest(SimpleTestCase): def test_test_setting(self): from django.conf import settings self.assertEqual(settings.EMAIL_BACKEND, "django.core.mail.backends.locmem.EmailBackend") import troggle.settings as settings def test_import_TroggleModel(self): from troggle.core.models.troggle import TroggleModel def test_import_Cave(self): from troggle.core.models.caves import Cave def test_import_parsers_surveys(self): # from PIL import Image from functools import reduce from troggle.core.utils import save_carefully def test_import_parsers_survex(self): import troggle.core.models.caves as models_caves import troggle.core.models.survex as models_survex import troggle.core.models.troggle as models import troggle.settings as settings from troggle.core.views import caves, drawings, other, scans, statistics, survex, uploads from troggle.core.views.caves import cavepage, ent from troggle.core.views.other import frontpage from troggle.parsers.people import GetPersonExpeditionNameLookup def test_import_views_uploads(self): from troggle.core.views.uploads import dwgupload def test_import_views_walletedit(self): from troggle.core.views.wallets_edit import walletedit def test_import_parsers_QMs(self): from troggle.core.models.logbooks import QM def test_import_parsers_people(self): from html import unescape from unidecode import unidecode def test_import_parsers_logbooks(self): from django.template.defaultfilters import slugify from django.utils.timezone import get_current_timezone, make_aware from parsers.people import GetPersonExpeditionNameLookup from troggle.core.models.logbooks import CaveSlug, QM, LogbookEntry, PersonLogEntry from troggle.core.models.troggle import DataIssue, Expedition def test_import_core_views_caves(self): from django.conf import settings from django.contrib.auth.decorators import login_required from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import get_object_or_404, render import troggle.core.views.expo from troggle.core.forms import CaveAndEntranceFormSet, CaveForm, EntranceForm, EntranceLetterForm from troggle.core.models.caves import Area, Cave, CaveAndEntrance, Entrance, EntranceSlug, SurvexStation from troggle.core.models.troggle import Expedition from troggle.core.views.auth import login_required_if_public def test_import_parsers_mix(self): import troggle.parsers.caves import troggle.parsers.drawings import troggle.parsers.logbooks import troggle.parsers.people import troggle.parsers.QMs import troggle.parsers.scans import troggle.parsers.survex import troggle.settings from troggle.parsers.logbooks import GetCaveLookup def test_import_imports(self): from django.contrib.auth.models import User from django.core import management from django.db import close_old_connections, connection, connections from django.http import HttpResponse from django.urls import reverse def test_import_urls(self): from django.conf import settings from django.conf.urls import include, url from django.contrib import admin, auth from django.urls import resolve, reverse from django.views.generic.base import RedirectView from django.views.generic.edit import UpdateView from django.views.generic.list import ListView from troggle.core.views import caves, other, statistics, survex from troggle.core.views.auth import expologin, expologout from troggle.core.views.caves import cavepage, ent from troggle.core.views.expo import ( editexpopage, expofiles_redirect, expofilessingle, expopage, map, mapfile, mediapage, ) from troggle.core.views.logbooks import ( Expeditions_jsonListView, Expeditions_tsvListView, expedition, get_logbook_entries, get_people, logbookentry, notablepersons, person, personexpedition, ) from troggle.core.views.other import controlpanel from troggle.core.views.prospect import prospecting, prospecting_image from troggle.core.views.statistics import dataissues, pathsreport, stats from troggle.core.views.survex import survexcavesingle, survexcaveslist, svx class SubprocessTest(TestCase): @classmethod def setUpTestData(cls): pass def setUp(self): pass def tearDown(self): pass def test_utf8(self): """Expects that utf8 is the default encoding when opening files""" import locale import sys self.assertTrue( sys.getdefaultencoding() == "utf-8", f"{sys.getdefaultencoding()} - UTF8 error in getdefaultencoding" ) self.assertTrue( sys.getfilesystemencoding() == "utf-8", f"{sys.getfilesystemencoding()} - UTF8 error in getfilesystemencoding", ) self.assertTrue( locale.getdefaultlocale()[1] == "UTF-8", f"{locale.getdefaultlocale()} - UTF8 error in locale.getdefaultlocale", ) self.assertTrue( locale.getpreferredencoding() == "UTF-8", f"{locale.getpreferredencoding()} - UTF8 error in locale.getpreferredencoding", ) def test_installs(self): """Expects external software installed: cavern, survexport, git (but not whether it actually works) """ import troggle.settings as settings for i in [settings.CAVERN, settings.SURVEXPORT, settings.GIT]: # Define command as string and then split() into list format cmd = f"which {i}".split() try: sp = subprocess.check_call(cmd, shell=False) except subprocess.CalledProcessError: self.assertTrue(False, f"no {i} installed") def test_repos_git_status(self): """Expects clean git repos with no added files and no merge failures""" from pathlib import Path import troggle.settings as settings TROGGLE_PATH = Path(settings.REPOS_ROOT_PATH) / "troggle" for cwd in [settings.SURVEX_DATA, settings.EXPOWEB, settings.DRAWINGS_DATA, TROGGLE_PATH]: sp = subprocess.run([settings.GIT, "status"], cwd=cwd, capture_output=True, text=True) out = str(sp.stdout) if len(out) > 160: out = out[:75] + "\n \n" + out[-75:] print(f"git output: {cwd}:\n # {sp.stderr=}\n # sp.stdout={out} \n # return code: {str(sp.returncode)}") if sp.returncode != 0: print(f"git output: {cwd}:\n # {sp.stderr=}\n # sp.stdout={out} \n # return code: {str(sp.returncode)}") self.assertTrue(sp.returncode == 0, f"{cwd} - git is unhappy") content = sp.stdout ph = r"Your branch is up[ -]to[ -]date" phmatch = re.search(ph, content) msg = f'{cwd} - Failed to find expected git output: "{ph}"' self.assertIsNotNone(phmatch, msg) ph1 = r"no changes added to commit" phmatch1 = re.search(ph1, content) ph2 = r"nothing to commit" phmatch2 = re.search(ph2, content) phmatch = phmatch1 or phmatch2 msg = f'{cwd} - Failed to find expected git output: "{ph1}" or "{ph2}"' self.assertIsNotNone(phmatch, msg) def test_loser_survex_status(self): """Expects no failures of survex files""" from pathlib import Path import troggle.settings as settings cwd = settings.SURVEX_DATA for survey in ["1623.svx", "1626.svx"]: sp = subprocess.run([settings.CAVERN, survey], cwd=cwd, capture_output=True, text=True) out = str(sp.stdout) if len(out) > 160: out = out[:75] + "\n \n" + out[-75:] # print(f'survex output: {cwd}:\n # {sp.stderr=}\n # sp.stdout={out} \n # return code: {str(sp.returncode)}') if sp.returncode != 0: print( f"survex output: {cwd}:\n # {sp.stderr=}\n # sp.stdout={out} \n # return code: {str(sp.returncode)}" ) self.assertTrue(sp.returncode == 0, f"{cwd} - survex is unhappy") content = sp.stdout ph = r"Total length of survey legs" phmatch = re.search(ph, content) msg = f'{cwd} - Failed to find expected survex output: "{ph}"' self.assertIsNotNone(phmatch, msg) ph1 = r"Time used" phmatch1 = re.search(ph1, content) ph2 = r"vertical length of survey le" phmatch2 = re.search(ph2, content) phmatch = phmatch1 or phmatch2 msg = f'{cwd} - Failed to find expected survex output: "{ph1}" or "{ph2}"' self.assertIsNotNone(phmatch, msg)