diff --git a/.woodpecker.yaml b/.woodpecker.yaml index c220704..38deed6 100644 --- a/.woodpecker.yaml +++ b/.woodpecker.yaml @@ -14,4 +14,11 @@ steps: - cd ./src - python manage.py collectstatic --noinput - 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" diff --git a/src/functional_tests/base.py b/src/functional_tests/base.py index 91c7b7e..2098df1 100644 --- a/src/functional_tests/base.py +++ b/src/functional_tests/base.py @@ -1,7 +1,9 @@ import os import time +from datetime import datetime from django.contrib.staticfiles.testing import StaticLiveServerTestCase +from pathlib import Path from selenium import webdriver from selenium.common.exceptions import WebDriverException from selenium.webdriver.common.by import By @@ -9,7 +11,9 @@ from selenium.webdriver.common.keys import Keys from .container_commands import reset_database + MAX_WAIT = 10 +SCREEN_DUMP_LOCATION = Path(__file__).absolute().parent / "screendumps" # Decorator fns @@ -25,7 +29,7 @@ def wait(fn): time.sleep(0.5) return modified_fn - +# Functional Tests class FunctionalTest(StaticLiveServerTestCase): # Helper methods def setUp(self): @@ -39,7 +43,32 @@ class FunctionalTest(StaticLiveServerTestCase): reset_database(self.test_server) 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() + 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 def wait_for(self, fn):