Skip to content

Commit 78ad0fc

Browse files
committed
tests: Add coloured runner
This is nicer to work with than a wall of red text. Signed-off-by: Stephen Finucane <stephen@that.guru>
1 parent 002f86e commit 78ad0fc

File tree

3 files changed

+91
-1
lines changed

3 files changed

+91
-1
lines changed

patchwork/settings/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141

4242
USE_TZ = False
4343

44-
TEST_RUNNER = 'django.test.runner.DiscoverRunner'
44+
TEST_RUNNER = 'patchwork.tests.runner.PatchworkTestRunner'
4545

4646
ROOT_URLCONF = 'patchwork.urls'
4747

patchwork/tests/runner.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Patchwork - automated patch tracking system
2+
# Copyright (C) 2023 Stephen Finucane <stephen@that.guru>
3+
#
4+
# SPDX-License-Identifier: GPL-2.0-or-later
5+
6+
from unittest import TestResult
7+
from unittest import TextTestRunner
8+
9+
from django.test.runner import DiscoverRunner
10+
from termcolor import colored
11+
12+
13+
# Based on upstream source
14+
# https://github.com/python/cpython/blob/v3.11.4/Lib/unittest/runner.py
15+
class ColourTextTestResult(TestResult):
16+
def __init__(self, stream, descriptions, verbosity, *, durations=None):
17+
super().__init__(stream, descriptions, verbosity)
18+
19+
self.stream = stream
20+
self.descriptions = descriptions
21+
self.verbosity = verbosity
22+
23+
def startTest(self, test):
24+
super().startTest(test)
25+
if self.verbosity > 1:
26+
self.stream.write(colored(str(test), 'white'))
27+
self.stream.write(colored(' ... ', 'white'))
28+
self.stream.flush()
29+
30+
def _reportResult(self, short, long, color):
31+
if self.verbosity == 1:
32+
self.stream.write(short)
33+
else: # > 1
34+
self.stream.writeln(colored(long, color, attrs=['bold']))
35+
self.stream.flush()
36+
37+
def addSuccess(self, test):
38+
super().addSuccess(test)
39+
self._reportResult('.', 'ok', 'green')
40+
41+
def addError(self, test, err):
42+
super().addError(test, err)
43+
self._reportResult('E', 'ERROR', 'red')
44+
45+
def addFailure(self, test, err):
46+
super().addFailure(test, err)
47+
self._reportResult('F', 'FAIL', 'yellow')
48+
49+
def addSkip(self, test, reason):
50+
super().addSkip(test, reason)
51+
self._reportResult('s', f'skipped {reason!r}', 'white')
52+
53+
def addExpectedFailure(self, test, err):
54+
super().addExpectedFailure(test, err)
55+
self._reportResult('s', 'expected failure', 'blue')
56+
57+
def addUnexpectedSuccess(self, test):
58+
super().addUnexpectedSuccess(test)
59+
self._reportResult('s', 'unexpected success', 'red')
60+
61+
def printErrors(self):
62+
self.stream.writeln()
63+
self.stream.flush()
64+
65+
self.printErrorList('ERROR', self.errors)
66+
self.printErrorList('FAIL', self.failures)
67+
68+
unexpectedSuccesses = getattr(self, 'unexpectedSuccesses', ())
69+
if unexpectedSuccesses:
70+
self.stream.writeln('=' * 70)
71+
for test in unexpectedSuccesses:
72+
self.stream.writeln(f"UNEXPECTED SUCCESS: {str(test)}")
73+
self.stream.flush()
74+
75+
def printErrorList(self, flavour, errors):
76+
for test, err in errors:
77+
self.stream.writeln('=' * 70)
78+
self.stream.writeln(f'{flavour}: {str(test)}')
79+
self.stream.writeln('-' * 70)
80+
self.stream.writeln(str(err))
81+
self.stream.flush()
82+
83+
84+
class ColourTextTestRunner(TextTestRunner):
85+
resultclass = ColourTextTestResult
86+
87+
88+
class PatchworkTestRunner(DiscoverRunner):
89+
test_runner = ColourTextTestRunner

requirements-test.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ sqlparse~=0.4.0
44
python-dateutil~=2.8.0
55
tblib~=2.0.0
66
openapi-core~=0.18.0
7+
termcolor~=2.3.0

0 commit comments

Comments
 (0)