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 360963 cce196d1d7b48958abcb1b23bc3afce6f223f074
parent 360962 02428eab5922de5d7ef07cf7ac4f2035bda417d5
child 360964 64465dd73b9751efed80449c38f82770bd0693b9
push id1369
push userjlorenzo@mozilla.com
push dateMon, 27 Feb 2017 14:59:41 +0000
treeherdermozilla-release@d75a1dba431f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersahal
bugs1280571
milestone52.0a1
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
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,
 }