""" 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.0/topics/testing/tools/ """ import unittest import re import subprocess from django.test import TestCase, SimpleTestCase, Client 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 troggle.core.utils import save_carefully from functools import reduce def test_import_parsers_survex(self): import troggle.settings as settings import troggle.core.models.troggle as models import troggle.core.models.survex as models_survex import troggle.core.models.caves as models_caves from troggle.parsers.people import GetPersonExpeditionNameLookup from troggle.core.views.other import frontpage from troggle.core.views.caves import ent, cavepage from troggle.core.views import scans, drawings, other, caves, statistics, survex, uploads def test_import_views_uploads(self): from troggle.core.views.uploads import dwgupload, scanupload def test_import_parsers_QMs(self): from troggle.core.models.caves import QM, Cave, LogbookEntry 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 troggle.core.models.troggle import DataIssue, Expedition from troggle.core.models.caves import Cave, LogbookEntry, PersonTrip from parsers.people import GetPersonExpeditionNameLookup def test_import_core_views_caves(self): from django.http import HttpResponse, HttpResponseRedirect from django.shortcuts import get_object_or_404, render import troggle.core.views.expo from troggle.core.models.troggle import Expedition from troggle.core.models.caves import CaveSlug, Cave, CaveAndEntrance, QM, EntranceSlug, Entrance, Area, SurvexStation from troggle.core.forms import CaveForm, CaveAndEntranceFormSet, EntranceForm, EntranceLetterForm from troggle.core.views.auth import login_required_if_public from django.contrib.auth.decorators import login_required from django.conf import settings def test_import_parsers_mix(self): from troggle.parsers.logbooks import GetCaveLookup import troggle.settings import troggle.parsers.caves import troggle.parsers.people import troggle.parsers.drawings import troggle.parsers.scans import troggle.parsers.logbooks import troggle.parsers.QMs import troggle.parsers.survex def test_import_imports(self): from django.core import management from django.db import connection, close_old_connections, connections from django.contrib.auth.models import User 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 url, include from django.contrib import admin from django.contrib import auth from django.urls import reverse, resolve 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 other, caves, statistics, survex from troggle.core.views.auth import expologin, expologout from troggle.core.views.caves import ent, cavepage from troggle.core.views.expo import expofiles_redirect, expofilessingle, expopage, editexpopage, mediapage, map, mapfile from troggle.core.views.logbooks import expedition, personexpedition, Expeditions_tsvListView, Expeditions_jsonListView from troggle.core.views.logbooks import get_logbook_entries, logbookentry, logbookSearch from troggle.core.views.logbooks import notablepersons, person, get_people from troggle.core.views.other import controlpanel from troggle.core.views.prospect import prospecting from troggle.core.views.prospect import prospecting_image from troggle.core.views.statistics import pathsreport, stats, dataissues from troggle.core.views.survex import survexcaveslist, survexcavesingle, 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 sys import locale 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) print(f'git output: {cwd}:\n # {sp.stderr=}\n # {sp.stdout=} \n # return code: {str(sp.returncode)}') if sp.returncode != 0: print(f'git output: {cwd}:\n # {sp.stderr=}\n # {sp.stdout=} \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) print(f'survex output: {cwd}:\n # {sp.stderr=}\n # {sp.stdout=} \n # return code: {str(sp.returncode)}') if sp.returncode != 0: print(f'survex output: {cwd}:\n # {sp.stderr=}\n # {sp.stdout=} \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)