functional_tests.base updated w. many helper functions to save screendumps on server after test failures; woodpecker pipeline updated accordingly
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
Disco DeDisco
2026-02-11 15:12:04 -05:00
parent 7f61dbd205
commit bcadb28017
2 changed files with 37 additions and 1 deletions

View File

@@ -14,4 +14,11 @@ steps:
- cd ./src - cd ./src
- python manage.py collectstatic --noinput - python manage.py collectstatic --noinput
- python manage.py test functional_tests - python manage.py test functional_tests
- name: screendumps
image: gitea.earthmanrpg.me/discoman/python-tdd-ci:latest
when:
- status: failure
commands:
- cat ./src/functional_tests/screendumps/*.html || echo "No screendumps found"

View File

@@ -1,7 +1,9 @@
import os import os
import time import time
from datetime import datetime
from django.contrib.staticfiles.testing import StaticLiveServerTestCase from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from pathlib import Path
from selenium import webdriver from selenium import webdriver
from selenium.common.exceptions import WebDriverException from selenium.common.exceptions import WebDriverException
from selenium.webdriver.common.by import By from selenium.webdriver.common.by import By
@@ -9,7 +11,9 @@ from selenium.webdriver.common.keys import Keys
from .container_commands import reset_database from .container_commands import reset_database
MAX_WAIT = 10 MAX_WAIT = 10
SCREEN_DUMP_LOCATION = Path(__file__).absolute().parent / "screendumps"
# Decorator fns # Decorator fns
@@ -25,7 +29,7 @@ def wait(fn):
time.sleep(0.5) time.sleep(0.5)
return modified_fn return modified_fn
# Functional Tests
class FunctionalTest(StaticLiveServerTestCase): class FunctionalTest(StaticLiveServerTestCase):
# Helper methods # Helper methods
def setUp(self): def setUp(self):
@@ -39,7 +43,32 @@ class FunctionalTest(StaticLiveServerTestCase):
reset_database(self.test_server) reset_database(self.test_server)
def tearDown(self): def tearDown(self):
if self._test_has_failed():
if not SCREEN_DUMP_LOCATION.exists():
SCREEN_DUMP_LOCATION.mkdir(parents=True)
self.take_screenshot()
self.dump_html()
self.browser.quit() self.browser.quit()
super().tearDown()
def _test_has_failed(self):
return self._outcome.result.failures or self._outcome.result.errors
def take_screenshot(self):
path = SCREEN_DUMP_LOCATION / self._get_filename("png")
print("screendumping to", path)
self.browser.get_screenshot_as_file(str(path))
def dump_html(self):
path = SCREEN_DUMP_LOCATION / self._get_filename("html")
print("dumping page html to", path)
path.write_text(self.browser.page_source)
def _get_filename(self, extension):
timestamp = datetime.now().isoformat().replace(":", ".")
return (
f"{self.__class__.__name__}.{self._testMethodName}-{timestamp}.{extension}"
)
@wait @wait
def wait_for(self, fn): def wait_for(self, fn):