blob: 080e0e5ed1e15b9521ccd604baa7d5a5ce545a00 [file] [log] [blame]
# Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org)
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Contains the entry method for test-webkitpy."""
import logging
import os
import sys
import unittest
import webkitpy
_log = logging.getLogger(__name__)
class Tester(object):
"""Discovers and runs webkitpy unit tests."""
def _find_unittest_files(self, webkitpy_dir):
"""Return a list of paths to all unit-test files."""
unittest_paths = [] # Return value.
for dir_path, dir_names, file_names in os.walk(webkitpy_dir):
for file_name in file_names:
if not file_name.endswith("_unittest.py"):
continue
unittest_path = os.path.join(dir_path, file_name)
unittest_paths.append(unittest_path)
return unittest_paths
def _modules_from_paths(self, package_root, paths):
"""Return a list of fully-qualified module names given paths."""
package_path = os.path.abspath(package_root)
root_package_name = os.path.split(package_path)[1] # Equals "webkitpy".
prefix_length = len(package_path)
modules = []
for path in paths:
path = os.path.abspath(path)
# This gives us, for example: /common/config/ports_unittest.py
rel_path = path[prefix_length:]
# This gives us, for example: /common/config/ports_unittest
rel_path = os.path.splitext(rel_path)[0]
parts = []
while True:
(rel_path, tail) = os.path.split(rel_path)
if not tail:
break
parts.insert(0, tail)
# We now have, for example: common.config.ports_unittest
# FIXME: This is all a hack around the fact that we always prefix webkitpy includes with "webkitpy."
parts.insert(0, root_package_name) # Put "webkitpy" at the beginning.
module = ".".join(parts)
modules.append(module)
return modules
def _win32_blacklist(self, module_path):
# FIXME: Remove this once https://bugs.webkit.org/show_bug.cgi?id=54526 is resolved.
if any([module_path.startswith(package) for package in [
'webkitpy.tool',
'webkitpy.common.checkout',
'webkitpy.common.config',
]]):
return False
return module_path not in [
# FIXME: This file also requires common.checkout to work
'webkitpy.layout_tests.deduplicate_tests_unittest',
]
def run_tests(self, sys_argv, external_package_paths=None):
"""Run the unit tests in all *_unittest.py modules in webkitpy.
This method excludes "webkitpy.common.checkout.scm_unittest" unless
the --all option is the second element of sys_argv.
Args:
sys_argv: A reference to sys.argv.
"""
if external_package_paths is None:
external_package_paths = []
else:
# FIXME: We should consider moving webkitpy off of using "webkitpy." to prefix
# all includes. If we did that, then this would use path instead of dirname(path).
# QueueStatusServer.__init__ has a sys.path import hack due to this code.
sys.path.extend(set(os.path.dirname(path) for path in external_package_paths))
if len(sys_argv) > 1 and not sys_argv[-1].startswith("-"):
# Then explicit modules or test names were provided, which
# the unittest module is equipped to handle.
unittest.main(argv=sys_argv, module=None)
# No need to return since unitttest.main() exits.
# Otherwise, auto-detect all unit tests.
# FIXME: This should be combined with the external_package_paths code above.
webkitpy_dir = os.path.dirname(webkitpy.__file__)
modules = []
for path in [webkitpy_dir] + external_package_paths:
modules.extend(self._modules_from_paths(path, self._find_unittest_files(path)))
modules.sort()
# This is a sanity check to ensure that the unit-test discovery
# methods are working.
if len(modules) < 1:
raise Exception("No unit-test modules found.")
for module in modules:
_log.debug("Found: %s" % module)
# FIXME: This is a hack, but I'm tired of commenting out the test.
# See https://bugs.webkit.org/show_bug.cgi?id=31818
if len(sys_argv) > 1 and sys.argv[1] == "--all":
sys.argv.remove("--all")
else:
excluded_module = "webkitpy.common.checkout.scm_unittest"
_log.info("Excluding: %s (use --all to include)" % excluded_module)
modules.remove(excluded_module)
if sys.platform == 'win32':
modules = filter(self._win32_blacklist, modules)
sys_argv.extend(modules)
# We pass None for the module because we do not want the unittest
# module to resolve module names relative to a given module.
# (This would require importing all of the unittest modules from
# this module.) See the loadTestsFromName() method of the
# unittest.TestLoader class for more details on this parameter.
unittest.main(argv=sys_argv, module=None)