Backed out 5 changesets (bug 1421799) for failing firefox ui functional tests. r=backout on a CLOSED TREE
authorSebastian Hengst <archaeopteryx@coole-files.de>
Wed, 03 Jan 2018 20:21:28 +0200
changeset 397609 9dcfb0365f3c758f9edbea67d94614cd582c1559
parent 397608 f491d9b28b7601af749bbab00c1aacc022d5dd61
child 397610 29245716751b536dcd730e9a7b81b1936863b8c3
push id33180
push useraciure@mozilla.com
push dateWed, 03 Jan 2018 21:35:29 +0000
treeherdermozilla-central@29245716751b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1421799
milestone59.0a1
backs outf9f32474fdaf5914832d256293ee1f98c6bf2561
18b4fa2419365231eb7f2fcf581112ce8f8f3e2e
88dca5c8cfac95561af3d6f36389e3f16460ffdc
8c1f1ab754a53611748461ef815ed8f26be119ec
e028f677bc8064dfbed6b752296f6913460a0dca
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 5 changesets (bug 1421799) for failing firefox ui functional tests. r=backout on a CLOSED TREE Backed out changeset f9f32474fdaf (bug 1421799) Backed out changeset 18b4fa241936 (bug 1421799) Backed out changeset 88dca5c8cfac (bug 1421799) Backed out changeset 8c1f1ab754a5 (bug 1421799) Backed out changeset e028f677bc80 (bug 1421799)
layout/tools/reftest/output.py
layout/tools/reftest/runreftest.py
python/mozbuild/mozbuild/action/test_archive.py
python/mozterm/setup.py
testing/config/mozbase_requirements.txt
testing/mach_commands.py
testing/mochitest/mach_commands.py
testing/mozbase/mozlog/mozlog/formatters/machformatter.py
--- a/layout/tools/reftest/output.py
+++ b/layout/tools/reftest/output.py
@@ -123,17 +123,16 @@ class OutputHandler(object):
     """Process the output of a process during a test run and translate
     raw data logged from reftest.js to an appropriate structured log action,
     where applicable.
     """
 
     def __init__(self, log, utilityPath, symbolsPath=None):
         self.stack_fixer_function = get_stack_fixer_function(utilityPath, symbolsPath)
         self.log = log
-        self.proc_name = None
 
     def __call__(self, line):
         # need to return processed messages to appease remoteautomation.py
         if not line.strip():
             return []
         line = line.decode('utf-8', errors='replace')
 
         try:
@@ -147,10 +146,9 @@ class OutputHandler(object):
         else:
             self.verbatim(json.dumps(data))
 
         return [data]
 
     def verbatim(self, line):
         if self.stack_fixer_function:
             line = self.stack_fixer_function(line)
-        name = self.proc_name or threading.current_thread().name
-        self.log.process_output(name, line)
+        self.log.process_output(threading.current_thread().name, line)
--- a/layout/tools/reftest/runreftest.py
+++ b/layout/tools/reftest/runreftest.py
@@ -708,17 +708,16 @@ class RefTest(object):
                             process_class=mozprocess.ProcessHandlerMixin,
                             cmdargs=cmdargs,
                             env=env,
                             process_args=kp_kwargs)
         runner.start(debug_args=debug_args,
                      interactive=interactive,
                      outputTimeout=timeout)
         proc = runner.process_handler
-        outputHandler.proc_name = 'GECKO({})'.format(proc.pid)
 
         # Used to defer a possible IOError exception from Marionette
         marionette_exception = None
 
         if self.use_marionette:
             marionette_args = {
                 'socket_timeout': options.marionette_socket_timeout,
                 'startup_timeout': options.marionette_startup_timeout,
@@ -745,17 +744,16 @@ class RefTest(object):
                 # wrong with the process, like a crash or the socket is no
                 # longer open. We defer raising this specific error so that
                 # post-test checks for leaks and crashes are performed and
                 # reported first.
                 marionette_exception = sys.exc_info()
 
         status = runner.wait()
         runner.process_handler = None
-        outputHandler.proc_name = None
 
         if status:
             msg = "TEST-UNEXPECTED-FAIL | %s | application terminated with exit code %s" % \
                 (self.lastTestSeen, status)
             # use process_output so message is logged verbatim
             self.log.process_output(None, msg)
         else:
             self.lastTestSeen = self.TEST_SEEN_FINAL
--- a/python/mozbuild/mozbuild/action/test_archive.py
+++ b/python/mozbuild/mozbuild/action/test_archive.py
@@ -216,22 +216,16 @@ ARCHIVE_FILES = {
         },
         {
             'source': buildconfig.topsrcdir,
             'base': 'testing/web-platform/tests/tools/wptserve',
             'pattern': '**',
             'dest': 'tools/wptserve',
         },
         {
-            'source': buildconfig.topsrcdir,
-            'base': 'python/mozterm',
-            'pattern': '**',
-            'dest': 'tools/mozterm',
-        },
-        {
             'source': buildconfig.topobjdir,
             'base': '',
             'pattern': 'mozinfo.json',
         },
         {
             'source': buildconfig.topobjdir,
             'base': 'dist/bin',
             'patterns': [
deleted file mode 100644
--- a/python/mozterm/setup.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-from __future__ import absolute_import
-
-from setuptools import setup
-
-VERSION = '0.1.0'
-DEPS = []
-
-setup(
-    name='mozterm',
-    description='Terminal abstractions built around the blessings module.',
-    license='MPL 2.0',
-    author='Andrew Halberstadt',
-    author_email='ahalberstadt@mozilla.com',
-    url='',
-    packages=['mozterm'],
-    version=VERSION,
-    classifiers=[
-        'Environment :: Console',
-        'Development Status :: 3 - Alpha',
-        'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)',
-        'Natural Language :: English',
-    ],
-    install_requires=DEPS,
-)
--- a/testing/config/mozbase_requirements.txt
+++ b/testing/config/mozbase_requirements.txt
@@ -10,10 +10,8 @@
 ../mozbase/mozlog
 ../mozbase/moznetwork
 ../mozbase/mozprocess
 ../mozbase/mozprofile
 ../mozbase/mozrunner
 ../mozbase/mozscreenshot
 ../mozbase/moztest
 ../mozbase/mozversion
-
-../tools/mozterm
--- a/testing/mach_commands.py
+++ b/testing/mach_commands.py
@@ -64,34 +64,26 @@ class TestConfig(object):
         level_desc = "The default log level to use when running tests with `mach test`."
         level_choices = [l.lower() for l in log_levels]
         return [
             ('test.format', 'string', format_desc, 'tbpl', {'choices': format_choices}),
             ('test.level', 'string', level_desc, 'info', {'choices': level_choices}),
         ]
 
 
-def get_test_parser():
-    from mozlog.commandline import add_logging_group
-    parser = argparse.ArgumentParser()
-    parser.add_argument('what', default=None, nargs='*', help=TEST_HELP)
-    parser.add_argument('extra_args', default=None, nargs=argparse.REMAINDER,
-                        help="Extra arguments to pass to the underlying test command(s). "
-                             "If an underlying command doesn't recognize the argument, it "
-                             "will fail.")
-    add_logging_group(parser)
-    return parser
-
-
 @CommandProvider
 class Test(MachCommandBase):
     @Command('test', category='testing',
-             description='Run tests (detects the kind of test and runs it).',
-             parser=get_test_parser)
-    def test(self, what, extra_args, **log_args):
+             description='Run tests (detects the kind of test and runs it).')
+    @CommandArgument('what', default=None, nargs='*', help=TEST_HELP)
+    @CommandArgument('extra_args', default=None, nargs=argparse.REMAINDER,
+                     help="Extra arguments to pass to the underlying test command(s). "
+                          "If an underlying command doesn't recognize the argument, it "
+                          "will fail.")
+    def test(self, what, extra_args):
         """Run tests from names or paths.
 
         mach test accepts arguments specifying which tests to run. Each argument
         can be:
 
         * The path to a test file
         * A directory containing tests
         * A test suite name
@@ -105,32 +97,35 @@ class Test(MachCommandBase):
         When paths or directories are given, they are first resolved to test
         files known to the build system.
 
         If resolved tests belong to more than one test type/flavor/harness,
         the harness for each relevant type/flavor will be invoked. e.g. if
         you specify a directory with xpcshell and browser chrome mochitests,
         both harnesses will be invoked.
         """
-        from mozlog.commandline import setup_logging
+        from mozlog.commandline import log_formatters
+        from mozlog.handlers import StreamHandler, LogLevelFilter
+        from mozlog.structuredlog import StructuredLogger
         from moztest.resolve import TestResolver, TEST_FLAVORS, TEST_SUITES
 
         resolver = self._spawn(TestResolver)
         run_suites, run_tests = resolver.resolve_metadata(what)
 
         if not run_suites and not run_tests:
             print(UNKNOWN_TEST)
             return 1
 
         # Create shared logger
-        default_format = self._mach_context.settings['test']['format']
-        default_level = self._mach_context.settings['test']['level']
-        log = setup_logging('mach-test', log_args, {default_format: sys.stdout},
-                            {'level': default_level})
-        log.handlers[0].formatter.inner.summary_on_shutdown = True
+        formatter = log_formatters[self._mach_context.settings['test']['format']][0]()
+        formatter.summary_on_shutdown = True
+
+        level = self._mach_context.settings['test']['level']
+        log = StructuredLogger('mach-test')
+        log.add_handler(StreamHandler(sys.stdout, LogLevelFilter(formatter, level)))
 
         status = None
         for suite_name in run_suites:
             suite = TEST_SUITES[suite_name]
             kwargs = suite['kwargs']
             kwargs['log'] = log
 
             if 'mach_command' in suite:
--- a/testing/mochitest/mach_commands.py
+++ b/testing/mochitest/mach_commands.py
@@ -63,16 +63,23 @@ ROBOCOP_TESTS_NOT_FOUND = '''
 The robocop command could not find any tests under the following
 test path(s):
 
 {}
 
 Please check spelling and make sure the named tests exist.
 '''.lstrip()
 
+NOW_RUNNING = '''
+######
+### Now running mochitest-{}.
+######
+'''
+
+
 SUPPORTED_APPS = ['firefox', 'android']
 
 parser = None
 
 
 class MochitestRunner(MozbuildObject):
 
     """Easily run mochitests.
@@ -274,17 +281,19 @@ def verify_host_bin():
 @CommandProvider
 class MachCommands(MachCommandBase):
     @Command('mochitest', category='testing',
              conditions=[is_buildapp_in(*SUPPORTED_APPS)],
              description='Run any flavor of mochitest (integration test).',
              parser=setup_argument_parser)
     def run_mochitest_general(self, flavor=None, test_objects=None, resolve_tests=True, **kwargs):
         from mochitest_options import ALL_FLAVORS
-        from mozlog.commandline import setup_logging
+        from mozlog.commandline import log_formatters
+        from mozlog.handlers import StreamHandler, LogLevelFilter
+        from mozlog.structuredlog import StructuredLogger
 
         buildapp = None
         for app in SUPPORTED_APPS:
             if is_buildapp_in(app)(self):
                 buildapp = app
                 break
 
         flavors = None
@@ -295,21 +304,22 @@ class MachCommands(MachCommandBase):
                         continue
                     flavors = [fname]
                     break
         else:
             flavors = [f for f, v in ALL_FLAVORS.iteritems() if buildapp in v['enabled_apps']]
 
         if not kwargs.get('log'):
             # Create shared logger
-            default_format = self._mach_context.settings['test']['format']
-            default_level = self._mach_context.settings['test']['level']
-            kwargs['log'] = setup_logging('mach-mochitest', kwargs, {default_format: sys.stdout},
-                                          {'level': default_level})
-            kwargs['log'].handlers[0].formatter.inner.summary_on_shutdown = True
+            formatter = log_formatters[self._mach_context.settings['test']['format']][0]()
+            formatter.summary_on_shutdown = True
+
+            level = self._mach_context.settings['test']['level']
+            kwargs['log'] = StructuredLogger('mach-mochitest')
+            kwargs['log'].add_handler(StreamHandler(sys.stdout, LogLevelFilter(formatter, level)))
 
         from mozbuild.controller.building import BuildDriver
         self._ensure_state_subdir_exists('.')
 
         test_paths = kwargs['test_paths']
         kwargs['test_paths'] = []
 
         mochitest = self._spawn(MochitestRunner)
@@ -394,16 +404,20 @@ class MachCommands(MachCommandBase):
             grant_runtime_permissions(self)
             run_mochitest = mochitest.run_android_test
         else:
             run_mochitest = mochitest.run_desktop_test
 
         overall = None
         for (flavor, subsuite), tests in sorted(suites.items()):
             fobj = ALL_FLAVORS[flavor]
+            msg = fobj['aliases'][0]
+            if subsuite:
+                msg = '{} with subsuite {}'.format(msg, subsuite)
+            print(NOW_RUNNING.format(msg))
 
             harness_args = kwargs.copy()
             harness_args['subsuite'] = subsuite
             harness_args.update(fobj.get('extra_args', {}))
 
             result = run_mochitest(
                 self._mach_context,
                 tests=tests,
--- a/testing/mozbase/mozlog/mozlog/formatters/machformatter.py
+++ b/testing/mozbase/mozlog/mozlog/formatters/machformatter.py
@@ -2,60 +2,107 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 
 from __future__ import absolute_import
 
 import time
 
-from mozterm import Terminal
+try:
+    import blessings
+except ImportError:
+    blessings = None
 
 from . import base
 from .process import strstatus
 from ..handlers import SummaryHandler
 
 
 def format_seconds(total):
     """Format number of seconds to MM:SS.DD form."""
     minutes, seconds = divmod(total, 60)
     return '%2d:%05.2f' % (minutes, seconds)
 
 
+class NullTerminal(object):
+
+    def __getattr__(self, name):
+        return self._id
+
+    def _id(self, value):
+        return value
+
+
 class MachFormatter(base.BaseFormatter):
 
     def __init__(self, start_time=None, write_interval=False, write_times=True,
                  terminal=None, disable_colors=False, summary_on_shutdown=False, **kwargs):
         super(MachFormatter, self).__init__(**kwargs)
 
+        if disable_colors:
+            terminal = None
+        elif terminal is None and blessings is not None:
+            terminal = blessings.Terminal()
+
         if start_time is None:
             start_time = time.time()
         start_time = int(start_time * 1000)
         self.start_time = start_time
         self.write_interval = write_interval
         self.write_times = write_times
         self.status_buffer = {}
         self.has_unexpected = {}
         self.last_time = None
-        self.term = Terminal(disable_styling=disable_colors)
+        self.terminal = terminal
         self.verbose = False
         self._known_pids = set()
 
         self.summary = SummaryHandler()
         self.summary_on_shutdown = summary_on_shutdown
 
     def __call__(self, data):
         self.summary(data)
 
         s = super(MachFormatter, self).__call__(data)
         if s is None:
             return
 
-        time = self.term.dim_blue(format_seconds(self._time(data)))
-        return "%s %s\n" % (time, s)
+        time = format_seconds(self._time(data))
+        action = data["action"].upper()
+        thread = data["thread"]
+
+        # Not using the NullTerminal here is a small optimisation to cut the number of
+        # function calls
+        if self.terminal is not None:
+            test = self._get_test_id(data)
+
+            time = self.terminal.blue(time)
+
+            color = None
+
+            if data["action"] == "test_end":
+                if "expected" not in data and not self.has_unexpected[test]:
+                    color = self.terminal.green
+                else:
+                    color = self.terminal.red
+            elif data["action"] in ("suite_start", "suite_end",
+                                    "test_start", "test_status"):
+                color = self.terminal.yellow
+            elif data["action"] == "crash":
+                color = self.terminal.red
+            elif data["action"] == "assertion_count":
+                if (data["count"] > data["max_expected"] or
+                    data["count"] < data["min_expected"]):
+                    color = self.terminal.red
+
+            if color is not None:
+                action = color(action)
+
+        return "%s %s: %s %s\n" % (time, action, thread, s)
 
     def _get_test_id(self, data):
         test_id = data.get("test")
         if isinstance(test_id, list):
             test_id = tuple(test_id)
         return test_id
 
     def _get_file_name(self, test_id):
@@ -64,41 +111,41 @@ class MachFormatter(base.BaseFormatter):
 
         if isinstance(test_id, tuple):
             return "".join(test_id)
 
         assert False, "unexpected test_id"
 
     def suite_start(self, data):
         num_tests = reduce(lambda x, y: x + len(y), data['tests'].itervalues(), 0)
-        action = self.term.yellow(data['action'].upper())
-        name = ""
-        if 'name' in data:
-            name = " %s -" % (data['name'],)
-        return "%s:%s running %i tests" % (action, name, num_tests)
+        return "%i" % num_tests
 
     def suite_end(self, data):
-        action = self.term.yellow(data['action'].upper())
-        rv = [action]
         if not self.summary_on_shutdown:
-            rv.append(self._format_suite_summary(self.summary.current_suite, self.summary.current))
-        return "\n".join(rv)
+            return self._format_suite_summary(self.summary.current_suite, self.summary.current)
 
     def _format_expected(self, status, expected):
-        color = self.term.red
+        term = self.terminal if self.terminal is not None else NullTerminal()
+        if status == "ERROR":
+            color = term.red
+        else:
+            color = term.yellow
+
         if expected in ("PASS", "OK"):
             return color(status)
 
         return color("%s expected %s" % (status, expected))
 
     def _format_suite_summary(self, suite, summary):
+        term = self.terminal if self.terminal is not None else NullTerminal()
+
         count = summary['counts']
         logs = summary['unexpected_logs']
 
-        rv = ["", self.term.yellow(suite), self.term.yellow("~" * len(suite))]
+        rv = ["", suite, "~" * len(suite)]
 
         # Format check counts
         checks = self.summary.aggregate('count', count)
         rv.append("Ran {} checks ({})".format(sum(checks.values()),
                   ', '.join(['{} {}s'.format(v, k) for k, v in checks.items() if v])))
 
         # Format expected counts
         checks = self.summary.aggregate('expected', count, include_skip=False)
@@ -123,17 +170,17 @@ class MachFormatter(base.BaseFormatter):
                     continue
                 status_str = ", ".join(["{} {}".format(n, s)
                                         for s, n in count[key]['unexpected'].items()])
                 rv.append("  {}: {} ({})".format(
                           key, sum(count[key]['unexpected'].values()), status_str))
 
         # Format status
         if not any(count[key]["unexpected"] for key in ('test', 'subtest', 'assert')):
-            rv.append(self.term.green("OK"))
+            rv.append(term.green("OK"))
         else:
             heading = "Unexpected Logs"
             rv.extend(["", heading, "-" * len(heading)])
             if count['subtest']['count']:
                 for test_id, results in logs.items():
                     test = self._get_file_name(test_id)
                     rv.append(test)
                     for data in results:
@@ -143,23 +190,22 @@ class MachFormatter(base.BaseFormatter):
             else:
                 for test_id, results in logs.items():
                     test = self._get_file_name(test_id)
                     rv.append(test)
                     assert len(results) == 1
                     data = results[0]
                     assert "subtest" not in data
                     rv.append("  %s %s" % (self._format_expected(
-                                           data["status"], data["expected"]), test))
+                                         data["status"], data["expected"]), test))
 
         return "\n".join(rv)
 
     def test_start(self, data):
-        action = self.term.yellow(data['action'].upper())
-        return "%s: %s" % (action, self._get_test_id(data))
+        return "%s" % (self._get_test_id(data),)
 
     def test_end(self, data):
         subtests = self._get_subtest_data(data)
 
         message = data.get("message", "")
         if "stack" in data:
             stack = data["stack"]
             if stack and stack[-1] != "\n":
@@ -193,23 +239,17 @@ class MachFormatter(base.BaseFormatter):
                 rv += "%s" % unexpected[0].get("message", "")
             else:
                 for data in unexpected:
                     name = data.get("subtest", "[Parent]")
                     expected_str = "Expected %s, got %s" % (data["expected"], data["status"])
                     rv += "%s\n" % (
                         "\n".join([name, "-" * len(name), expected_str, data.get("message", "")]))
                 rv = rv[:-1]
-
-        if "expected" not in data and not bool(subtests['unexpected']):
-            color = self.term.green
-        else:
-            color = self.term.red
-        action = color(data['action'].upper())
-        return "%s: %s" % (action, rv)
+        return rv
 
     def valgrind_error(self, data):
         rv = " " + data['primary'] + "\n"
         for line in data['secondary']:
             rv = rv + line + "\n"
 
         return rv
 
@@ -227,52 +267,48 @@ class MachFormatter(base.BaseFormatter):
 
         if data["status"] == "PASS":
             self.status_buffer[test]["pass"] += 1
 
         rv = None
         status, subtest = data["status"], data["subtest"]
         unexpected = "expected" in data
         if self.verbose:
-            status = (self.term.red if unexpected else self.term.green)(status)
+            if self.terminal is not None:
+                status = (self.terminal.red if unexpected else self.terminal.green)(status)
             rv = " ".join([subtest, status, message])
 
         if unexpected:
             self.status_buffer[test]["unexpected"] += 1
-        if rv:
-            action = self.term.yellow(data['action'].upper())
-            return "%s: %s" % (action, rv)
+        return rv
 
     def assertion_count(self, data):
         if data["min_expected"] <= data["count"] <= data["max_expected"]:
             return
 
         if data["min_expected"] != data["max_expected"]:
             expected = "%i to %i" % (data["min_expected"],
                                      data["max_expected"])
         else:
             expected = "%i" % data["min_expected"]
 
-        action = self.term.red("ASSERT")
-        return "%s: Assertion count %i, expected %i assertions\n" % (
-                action, data["count"], expected)
+        return "Assertion count %i, expected %s assertions\n" % (data["count"], expected)
 
     def process_output(self, data):
         rv = []
 
         pid = data['process']
         if pid.isdigit():
             pid = 'pid:%s' % pid
-        pid = self.term.dim_cyan(pid)
 
         if "command" in data and data["process"] not in self._known_pids:
             self._known_pids.add(data["process"])
-            rv.append('%s Full command: %s' % (pid, data["command"]))
+            rv.append('(%s) Full command: %s' % (pid, data["command"]))
 
-        rv.append('%s %s' % (pid, data["data"]))
+        rv.append('(%s) "%s"' % (pid, data["data"]))
         return "\n".join(rv)
 
     def crash(self, data):
         test = self._get_test_id(data)
 
         if data.get("stackwalk_returncode", 0) != 0 and not data.get("stackwalk_stderr"):
             success = True
         else:
@@ -296,73 +332,74 @@ class MachFormatter(base.BaseFormatter):
 
         if data.get("stackwalk_errors"):
             rv.extend(data.get("stackwalk_errors"))
 
         rv = "\n".join(rv)
         if not rv[-1] == "\n":
             rv += "\n"
 
-        action = self.term.red(data['action'].upper())
-        return "%s: %s" % (action, rv)
+        return rv
 
     def process_start(self, data):
         rv = "Started process `%s`" % data['process']
         desc = data.get('command')
         if desc:
             rv = '%s (%s)' % (rv, desc)
         return rv
 
     def process_exit(self, data):
         return "%s: %s" % (data['process'], strstatus(data['exitcode']))
 
     def log(self, data):
         level = data.get("level").upper()
 
-        if level in ("CRITICAL", "ERROR"):
-            level = self.term.red(level)
-        elif level == "WARNING":
-            level = self.term.yellow(level)
-        elif level == "INFO":
-            level = self.term.blue(level)
+        if self.terminal is not None:
+            if level in ("CRITICAL", "ERROR"):
+                level = self.terminal.red(level)
+            elif level == "WARNING":
+                level = self.terminal.yellow(level)
+            elif level == "INFO":
+                level = self.terminal.blue(level)
 
         if data.get('component'):
             rv = " ".join([data["component"], level, data["message"]])
         else:
             rv = "%s %s" % (level, data["message"])
 
         if "stack" in data:
             rv += "\n%s" % data["stack"]
 
         return rv
 
     def lint(self, data):
+        term = self.terminal if self.terminal is not None else NullTerminal()
         fmt = "{path}  {c1}{lineno}{column}  {c2}{level}{normal}  {message}" \
               "  {c1}{rule}({linter}){normal}"
         message = fmt.format(
             path=data["path"],
-            normal=self.term.normal,
-            c1=self.term.grey,
-            c2=self.term.red if data["level"] == 'error' else self.term.yellow,
+            normal=term.normal,
+            c1=term.grey,
+            c2=term.red if data["level"] == 'error' else term.yellow,
             lineno=str(data["lineno"]),
             column=(":" + str(data["column"])) if data.get("column") else "",
             level=data["level"],
             message=data["message"],
             rule='{} '.format(data["rule"]) if data.get("rule") else "",
             linter=data["linter"].lower() if data.get("linter") else "",
         )
 
         return message
 
     def shutdown(self, data):
         if not self.summary_on_shutdown:
             return
 
         heading = "Overall Summary"
-        rv = ["", self.term.bold_yellow(heading), self.term.bold_yellow("=" * len(heading))]
+        rv = ["", heading, "=" * len(heading)]
         for suite, summary in self.summary:
             rv.append(self._format_suite_summary(suite, summary))
         return "\n".join(rv)
 
     def _get_subtest_data(self, data):
         test = self._get_test_id(data)
         return self.status_buffer.get(test, {"count": 0, "unexpected": 0, "pass": 0})