Skip to content

colortest

ontopy.colortest

Print tests in colors.

Adapted from https://github.com/meshy/colour-runner by Charlie Denton License: MIT

ColourTextTestResult (TestResult)

A test result class that prints colour formatted text results to a stream.

Based on https://github.com/python/cpython/blob/3.3/Lib/unittest/runner.py

Source code in ontopy/colortest.py
class ColourTextTestResult(TestResult):
    """
    A test result class that prints colour formatted text results to a stream.

    Based on https://github.com/python/cpython/blob/3.3/Lib/unittest/runner.py
    """

    formatter = formatters.Terminal256Formatter()  # pylint: disable=no-member
    lexer = Lexer()
    separator1 = "=" * 70
    separator2 = "-" * 70
    indent = " " * 4
    # if `checkmode` is true, simplified output will be generated with
    # no traceback
    checkmode = False
    _terminal = Terminal()
    colours = {
        None: str,
        "error": _terminal.bold_red,
        "expected": _terminal.blue,
        # "fail": _terminal.bold_yellow,
        "fail": _terminal.bold_magenta,
        "skip": str,
        "success": _terminal.green,
        "title": _terminal.blue,
        "unexpected": _terminal.bold_red,
    }

    _test_class = None

    def __init__(self, stream, descriptions, verbosity):
        super().__init__(stream, descriptions, verbosity)
        self.stream = stream
        self.show_all = verbosity > 1
        self.dots = verbosity == 1
        self.descriptions = descriptions

    def getShortDescription(self, test):
        doc_first_line = test.shortDescription()
        if self.descriptions and doc_first_line:
            return self.indent + doc_first_line
        return self.indent + test._testMethodName

    def getLongDescription(self, test):
        doc_first_line = test.shortDescription()
        if self.descriptions and doc_first_line:
            return "\n".join((str(test), doc_first_line))
        return str(test)

    def getClassDescription(self, test):
        test_class = test.__class__
        doc = test_class.__doc__
        if self.descriptions and doc:
            return doc.split("\n")[0].strip()
        return strclass(test_class)

    def startTest(self, test):
        super().startTest(test)
        pos = 0
        if self.show_all:
            if self._test_class != test.__class__:
                self._test_class = test.__class__
                title = self.getClassDescription(test)
                self.stream.writeln(self.colours["title"](title))
            descr = self.getShortDescription(test)
            self.stream.write(descr)
            pos += len(descr)
            self.stream.write(" " * (70 - pos))
            # self.stream.write(' ' * (self._terminal.width - 10 - pos))
            # self.stream.write(' ... ')
            self.stream.flush()

    def printResult(self, short, extended, colour_key=None):
        colour = self.colours[colour_key]
        if self.show_all:
            self.stream.writeln(colour(extended))
        elif self.dots:
            self.stream.write(colour(short))
            self.stream.flush()

    def addSuccess(self, test):
        super().addSuccess(test)
        self.printResult(".", "ok", "success")

    def addError(self, test, err):
        super().addError(test, err)
        self.printResult("E", "ERROR", "error")

    def addFailure(self, test, err):
        super().addFailure(test, err)
        self.printResult("F", "FAIL", "fail")

    def addSkip(self, test, reason):
        super().addSkip(test, reason)
        if self.checkmode:
            self.printResult("s", "skipped", "skip")
        else:
            self.printResult("s", f"skipped {reason!r}", "skip")

    def addExpectedFailure(self, test, err):
        super().addExpectedFailure(test, err)
        self.printResult("x", "expected failure", "expected")

    def addUnexpectedSuccess(self, test):
        super().addUnexpectedSuccess(test)
        self.printResult("u", "unexpected success", "unexpected")

    def printErrors(self):
        if self.dots or self.show_all:
            self.stream.writeln()
        self.printErrorList("ERROR", self.errors)
        self.printErrorList("FAIL", self.failures)

    def printErrorList(self, flavour, errors):
        colour = self.colours[flavour.lower()]

        for test, err in errors:
            if self.checkmode and flavour == "FAIL":
                self.stream.writeln(self.separator1)
                title = f"{flavour}: {test.shortDescription()}"
                self.stream.writeln(colour(title))
                self.stream.writeln(str(test))
                if self.show_all:
                    self.stream.writeln(self.separator2)
                    lines = str(err).split("\n")
                    i = 1
                    for line in lines[1:]:
                        if line.startswith(" "):
                            i += 1
                        else:
                            break
                    self.stream.writeln(
                        highlight(
                            "\n".join(lines[i:]), self.lexer, self.formatter
                        )
                    )
            else:
                self.stream.writeln(self.separator1)
                title = f"{flavour}: {self.getLongDescription(test)}"
                self.stream.writeln(colour(title))
                self.stream.writeln(self.separator2)
                self.stream.writeln(highlight(err, self.lexer, self.formatter))

addError(self, test, err)

Called when an error has occurred. 'err' is a tuple of values as returned by sys.exc_info().

Source code in ontopy/colortest.py
def addError(self, test, err):
    super().addError(test, err)
    self.printResult("E", "ERROR", "error")

addExpectedFailure(self, test, err)

Called when an expected failure/error occurred.

Source code in ontopy/colortest.py
def addExpectedFailure(self, test, err):
    super().addExpectedFailure(test, err)
    self.printResult("x", "expected failure", "expected")

addFailure(self, test, err)

Called when an error has occurred. 'err' is a tuple of values as returned by sys.exc_info().

Source code in ontopy/colortest.py
def addFailure(self, test, err):
    super().addFailure(test, err)
    self.printResult("F", "FAIL", "fail")

addSkip(self, test, reason)

Called when a test is skipped.

Source code in ontopy/colortest.py
def addSkip(self, test, reason):
    super().addSkip(test, reason)
    if self.checkmode:
        self.printResult("s", "skipped", "skip")
    else:
        self.printResult("s", f"skipped {reason!r}", "skip")

addSuccess(self, test)

Called when a test has completed successfully

Source code in ontopy/colortest.py
def addSuccess(self, test):
    super().addSuccess(test)
    self.printResult(".", "ok", "success")

addUnexpectedSuccess(self, test)

Called when a test was expected to fail, but succeed.

Source code in ontopy/colortest.py
def addUnexpectedSuccess(self, test):
    super().addUnexpectedSuccess(test)
    self.printResult("u", "unexpected success", "unexpected")

printErrors(self)

Called by TestRunner after test run

Source code in ontopy/colortest.py
def printErrors(self):
    if self.dots or self.show_all:
        self.stream.writeln()
    self.printErrorList("ERROR", self.errors)
    self.printErrorList("FAIL", self.failures)

startTest(self, test)

Called when the given test is about to be run

Source code in ontopy/colortest.py
def startTest(self, test):
    super().startTest(test)
    pos = 0
    if self.show_all:
        if self._test_class != test.__class__:
            self._test_class = test.__class__
            title = self.getClassDescription(test)
            self.stream.writeln(self.colours["title"](title))
        descr = self.getShortDescription(test)
        self.stream.write(descr)
        pos += len(descr)
        self.stream.write(" " * (70 - pos))
        # self.stream.write(' ' * (self._terminal.width - 10 - pos))
        # self.stream.write(' ... ')
        self.stream.flush()

ColourTextTestRunner (TextTestRunner)

A test runner that uses colour in its output.

Source code in ontopy/colortest.py
class ColourTextTestRunner(
    TextTestRunner
):  # pylint: disable=too-few-public-methods
    """A test runner that uses colour in its output."""

    resultclass = ColourTextTestResult

resultclass (TestResult)

A test result class that prints colour formatted text results to a stream.

Based on https://github.com/python/cpython/blob/3.3/Lib/unittest/runner.py

Source code in ontopy/colortest.py
class ColourTextTestResult(TestResult):
    """
    A test result class that prints colour formatted text results to a stream.

    Based on https://github.com/python/cpython/blob/3.3/Lib/unittest/runner.py
    """

    formatter = formatters.Terminal256Formatter()  # pylint: disable=no-member
    lexer = Lexer()
    separator1 = "=" * 70
    separator2 = "-" * 70
    indent = " " * 4
    # if `checkmode` is true, simplified output will be generated with
    # no traceback
    checkmode = False
    _terminal = Terminal()
    colours = {
        None: str,
        "error": _terminal.bold_red,
        "expected": _terminal.blue,
        # "fail": _terminal.bold_yellow,
        "fail": _terminal.bold_magenta,
        "skip": str,
        "success": _terminal.green,
        "title": _terminal.blue,
        "unexpected": _terminal.bold_red,
    }

    _test_class = None

    def __init__(self, stream, descriptions, verbosity):
        super().__init__(stream, descriptions, verbosity)
        self.stream = stream
        self.show_all = verbosity > 1
        self.dots = verbosity == 1
        self.descriptions = descriptions

    def getShortDescription(self, test):
        doc_first_line = test.shortDescription()
        if self.descriptions and doc_first_line:
            return self.indent + doc_first_line
        return self.indent + test._testMethodName

    def getLongDescription(self, test):
        doc_first_line = test.shortDescription()
        if self.descriptions and doc_first_line:
            return "\n".join((str(test), doc_first_line))
        return str(test)

    def getClassDescription(self, test):
        test_class = test.__class__
        doc = test_class.__doc__
        if self.descriptions and doc:
            return doc.split("\n")[0].strip()
        return strclass(test_class)

    def startTest(self, test):
        super().startTest(test)
        pos = 0
        if self.show_all:
            if self._test_class != test.__class__:
                self._test_class = test.__class__
                title = self.getClassDescription(test)
                self.stream.writeln(self.colours["title"](title))
            descr = self.getShortDescription(test)
            self.stream.write(descr)
            pos += len(descr)
            self.stream.write(" " * (70 - pos))
            # self.stream.write(' ' * (self._terminal.width - 10 - pos))
            # self.stream.write(' ... ')
            self.stream.flush()

    def printResult(self, short, extended, colour_key=None):
        colour = self.colours[colour_key]
        if self.show_all:
            self.stream.writeln(colour(extended))
        elif self.dots:
            self.stream.write(colour(short))
            self.stream.flush()

    def addSuccess(self, test):
        super().addSuccess(test)
        self.printResult(".", "ok", "success")

    def addError(self, test, err):
        super().addError(test, err)
        self.printResult("E", "ERROR", "error")

    def addFailure(self, test, err):
        super().addFailure(test, err)
        self.printResult("F", "FAIL", "fail")

    def addSkip(self, test, reason):
        super().addSkip(test, reason)
        if self.checkmode:
            self.printResult("s", "skipped", "skip")
        else:
            self.printResult("s", f"skipped {reason!r}", "skip")

    def addExpectedFailure(self, test, err):
        super().addExpectedFailure(test, err)
        self.printResult("x", "expected failure", "expected")

    def addUnexpectedSuccess(self, test):
        super().addUnexpectedSuccess(test)
        self.printResult("u", "unexpected success", "unexpected")

    def printErrors(self):
        if self.dots or self.show_all:
            self.stream.writeln()
        self.printErrorList("ERROR", self.errors)
        self.printErrorList("FAIL", self.failures)

    def printErrorList(self, flavour, errors):
        colour = self.colours[flavour.lower()]

        for test, err in errors:
            if self.checkmode and flavour == "FAIL":
                self.stream.writeln(self.separator1)
                title = f"{flavour}: {test.shortDescription()}"
                self.stream.writeln(colour(title))
                self.stream.writeln(str(test))
                if self.show_all:
                    self.stream.writeln(self.separator2)
                    lines = str(err).split("\n")
                    i = 1
                    for line in lines[1:]:
                        if line.startswith(" "):
                            i += 1
                        else:
                            break
                    self.stream.writeln(
                        highlight(
                            "\n".join(lines[i:]), self.lexer, self.formatter
                        )
                    )
            else:
                self.stream.writeln(self.separator1)
                title = f"{flavour}: {self.getLongDescription(test)}"
                self.stream.writeln(colour(title))
                self.stream.writeln(self.separator2)
                self.stream.writeln(highlight(err, self.lexer, self.formatter))

addError(self, test, err)

Called when an error has occurred. 'err' is a tuple of values as returned by sys.exc_info().

Source code in ontopy/colortest.py
def addError(self, test, err):
    super().addError(test, err)
    self.printResult("E", "ERROR", "error")

addExpectedFailure(self, test, err)

Called when an expected failure/error occurred.

Source code in ontopy/colortest.py
def addExpectedFailure(self, test, err):
    super().addExpectedFailure(test, err)
    self.printResult("x", "expected failure", "expected")

addFailure(self, test, err)

Called when an error has occurred. 'err' is a tuple of values as returned by sys.exc_info().

Source code in ontopy/colortest.py
def addFailure(self, test, err):
    super().addFailure(test, err)
    self.printResult("F", "FAIL", "fail")

addSkip(self, test, reason)

Called when a test is skipped.

Source code in ontopy/colortest.py
def addSkip(self, test, reason):
    super().addSkip(test, reason)
    if self.checkmode:
        self.printResult("s", "skipped", "skip")
    else:
        self.printResult("s", f"skipped {reason!r}", "skip")

addSuccess(self, test)

Called when a test has completed successfully

Source code in ontopy/colortest.py
def addSuccess(self, test):
    super().addSuccess(test)
    self.printResult(".", "ok", "success")

addUnexpectedSuccess(self, test)

Called when a test was expected to fail, but succeed.

Source code in ontopy/colortest.py
def addUnexpectedSuccess(self, test):
    super().addUnexpectedSuccess(test)
    self.printResult("u", "unexpected success", "unexpected")

printErrors(self)

Called by TestRunner after test run

Source code in ontopy/colortest.py
def printErrors(self):
    if self.dots or self.show_all:
        self.stream.writeln()
    self.printErrorList("ERROR", self.errors)
    self.printErrorList("FAIL", self.failures)

startTest(self, test)

Called when the given test is about to be run

Source code in ontopy/colortest.py
def startTest(self, test):
    super().startTest(test)
    pos = 0
    if self.show_all:
        if self._test_class != test.__class__:
            self._test_class = test.__class__
            title = self.getClassDescription(test)
            self.stream.writeln(self.colours["title"](title))
        descr = self.getShortDescription(test)
        self.stream.write(descr)
        pos += len(descr)
        self.stream.write(" " * (70 - pos))
        # self.stream.write(' ' * (self._terminal.width - 10 - pos))
        # self.stream.write(' ... ')
        self.stream.flush()