From: Stephen Finucane Date: Wed, 2 Aug 2023 11:23:45 +0000 (+0100) Subject: tests: Add coloured runner X-Git-Tag: v3.2.0~60 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=78ad0fccd69b9e9ce1cbb3ce37bd348115243acf;p=thirdparty%2Fpatchwork.git tests: Add coloured runner This is nicer to work with than a wall of red text. Signed-off-by: Stephen Finucane --- diff --git a/patchwork/settings/base.py b/patchwork/settings/base.py index 965c949f..dccab6c3 100644 --- a/patchwork/settings/base.py +++ b/patchwork/settings/base.py @@ -41,7 +41,7 @@ USE_I18N = False USE_TZ = False -TEST_RUNNER = 'django.test.runner.DiscoverRunner' +TEST_RUNNER = 'patchwork.tests.runner.PatchworkTestRunner' ROOT_URLCONF = 'patchwork.urls' diff --git a/patchwork/tests/runner.py b/patchwork/tests/runner.py new file mode 100644 index 00000000..84f3abad --- /dev/null +++ b/patchwork/tests/runner.py @@ -0,0 +1,89 @@ +# Patchwork - automated patch tracking system +# Copyright (C) 2023 Stephen Finucane +# +# SPDX-License-Identifier: GPL-2.0-or-later + +from unittest import TestResult +from unittest import TextTestRunner + +from django.test.runner import DiscoverRunner +from termcolor import colored + + +# Based on upstream source +# https://github.com/python/cpython/blob/v3.11.4/Lib/unittest/runner.py +class ColourTextTestResult(TestResult): + def __init__(self, stream, descriptions, verbosity, *, durations=None): + super().__init__(stream, descriptions, verbosity) + + self.stream = stream + self.descriptions = descriptions + self.verbosity = verbosity + + def startTest(self, test): + super().startTest(test) + if self.verbosity > 1: + self.stream.write(colored(str(test), 'white')) + self.stream.write(colored(' ... ', 'white')) + self.stream.flush() + + def _reportResult(self, short, long, color): + if self.verbosity == 1: + self.stream.write(short) + else: # > 1 + self.stream.writeln(colored(long, color, attrs=['bold'])) + self.stream.flush() + + def addSuccess(self, test): + super().addSuccess(test) + self._reportResult('.', 'ok', 'green') + + def addError(self, test, err): + super().addError(test, err) + self._reportResult('E', 'ERROR', 'red') + + def addFailure(self, test, err): + super().addFailure(test, err) + self._reportResult('F', 'FAIL', 'yellow') + + def addSkip(self, test, reason): + super().addSkip(test, reason) + self._reportResult('s', f'skipped {reason!r}', 'white') + + def addExpectedFailure(self, test, err): + super().addExpectedFailure(test, err) + self._reportResult('s', 'expected failure', 'blue') + + def addUnexpectedSuccess(self, test): + super().addUnexpectedSuccess(test) + self._reportResult('s', 'unexpected success', 'red') + + def printErrors(self): + self.stream.writeln() + self.stream.flush() + + self.printErrorList('ERROR', self.errors) + self.printErrorList('FAIL', self.failures) + + unexpectedSuccesses = getattr(self, 'unexpectedSuccesses', ()) + if unexpectedSuccesses: + self.stream.writeln('=' * 70) + for test in unexpectedSuccesses: + self.stream.writeln(f"UNEXPECTED SUCCESS: {str(test)}") + self.stream.flush() + + def printErrorList(self, flavour, errors): + for test, err in errors: + self.stream.writeln('=' * 70) + self.stream.writeln(f'{flavour}: {str(test)}') + self.stream.writeln('-' * 70) + self.stream.writeln(str(err)) + self.stream.flush() + + +class ColourTextTestRunner(TextTestRunner): + resultclass = ColourTextTestResult + + +class PatchworkTestRunner(DiscoverRunner): + test_runner = ColourTextTestRunner diff --git a/requirements-test.txt b/requirements-test.txt index af4f8635..f538b61d 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -4,3 +4,4 @@ sqlparse~=0.4.0 python-dateutil~=2.8.0 tblib~=2.0.0 openapi-core~=0.18.0 +termcolor~=2.3.0