Bug 1280571 - Add testing/mochitest to the flake8 linter, r=ahal
authorPrabhjyot Singh Sodhi <prabhjyotsingh95@gmail.com>
Wed, 28 Sep 2016 08:28:04 -0400
changeset 342554 cce196d1d7b48958abcb1b23bc3afce6f223f074
parent 342553 02428eab5922de5d7ef07cf7ac4f2035bda417d5
child 342555 64465dd73b9751efed80449c38f82770bd0693b9
push id10298
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:33:03 +0000
treeherdermozilla-aurora@7e29173b1641 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersahal
bugs1280571
milestone52.0a1
Bug 1280571 - Add testing/mochitest to the flake8 linter, r=ahal MozReview-Commit-ID: INBZaZzcPmF
.flake8
testing/mochitest/bisection.py
testing/mochitest/leaks.py
testing/mochitest/mach_commands.py
testing/mochitest/runrobocop.py
testing/mochitest/runtests.py
testing/mochitest/runtestsb2g.py
testing/mochitest/runtestsremote.py
tools/lint/flake8.lint
--- a/.flake8
+++ b/.flake8
@@ -1,3 +1,5 @@
 [flake8]
+# See http://pep8.readthedocs.io/en/latest/intro.html#configuration
+ignore = E121, E123, E126, E133, E226, E241, E242, E704, W503, E402
 max-line-length = 99
 filename = *.py, +.lint
--- a/testing/mochitest/bisection.py
+++ b/testing/mochitest/bisection.py
@@ -10,58 +10,64 @@ class Bisect(object):
         super(Bisect, self).__init__()
         self.summary = []
         self.contents = {}
         self.repeat = 10
         self.failcount = 0
         self.max_failures = 3
 
     def setup(self, tests):
-        "This method is used to initialize various variables that are required for test bisection"
+        """This method is used to initialize various variables that are required
+        for test bisection"""
         status = 0
         self.contents.clear()
         # We need totalTests key in contents for sanity check
         self.contents['totalTests'] = tests
         self.contents['tests'] = tests
         self.contents['loop'] = 0
         return status
 
     def reset(self, expectedError, result):
-        "This method is used to initialize self.expectedError and self.result for each loop in runtests."
+        """This method is used to initialize self.expectedError and self.result
+        for each loop in runtests."""
         self.expectedError = expectedError
         self.result = result
 
     def get_tests_for_bisection(self, options, tests):
-        "Make a list of tests for bisection from a given list of tests"
+        """Make a list of tests for bisection from a given list of tests"""
         bisectlist = []
         for test in tests:
             bisectlist.append(test)
             if test.endswith(options.bisectChunk):
                 break
 
         return bisectlist
 
     def pre_test(self, options, tests, status):
-        "This method is used to call other methods for setting up variables and getting the list of tests for bisection."
+        """This method is used to call other methods for setting up variables and
+        getting the list of tests for bisection."""
         if options.bisectChunk == "default":
             return tests
         # The second condition in 'if' is required to verify that the failing
         # test is the last one.
-        elif 'loop' not in self.contents or not self.contents['tests'][-1].endswith(options.bisectChunk):
+        elif ('loop' not in self.contents or not self.contents['tests'][-1].endswith(
+                options.bisectChunk)):
             tests = self.get_tests_for_bisection(options, tests)
             status = self.setup(tests)
 
         return self.next_chunk_binary(options, status)
 
     def post_test(self, options, expectedError, result):
-        "This method is used to call other methods to summarize results and check whether a sanity check is done or not."
+        """This method is used to call other methods to summarize results and check whether a
+        sanity check is done or not."""
         self.reset(expectedError, result)
         status = self.summarize_chunk(options)
-        # Check whether sanity check has to be done. Also it is necessary to check whether options.bisectChunk is present
-        # in self.expectedError as we do not want to run if it is "default".
+        # Check whether sanity check has to be done. Also it is necessary to check whether
+        # options.bisectChunk is present in self.expectedError as we do not want to run
+        # if it is "default".
         if status == -1 and options.bisectChunk in self.expectedError:
             # In case we have a debug build, we don't want to run a sanity
             # check, will take too much time.
             if mozinfo.info['debug']:
                 return status
 
             testBleedThrough = self.contents['testsToRun'][0]
             tests = self.contents['totalTests']
@@ -208,17 +214,18 @@ class Bisect(object):
                 # This code checks for test-bleedthrough. Should work for any
                 # algorithm.
                 numberOfTests = len(self.contents['testsToRun'])
                 if numberOfTests < 3:
                     # This means that only 2 tests are run. Since the last test
                     # is the failing test itself therefore the bleedthrough
                     # test is the first test
                     self.summary.append(
-                        "TEST-UNEXPECTED-FAIL | %s | Bleedthrough detected, this test is the root cause for many of the above failures" %
+                        "TEST-UNEXPECTED-FAIL | %s | Bleedthrough detected, this test is the "
+                        "root cause for many of the above failures" %
                         self.contents['testsToRun'][0])
                     status = -1
             else:
                 self.summary.append(
                     "\t\t%s failed with different error." % self.contents['testsToRun'][-1])
                 status = -1
 
         return status
@@ -231,17 +238,18 @@ class Bisect(object):
                 self.contents['testsToRun'][0])
             if self.repeat > 0:
                 # loop is set to 1 to again run the single test.
                 self.contents['loop'] = 1
                 self.repeat -= 1
                 return 0
             else:
                 if self.failcount > 0:
-                    # -1 is being returned as the test is intermittent, so no need to bisect further.
+                    # -1 is being returned as the test is intermittent, so no need to bisect
+                    # further.
                     return -1
                 # If the test does not fail even once, then proceed to next chunk for bisection.
                 # loop is set to 2 to proceed on bisection.
                 self.contents['loop'] = 2
                 return 1
         elif self.result[options.bisectChunk] == "FAIL":
             self.summary.append(
                 "\t\tThe test %s failed." %
@@ -249,22 +257,24 @@ class Bisect(object):
             self.failcount += 1
             self.contents['loop'] = 1
             self.repeat -= 1
             # self.max_failures is the maximum number of times a test is allowed
             # to fail to be called an intermittent. If a test fails more than
             # limit set, it is a perma-fail.
             if self.failcount < self.max_failures:
                 if self.repeat == 0:
-                    # -1 is being returned as the test is intermittent, so no need to bisect further.
+                    # -1 is being returned as the test is intermittent, so no need to bisect
+                    # further.
                     return -1
                 return 0
             else:
                 self.summary.append(
-                    "TEST-UNEXPECTED-FAIL | %s | Bleedthrough detected, this test is the root cause for many of the above failures" %
+                    "TEST-UNEXPECTED-FAIL | %s | Bleedthrough detected, this test is the "
+                    "root cause for many of the above failures" %
                     self.contents['testsToRun'][0])
                 return -1
 
     def print_summary(self):
         "This method is used to print the recorded summary."
         print "Bisection summary:"
         for line in self.summary:
             print line
--- a/testing/mochitest/leaks.py
+++ b/testing/mochitest/leaks.py
@@ -49,27 +49,31 @@ class ShutdownLeaks(object):
     def process(self):
         if not self.seenShutdown:
             self.logger.warning(
                 "TEST-UNEXPECTED-FAIL | ShutdownLeaks | process() called before end of test suite")
 
         for test in self._parseLeakingTests():
             for url, count in self._zipLeakedWindows(test["leakedWindows"]):
                 self.logger.warning(
-                    "TEST-UNEXPECTED-FAIL | %s | leaked %d window(s) until shutdown [url = %s]" % (test["fileName"], count, url))
+                    "TEST-UNEXPECTED-FAIL | %s | leaked %d window(s) until shutdown "
+                    "[url = %s]" % (test["fileName"], count, url))
 
             if test["leakedWindowsString"]:
                 self.logger.info("TEST-INFO | %s | windows(s) leaked: %s" %
                                  (test["fileName"], test["leakedWindowsString"]))
 
             if test["leakedDocShells"]:
-                self.logger.warning("TEST-UNEXPECTED-FAIL | %s | leaked %d docShell(s) until shutdown" % (
-                    test["fileName"], len(test["leakedDocShells"])))
-                self.logger.info("TEST-INFO | %s | docShell(s) leaked: %s" % (test["fileName"],
-                                                                              ', '.join(["[pid = %s] [id = %s]" % x for x in test["leakedDocShells"]])))
+                self.logger.warning("TEST-UNEXPECTED-FAIL | %s | leaked %d docShell(s) until "
+                                    "shutdown" %
+                                    (test["fileName"], len(test["leakedDocShells"])))
+                self.logger.info("TEST-INFO | %s | docShell(s) leaked: %s" %
+                                 (test["fileName"], ', '.join(["[pid = %s] [id = %s]" %
+                                                               x for x in test["leakedDocShells"]]
+                                                              )))
 
     def _logWindow(self, line):
         created = line[:2] == "++"
         pid = self._parseValue(line, "pid")
         serial = self._parseValue(line, "serial")
 
         # log line has invalid format
         if not pid or not serial:
@@ -224,22 +228,24 @@ class LSANLeaks(object):
             # so don't bother checking if they do.
             self._recordFrame(sysLibStackFrame.group(1))
 
         # If we don't match either of these, just ignore the frame.
         # We'll end up with "unknown stack" if everything is ignored.
 
     def process(self):
         if self.fatalError:
-            self.logger.warning(
-                "TEST-UNEXPECTED-FAIL | LeakSanitizer | LeakSanitizer has encountered a fatal error.")
+            self.logger.warning("TEST-UNEXPECTED-FAIL | LeakSanitizer | LeakSanitizer "
+                                "has encountered a fatal error.")
 
         if self.foundFrames:
-            self.logger.info("TEST-INFO | LeakSanitizer | To show the addresses of leaked objects add report_objects=1 to LSAN_OPTIONS")
-            self.logger.info("TEST-INFO | LeakSanitizer | This can be done in testing/mozbase/mozrunner/mozrunner/utils.py")
+            self.logger.info("TEST-INFO | LeakSanitizer | To show the "
+                             "addresses of leaked objects add report_objects=1 to LSAN_OPTIONS")
+            self.logger.info("TEST-INFO | LeakSanitizer | This can be done "
+                             "in testing/mozbase/mozrunner/mozrunner/utils.py")
 
         for f in self.foundFrames:
             self.logger.warning(
                 "TEST-UNEXPECTED-FAIL | LeakSanitizer | leak at " + f)
 
     def _finishStack(self):
         if self.recordMoreFrames and len(self.currStack) == 0:
             self.currStack = ["unknown stack"]
--- a/testing/mochitest/mach_commands.py
+++ b/testing/mochitest/mach_commands.py
@@ -4,17 +4,16 @@
 
 from __future__ import absolute_import, unicode_literals
 
 from argparse import Namespace
 from collections import defaultdict
 from itertools import chain
 import logging
 import os
-import shutil
 import sys
 import warnings
 
 from mozbuild.base import (
     MachCommandBase,
     MachCommandConditions as conditions,
     MozbuildObject,
 )
@@ -345,17 +344,18 @@ def is_buildapp_in(*apps):
         ' or '.join(apps))
     return is_buildapp_supported
 
 
 def verify_host_bin():
     # validate MOZ_HOST_BIN environment variables for Android tests
     MOZ_HOST_BIN = os.environ.get('MOZ_HOST_BIN')
     if not MOZ_HOST_BIN:
-        print('environment variable MOZ_HOST_BIN must be set to a directory containing host xpcshell')
+        print('environment variable MOZ_HOST_BIN must be set to a directory containing host '
+              'xpcshell')
         return 1
     elif not os.path.isdir(MOZ_HOST_BIN):
         print('$MOZ_HOST_BIN does not specify a directory')
         return 1
     elif not os.path.isfile(os.path.join(MOZ_HOST_BIN, 'xpcshell')):
         print('$MOZ_HOST_BIN/xpcshell does not exist')
         return 1
     return 0
--- a/testing/mochitest/runrobocop.py
+++ b/testing/mochitest/runrobocop.py
@@ -371,19 +371,19 @@ class RobocopTestRunner(MochitestDesktop
             "rawhost=http://%s:%s/tests\n" %
             (self.options.remoteWebServer, self.options.httpPort))
         if browserEnv:
             envstr = ""
             delim = ""
             for key, value in browserEnv.items():
                 try:
                     value.index(',')
-                    self.log.error(
-                        "setupRobotiumConfig: browserEnv - Found a ',' in our value, unable to process value. key=%s,value=%s" %
-                        (key, value))
+                    self.log.error("setupRobotiumConfig: browserEnv - Found a ',' "
+                                   "in our value, unable to process value. key=%s,value=%s" %
+                                   (key, value))
                     self.log.error("browserEnv=%s" % browserEnv)
                 except ValueError:
                     envstr += "%s%s=%s" % (delim, key, value)
                     delim = ","
             fHandle.write("envvars=%s\n" % envstr)
         fHandle.close()
         self.dm.removeFile(self.remoteConfigFile)
         self.dm.pushFile(fHandle.name, self.remoteConfigFile)
@@ -440,19 +440,19 @@ class RobocopTestRunner(MochitestDesktop
                 "-e", "deviceroot", self.deviceRoot,
                 "-e", "class",
                 "org.mozilla.gecko.tests.%s" % test['name'].split('/')[-1].split('.java')[0],
                 "org.mozilla.roboexample.test/org.mozilla.gecko.FennecInstrumentationTestRunner"]
         else:
             # This does not launch a test at all. It launches an activity
             # that starts Fennec and then waits indefinitely, since cat
             # never returns.
-            browserArgs = ["start",
-                           "-n", "org.mozilla.roboexample.test/org.mozilla.gecko.LaunchFennecWithConfigurationActivity",
-                           "&&", "cat"]
+            browserArgs = ["start", "-n",
+                           "org.mozilla.roboexample.test/org.mozilla."
+                           "gecko.LaunchFennecWithConfigurationActivity", "&&", "cat"]
             self.dm.default_timeout = sys.maxint  # Forever.
             self.log.info("")
             self.log.info("Serving mochi.test Robocop root at http://%s:%s/tests/robocop/" %
                           (self.options.remoteWebServer, self.options.httpPort))
             self.log.info("")
         result = -1
         log_result = -1
         try:
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -152,17 +152,18 @@ class MessageLogger(object):
 
         # Message buffering
         self.buffered_messages = []
 
         # Failures reporting, after the end of the tests execution
         self.errors = []
 
     def valid_message(self, obj):
-        """True if the given object is a valid structured message (only does a superficial validation)"""
+        """True if the given object is a valid structured message
+        (only does a superficial validation)"""
         return isinstance(obj, dict) and 'action' in obj and obj[
             'action'] in MessageLogger.VALID_ACTIONS
 
     def _fix_test_name(self, message):
         """Normalize a logged test path to match the relative path from the sourcedir.
         """
         if 'test' in message:
             test = message['test']
@@ -174,17 +175,18 @@ class MessageLogger(object):
     def _fix_message_format(self, message):
         if 'message' in message:
             if isinstance(message['message'], bytes):
                 message['message'] = message['message'].decode('utf-8', 'replace')
             elif not isinstance(message['message'], unicode):
                 message['message'] = unicode(message['message'])
 
     def parse_line(self, line):
-        """Takes a given line of input (structured or not) and returns a list of structured messages"""
+        """Takes a given line of input (structured or not) and
+        returns a list of structured messages"""
         line = line.rstrip().decode("UTF-8", "replace")
 
         messages = []
         for fragment in line.split(MessageLogger.DELIMITER):
             if not fragment:
                 continue
             try:
                 message = json.loads(fragment)
@@ -408,17 +410,19 @@ class MochitestServer(object):
             self._xrePath,
             "-v",
             "170",
             "-f",
             os.path.join(
                 self._httpdPath,
                 "httpd.js"),
             "-e",
-            """const _PROFILE_PATH = '%(profile)s'; const _SERVER_PORT = '%(port)s'; const _SERVER_ADDR = '%(server)s'; const _TEST_PREFIX = %(testPrefix)s; const _DISPLAY_RESULTS = %(displayResults)s;""" % {
+            "const _PROFILE_PATH = '%(profile)s'; const _SERVER_PORT = '%(port)s'; "
+            "const _SERVER_ADDR = '%(server)s'; const _TEST_PREFIX = %(testPrefix)s; "
+            "const _DISPLAY_RESULTS = %(displayResults)s;" % {
                 "profile": self._profileDir.replace(
                     '\\',
                     '\\\\'),
                 "port": self.httpPort,
                 "server": self.webServer,
                 "testPrefix": self.testPrefix,
                 "displayResults": str(
                     self._keep_open).lower()},
@@ -550,17 +554,16 @@ class MochitestBase(object):
                                                  logger_options,
                                                  {
                                                      "tbpl": sys.stdout
                                                  })
             MochitestBase.log = self.log
 
         self.message_logger = MessageLogger(logger=self.log)
 
-
     def update_mozinfo(self):
         """walk up directories to find mozinfo.json update the info"""
         # TODO: This should go in a more generic place, e.g. mozinfo
 
         path = SCRIPT_DIR
         dirs = set()
         while path != os.path.expanduser('~'):
             if path in dirs:
@@ -810,17 +813,17 @@ class MochitestBase(object):
                                 "websocketprocessbridge.py")]
         self.websocketProcessBridge = mozprocess.ProcessHandler(command,
                                                                 cwd=SCRIPT_DIR)
         self.websocketProcessBridge.run()
         self.log.info("runtests.py | websocket/process bridge pid: %d"
                       % self.websocketProcessBridge.pid)
 
         # ensure the server is up, wait for at most ten seconds
-        for i in range(1,100):
+        for i in range(1, 100):
             if self.websocketProcessBridge.proc.poll() is not None:
                 self.log.error("runtests.py | websocket/process bridge failed "
                                "to launch. Are all the dependencies installed?")
                 return
 
             try:
                 sock = socket.create_connection(("127.0.0.1", 8191))
                 sock.close()
@@ -946,17 +949,18 @@ class MochitestBase(object):
         "Adds MochiKit chrome tests to the profile."
 
         # Create (empty) chrome directory.
         chromedir = os.path.join(options.profilePath, "chrome")
         os.mkdir(chromedir)
 
         # Write userChrome.css.
         chrome = """
-@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* set default namespace to XUL */
+/* set default namespace to XUL */
+@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 toolbar,
 toolbarpalette {
   background-color: rgb(235, 235, 235) !important;
 }
 toolbar#nav-bar {
   background-image: none !important;
 }
 """
@@ -1130,17 +1134,18 @@ toolbar#nav-bar {
 
     def getTestManifest(self, options):
         if isinstance(options.manifestFile, TestManifest):
             manifest = options.manifestFile
         elif options.manifestFile and os.path.isfile(options.manifestFile):
             manifestFileAbs = os.path.abspath(options.manifestFile)
             assert manifestFileAbs.startswith(SCRIPT_DIR)
             manifest = TestManifest([options.manifestFile], strict=False)
-        elif options.manifestFile and os.path.isfile(os.path.join(SCRIPT_DIR, options.manifestFile)):
+        elif (options.manifestFile and
+                os.path.isfile(os.path.join(SCRIPT_DIR, options.manifestFile))):
             manifestFileAbs = os.path.abspath(
                 os.path.join(
                     SCRIPT_DIR,
                     options.manifestFile))
             assert manifestFileAbs.startswith(SCRIPT_DIR)
             manifest = TestManifest([manifestFileAbs], strict=False)
         else:
             masterName = self.normflavor(options.flavor) + '.ini'
@@ -1273,18 +1278,17 @@ toolbar#nav-bar {
 
         if os.path.isfile(self.start_script):
             with open(self.start_script, 'r') as fh:
                 script = fh.read()
         else:
             script = self.start_script
 
         with self.marionette.using_context('chrome'):
-            return self.marionette.execute_script(script,
-                script_args=self.start_script_args)
+            return self.marionette.execute_script(script, script_args=self.start_script_args)
 
 
 class SSLTunnel:
 
     def __init__(self, options, logger, ignoreSSLTunnelExts=False):
         self.log = logger
         self.process = None
         self.utilityPath = options.utilityPath
@@ -1685,24 +1689,24 @@ class MochitestDesktop(MochitestBase):
 
         prefs = json.loads(json.dumps(prefs) % interpolation)
         for pref in prefs:
             prefs[pref] = Preferences.cast(prefs[pref])
         # TODO: make this less hacky
         # https://bugzilla.mozilla.org/show_bug.cgi?id=913152
 
         # proxy
+        # use SSL port for legacy compatibility; see
+        # - https://bugzilla.mozilla.org/show_bug.cgi?id=688667#c66
+        # - https://bugzilla.mozilla.org/show_bug.cgi?id=899221
+        # - https://github.com/mozilla/mozbase/commit/43f9510e3d58bfed32790c82a57edac5f928474d
+        #             'ws': str(self.webSocketPort)
         proxy = {'remote': options.webServer,
                  'http': options.httpPort,
                  'https': options.sslPort,
-                 # use SSL port for legacy compatibility; see
-                 # - https://bugzilla.mozilla.org/show_bug.cgi?id=688667#c66
-                 # - https://bugzilla.mozilla.org/show_bug.cgi?id=899221
-                 # - https://github.com/mozilla/mozbase/commit/43f9510e3d58bfed32790c82a57edac5f928474d
-                 #             'ws': str(self.webSocketPort)
                  'ws': options.sslPort
                  }
 
         # See if we should use fake media devices.
         if options.useTestMediaDevices:
             prefs['media.audio_loopback_dev'] = self.mediaDevices['audio']
             prefs['media.video_loopback_dev'] = self.mediaDevices['video']
 
@@ -1851,19 +1855,18 @@ class MochitestDesktop(MochitestBase):
         # kill zombies
         foundZombie = False
         for processPID in processList:
             self.log.info(
                 "zombiecheck | Checking for orphan process with PID: %d" %
                 processPID)
             if isPidAlive(processPID):
                 foundZombie = True
-                self.log.info(
-                    "TEST-UNEXPECTED-FAIL | zombiecheck | child process %d still alive after shutdown" %
-                    processPID)
+                self.log.info("TEST-UNEXPECTED-FAIL | zombiecheck | child process "
+                              "%d still alive after shutdown" % processPID)
                 self.killAndGetStack(
                     processPID,
                     utilityPath,
                     debuggerInfo,
                     dump_screen=not debuggerInfo)
 
         return foundZombie
 
@@ -1882,17 +1885,18 @@ class MochitestDesktop(MochitestBase):
                timeout=-1,
                detectShutdownLeaks=False,
                screenshotOnFail=False,
                bisectChunk=None,
                quiet=False,
                marionette_args=None):
         """
         Run the app, log the duration it took to execute, return the status code.
-        Kills the app if it runs for longer than |maxTime| seconds, or outputs nothing for |timeout| seconds.
+        Kills the app if it runs for longer than |maxTime| seconds, or outputs nothing
+        for |timeout| seconds.
         """
 
         # configure the message logger buffering
         self.message_logger.buffering = quiet
 
         # It can't be the case that both a with-debugger and an
         # on-Valgrind run have been requested.  doTests() should have
         # already excluded this possibility.
@@ -1908,17 +1912,18 @@ class MochitestDesktop(MochitestBase):
         # Set up Valgrind arguments.
         if valgrindPath:
             interactive = False
             valgrindArgs_split = ([] if valgrindArgs is None
                                   else valgrindArgs.split(","))
 
             valgrindSuppFiles_final = []
             if valgrindSuppFiles is not None:
-                valgrindSuppFiles_final = ["--suppressions=" + path for path in valgrindSuppFiles.split(",")]
+                valgrindSuppFiles_final = ["--suppressions=" +
+                                           path for path in valgrindSuppFiles.split(",")]
 
             debug_args = ([valgrindPath]
                           + mozdebug.get_default_valgrind_args()
                           + valgrindArgs_split
                           + valgrindSuppFiles_final)
 
         # fix default timeout
         if timeout == -1:
@@ -2157,18 +2162,19 @@ class MochitestDesktop(MochitestBase):
         status = 0
         bisection_log = 0
         while not finished:
             if options.bisectChunk:
                 testsToRun = bisect.pre_test(options, testsToRun, status)
                 # To inform that we are in the process of bisection, and to
                 # look for bleedthrough
                 if options.bisectChunk != "default" and not bisection_log:
-                    self.log.info(
-                        "TEST-UNEXPECTED-FAIL | Bisection | Please ignore repeats and look for 'Bleedthrough' (if any) at the end of the failure list")
+                    self.log.info("TEST-UNEXPECTED-FAIL | Bisection | Please ignore repeats "
+                                  "and look for 'Bleedthrough' (if any) at the end of "
+                                  "the failure list")
                     bisection_log = 1
 
             result = self.doTests(options, testsToRun)
             if options.bisectChunk:
                 status = bisect.post_test(
                     options,
                     self.expectedError,
                     self.result)
@@ -2219,18 +2225,18 @@ class MochitestDesktop(MochitestBase):
         dirs = self.getDirectories(options)
 
         result = 1  # default value, if no tests are run.
         for d in dirs:
             print "dir: %s" % d
             tests_in_dir = [t for t in testsToRun if os.path.dirname(t) == d]
 
             # If we are using --run-by-dir, we should not use the profile path (if) provided
-            # by the user, since we need to create a new directory for each run. We would face problems
-            # if we use the directory provided by the user.
+            # by the user, since we need to create a new directory for each run. We would face
+            # problems if we use the directory provided by the user.
             result = self.runMochitests(options, tests_in_dir)
 
             # Dump the logging buffer
             self.message_logger.dump_buffered()
 
             if result == -1:
                 break
 
@@ -2327,17 +2333,18 @@ class MochitestDesktop(MochitestBase):
             if mozinfo.info.get('buildapp') == 'mulet':
                 del self.browserEnv['MOZ_DISABLE_NONLOCAL_CONNECTIONS']
                 os.environ["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "0"
 
         if self.browserEnv is None:
             return 1
 
         if self.mozLogs:
-            self.browserEnv["MOZ_LOG_FILE"] = "{}/moz-pid=%PID-uid={}.log".format(self.browserEnv["MOZ_UPLOAD_DIR"], str(uuid.uuid4()))
+            self.browserEnv["MOZ_LOG_FILE"] = "{}/moz-pid=%PID-uid={}.log".format(
+                self.browserEnv["MOZ_UPLOAD_DIR"], str(uuid.uuid4()))
 
         try:
             self.startServers(options, debuggerInfo)
 
             # testsToFilter parameter is used to filter out the test list that
             # is sent to buildTestPath
             testURL = self.buildTestPath(options, testsToFilter)
 
@@ -2456,22 +2463,22 @@ class MochitestDesktop(MochitestBase):
 
         return status
 
     def handleTimeout(self, timeout, proc, utilityPath, debuggerInfo,
                       browser_pid, processLog):
         """handle process output timeout"""
         # TODO: bug 913975 : _processOutput should call self.processOutputLine
         # one more time one timeout (I think)
-        error_message = "TEST-UNEXPECTED-TIMEOUT | %s | application timed out after %d seconds with no output" % (
-            self.lastTestSeen, int(timeout))
+        error_message = ("TEST-UNEXPECTED-TIMEOUT | %s | application timed out after "
+                         "%d seconds with no output") % (self.lastTestSeen, int(timeout))
         self.message_logger.dump_buffered()
         self.message_logger.buffering = False
         self.log.info(error_message)
-        self.log.error("Force-terminating active process(es).");
+        self.log.error("Force-terminating active process(es).")
 
         browser_pid = browser_pid or proc.pid
         child_pids = self.extract_child_pids(processLog, browser_pid)
         self.log.info('Found child pids: %s' % child_pids)
 
         if HAVE_PSUTIL:
             child_procs = [psutil.Process(pid) for pid in child_pids]
             for pid in child_pids:
@@ -2518,20 +2525,20 @@ class MochitestDesktop(MochitestBase):
             self.utilityPath = utilityPath
             self.symbolsPath = symbolsPath
             self.dump_screen_on_timeout = dump_screen_on_timeout
             self.dump_screen_on_fail = dump_screen_on_fail
             self.shutdownLeaks = shutdownLeaks
             self.lsanLeaks = lsanLeaks
             self.bisectChunk = bisectChunk
 
-            # With metro browser runs this script launches the metro test harness which launches the browser.
-            # The metro test harness hands back the real browser process id via log output which we need to
-            # pick up on and parse out. This variable tracks the real browser
-            # process id if we find it.
+            # With metro browser runs this script launches the metro test harness which launches
+            # the browser. The metro test harness hands back the real browser process id via log
+            # output which we need to pick up on and parse out. This variable tracks the real
+            # browser process id if we find it.
             self.browserProcessId = None
 
             self.stackFixerFunction = self.stackFixer()
 
         def processOutputLine(self, line):
             """per line handler of output for mozprocess"""
             # Parsing the line (by the structured messages logger).
             messages = self.harness.message_logger.parse_line(line)
--- a/testing/mochitest/runtestsb2g.py
+++ b/testing/mochitest/runtestsb2g.py
@@ -214,17 +214,18 @@ class MochitestB2G(MochitestBase):
             # emulators.
             self.marionette.execute_script("""
                 Components.utils.import("resource://gre/modules/Services.jsm");
                 Services.io.manageOfflineStatus = false;
                 Services.io.offline = false;
                 """)
 
             self.marionette.execute_script("""
-                let SECURITY_PREF = "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer";
+                let SECURITY_PREF = "security.turn_off_all_security_" +
+                                    "so_that_viruses_can_take_over_this_computer";
                 Services.prefs.setBoolPref(SECURITY_PREF, true);
 
                 if (!testUtils.hasOwnProperty("specialPowersObserver")) {
                   let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
                     .getService(Components.interfaces.mozIJSSubScriptLoader);
                   loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.jsm",
                     testUtils);
                   testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver();
@@ -307,17 +308,18 @@ class MochitestB2G(MochitestBase):
             self.app_ctx.dm.getFile(self.remote_log, self.local_log)
             self.app_ctx.dm.removeFile(self.remote_log)
 
         if options.pidFile != "":
             try:
                 os.remove(options.pidFile)
                 os.remove(options.pidFile + ".xpcshell.pid")
             except:
-                print "Warning: cleaning up pidfile '%s' was unsuccessful from the test harness" % options.pidFile
+                print("Warning: cleaning up pidfile '%s' was unsuccessful "
+                      "from the test harness") % options.pidFile
 
         # stop and clean up the runner
         if getattr(self, 'runner', False):
             if self.local_log:
                 self.app_ctx.dm.getFile(self.remote_log, self.local_log)
                 self.app_ctx.dm.removeFile(self.remote_log)
 
             self.runner.cleanup()
--- a/testing/mochitest/runtestsremote.py
+++ b/testing/mochitest/runtestsremote.py
@@ -189,17 +189,18 @@ class MochiRemote(MochitestDesktop):
 
     def addChromeToProfile(self, options):
         manifest = MochitestDesktop.addChromeToProfile(self, options)
 
         # Support Firefox (browser), B2G (shell), SeaMonkey (navigator), and Webapp
         # Runtime (webapp).
         if options.flavor == 'chrome':
             # append overlay to chrome.manifest
-            chrome = "overlay chrome://browser/content/browser.xul chrome://mochikit/content/browser-test-overlay.xul"
+            chrome = ("overlay chrome://browser/content/browser.xul "
+                      "chrome://mochikit/content/browser-test-overlay.xul")
             path = os.path.join(options.profilePath, 'extensions', 'staged',
                                 'mochikit@mozilla.org', 'chrome.manifest')
             with open(path, "a") as f:
                 f.write(chrome)
         return manifest
 
     def buildURLOptions(self, options, env):
         self.localLog = options.logFile
--- a/tools/lint/flake8.lint
+++ b/tools/lint/flake8.lint
@@ -130,17 +130,18 @@ LINTER = {
     'name': "flake8",
     'description': "Python linter",
     'include': [
         'python/mozlint',
         'taskcluster',
         'testing/firefox-ui',
         'testing/marionette/client',
         'testing/marionette/harness',
+        'testing/mochitest',
         'testing/puppeteer',
         'testing/talos/',
         'tools/lint',
     ],
-    'exclude': [],
+    'exclude': ['testing/mochitest/pywebsocket'],
     'extensions': EXTENSIONS,
     'type': 'external',
     'payload': lint,
 }