示例#1
0
class Tester(object):
    def __init__(self, filesystem=None):
        self.finder = TestFinder(filesystem or FileSystem())
        self.stream = sys.stderr

    def add_tree(self, top_directory, starting_subdirectory=None):
        self.finder.add_tree(top_directory, starting_subdirectory)

    def _parse_args(self):
        parser = optparse.OptionParser(
            usage='usage: %prog [options] [args...]')
        parser.add_option('-a',
                          '--all',
                          action='store_true',
                          default=False,
                          help='run all the tests'),
        parser.add_option(
            '-c',
            '--coverage',
            action='store_true',
            default=False,
            help=
            'generate code coverage info (requires http://pypi.python.org/pypi/coverage)'
        ),
        parser.add_option(
            '-q',
            '--quiet',
            action='store_true',
            default=False,
            help='run quietly (errors, warnings, and progress only)'),
        parser.add_option(
            '-t',
            '--timing',
            action='store_true',
            default=False,
            help='display per-test execution time (implies --verbose)'),
        parser.add_option(
            '-v',
            '--verbose',
            action='count',
            default=0,
            help=
            'verbose output (specify once for individual test results, twice for debug messages)'
        )
        parser.add_option('--skip-integrationtests',
                          action='store_true',
                          default=False,
                          help='do not run the integration tests')

        parser.epilog = (
            '[args...] is an optional list of modules, test_classes, or individual tests. '
            'If no args are given, all the tests will be run.')

        return parser.parse_args()

    def _configure(self, options):
        self._options = options

        if options.timing:
            # --timing implies --verbose
            options.verbose = max(options.verbose, 1)

        log_level = logging.INFO
        if options.quiet:
            log_level = logging.WARNING
        elif options.verbose == 2:
            log_level = logging.DEBUG
        self._configure_logging(log_level)

    def _configure_logging(self, log_level):
        """Configure the root logger.

        Configure the root logger not to log any messages from webkitpy --
        except for messages from the autoinstall module.  Also set the
        logging level as described below.
        """
        handler = logging.StreamHandler(self.stream)
        # We constrain the level on the handler rather than on the root
        # logger itself.  This is probably better because the handler is
        # configured and known only to this module, whereas the root logger
        # is an object shared (and potentially modified) by many modules.
        # Modifying the handler, then, is less intrusive and less likely to
        # interfere with modifications made by other modules (e.g. in unit
        # tests).
        handler.name = __name__
        handler.setLevel(log_level)
        formatter = logging.Formatter("%(message)s")
        handler.setFormatter(formatter)

        logger = logging.getLogger()
        logger.addHandler(handler)
        logger.setLevel(logging.NOTSET)

        # Filter out most webkitpy messages.
        #
        # Messages can be selectively re-enabled for this script by updating
        # this method accordingly.
        def filter(record):
            """Filter out autoinstall and non-third-party webkitpy messages."""
            # FIXME: Figure out a way not to use strings here, for example by
            #        using syntax like webkitpy.test.__name__.  We want to be
            #        sure not to import any non-Python 2.4 code, though, until
            #        after the version-checking code has executed.
            if (record.name.startswith("webkitpy.common.system.autoinstall")
                    or record.name.startswith("webkitpy.test")):
                return True
            if record.name.startswith("webkitpy"):
                return False
            return True

        testing_filter = logging.Filter()
        testing_filter.filter = filter

        # Display a message so developers are not mystified as to why
        # logging does not work in the unit tests.
        _log.info(
            "Suppressing most webkitpy logging while running unit tests.")
        handler.addFilter(testing_filter)

    def run(self):
        options, args = self._parse_args()
        self._configure(options)

        self.finder.clean_trees()

        names = self.finder.find_names(args,
                                       self._options.skip_integrationtests,
                                       self._options.all)
        return self._run_tests(names)

    def _run_tests(self, names):
        if self._options.coverage:
            try:
                import webkitpy.thirdparty.autoinstalled.coverage as coverage
            except ImportError, e:
                _log.error(
                    "Failed to import 'coverage'; can't generate coverage numbers."
                )
                return False
            cov = coverage.coverage()
            cov.start()

        # Make sure PYTHONPATH is set up properly.
        sys.path = self.finder.additional_paths(sys.path) + sys.path

        _log.debug("Loading the tests...")

        loader = unittest.defaultTestLoader
        suites = []
        for name in names:
            if self.finder.is_module(name):
                # if we failed to load a name and it looks like a module,
                # try importing it directly, because loadTestsFromName()
                # produces lousy error messages for bad modules.
                try:
                    __import__(name)
                except ImportError, e:
                    _log.fatal('Failed to import %s:' % name)
                    self._log_exception()
                    return False

            suites.append(loader.loadTestsFromName(name, None))
示例#2
0
文件: main.py 项目: dzhshf/WebKit
class Tester(object):
    def __init__(self, filesystem=None):
        self.finder = TestFinder(filesystem or FileSystem())
        self.stream = sys.stderr

    def add_tree(self, top_directory, starting_subdirectory=None):
        self.finder.add_tree(top_directory, starting_subdirectory)

    def _parse_args(self):
        parser = optparse.OptionParser(usage='usage: %prog [options] [args...]')
        parser.add_option('-a', '--all', action='store_true', default=False,
                          help='run all the tests'),
        parser.add_option('-c', '--coverage', action='store_true', default=False,
                          help='generate code coverage info (requires http://pypi.python.org/pypi/coverage)'),
        parser.add_option('-q', '--quiet', action='store_true', default=False,
                          help='run quietly (errors, warnings, and progress only)'),
        parser.add_option('-t', '--timing', action='store_true', default=False,
                          help='display per-test execution time (implies --verbose)'),
        parser.add_option('-v', '--verbose', action='count', default=0,
                          help='verbose output (specify once for individual test results, twice for debug messages)')
        parser.add_option('--skip-integrationtests', action='store_true', default=False,
                          help='do not run the integration tests')

        parser.epilog = ('[args...] is an optional list of modules, test_classes, or individual tests. '
                         'If no args are given, all the tests will be run.')

        return parser.parse_args()

    def _configure(self, options):
        self._options = options

        if options.timing:
            # --timing implies --verbose
            options.verbose = max(options.verbose, 1)

        log_level = logging.INFO
        if options.quiet:
            log_level = logging.WARNING
        elif options.verbose == 2:
            log_level = logging.DEBUG
        self._configure_logging(log_level)

    def _configure_logging(self, log_level):
        """Configure the root logger.

        Configure the root logger not to log any messages from webkitpy --
        except for messages from the autoinstall module.  Also set the
        logging level as described below.
        """
        handler = logging.StreamHandler(self.stream)
        # We constrain the level on the handler rather than on the root
        # logger itself.  This is probably better because the handler is
        # configured and known only to this module, whereas the root logger
        # is an object shared (and potentially modified) by many modules.
        # Modifying the handler, then, is less intrusive and less likely to
        # interfere with modifications made by other modules (e.g. in unit
        # tests).
        handler.name = __name__
        handler.setLevel(log_level)
        formatter = logging.Formatter("%(message)s")
        handler.setFormatter(formatter)

        logger = logging.getLogger()
        logger.addHandler(handler)
        logger.setLevel(logging.NOTSET)

        # Filter out most webkitpy messages.
        #
        # Messages can be selectively re-enabled for this script by updating
        # this method accordingly.
        def filter(record):
            """Filter out autoinstall and non-third-party webkitpy messages."""
            # FIXME: Figure out a way not to use strings here, for example by
            #        using syntax like webkitpy.test.__name__.  We want to be
            #        sure not to import any non-Python 2.4 code, though, until
            #        after the version-checking code has executed.
            if (record.name.startswith("webkitpy.common.system.autoinstall") or
                record.name.startswith("webkitpy.test")):
                return True
            if record.name.startswith("webkitpy"):
                return False
            return True

        testing_filter = logging.Filter()
        testing_filter.filter = filter

        # Display a message so developers are not mystified as to why
        # logging does not work in the unit tests.
        _log.info("Suppressing most webkitpy logging while running unit tests.")
        handler.addFilter(testing_filter)

    def run(self):
        options, args = self._parse_args()
        self._configure(options)

        self.finder.clean_trees()

        names = self.finder.find_names(args, self._options.skip_integrationtests, self._options.all)
        if not names:
            _log.error('No tests to run')
            return False

        return self._run_tests(names)

    def _run_tests(self, names):
        if self._options.coverage:
            try:
                import webkitpy.thirdparty.autoinstalled.coverage as coverage
            except ImportError, e:
                _log.error("Failed to import 'coverage'; can't generate coverage numbers.")
                return False
            cov = coverage.coverage()
            cov.start()

        # Make sure PYTHONPATH is set up properly.
        sys.path = self.finder.additional_paths(sys.path) + sys.path

        _log.debug("Loading the tests...")

        loader = unittest.defaultTestLoader
        suites = []
        for name in names:
            if self.finder.is_module(name):
                # if we failed to load a name and it looks like a module,
                # try importing it directly, because loadTestsFromName()
                # produces lousy error messages for bad modules.
                try:
                    __import__(name)
                except ImportError, e:
                    _log.fatal('Failed to import %s:' % name)
                    self._log_exception()
                    return False

            suites.append(loader.loadTestsFromName(name, None))
示例#3
0
class TestFinderTest(unittest.TestCase):
    def setUp(self):
        files = {
            '/foo/bar/baz.py': '',
            '/foo/bar/baz_unittest.py': '',
            '/foo2/bar2/baz2.py': '',
            '/foo2/bar2/baz2.pyc': '',
            '/foo2/bar2/baz2_integrationtest.py': '',
            '/foo2/bar2/missing.pyc': '',
            '/tmp/another_unittest.py': '',
        }
        self.fs = MockFileSystem(files)
        self.finder = TestFinder(self.fs)
        self.finder.add_tree('/foo', 'bar')
        self.finder.add_tree('/foo2')

        # Here we have to jump through a hoop to make sure test-webkitpy doesn't log
        # any messages from these tests :(.
        self.root_logger = logging.getLogger()
        self.log_handler = None
        for h in self.root_logger.handlers:
            if getattr(h, 'name', None) == 'webkitpy.test.main':
                self.log_handler = h
                break
        if self.log_handler:
            self.log_level = self.log_handler.level
            self.log_handler.level = logging.CRITICAL

    def tearDown(self):
        if self.log_handler:
            self.log_handler.setLevel(self.log_level)

    def test_additional_system_paths(self):
        self.assertEquals(self.finder.additional_paths(['/usr']),
                          ['/foo', '/foo2'])

    def test_is_module(self):
        self.assertTrue(self.finder.is_module('bar.baz'))
        self.assertTrue(self.finder.is_module('bar2.baz2'))
        self.assertTrue(self.finder.is_module('bar2.baz2_integrationtest'))

        # Missing the proper namespace.
        self.assertFalse(self.finder.is_module('baz'))

    def test_to_module(self):
        self.assertEquals(self.finder.to_module('/foo/test.py'), 'test')
        self.assertEquals(self.finder.to_module('/foo/bar/test.py'),
                          'bar.test')
        self.assertEquals(self.finder.to_module('/foo/bar/pytest.py'),
                          'bar.pytest')

    def test_clean(self):
        self.assertTrue(self.fs.exists('/foo2/bar2/missing.pyc'))
        self.finder.clean_trees()
        self.assertFalse(self.fs.exists('/foo2/bar2/missing.pyc'))

    def check_names(self,
                    names,
                    expected_names,
                    skip_integrationtests=False,
                    find_all=False):
        self.assertEquals(
            self.finder.find_names(names, skip_integrationtests, find_all),
            expected_names)

    def test_default_names(self):
        self.check_names([], ['bar.baz_unittest', 'bar2.baz2_integrationtest'])
        self.check_names([], ['bar.baz_unittest'],
                         skip_integrationtests=True,
                         find_all=True)
        self.check_names([], ['bar.baz_unittest'],
                         skip_integrationtests=True,
                         find_all=False)

        # Should return the names given it, even if they don't exist.
        self.check_names(['foobar'], ['foobar'],
                         skip_integrationtests=True,
                         find_all=False)

    def test_paths(self):
        self.fs.chdir('/foo/bar')
        self.check_names(['baz_unittest.py'], ['bar.baz_unittest'])
        self.check_names(['./baz_unittest.py'], ['bar.baz_unittest'])
        self.check_names(['/foo/bar/baz_unittest.py'], ['bar.baz_unittest'])
        self.check_names(['.'], ['bar.baz_unittest'])
        self.check_names(['../../foo2/bar2'], ['bar2.baz2_integrationtest'])

        self.fs.chdir('/')
        self.check_names(['bar'], ['bar.baz_unittest'])
        self.check_names(['/foo/bar/'], ['bar.baz_unittest'])

        # This works 'by accident' since it maps onto a package.
        self.check_names(['bar/'], ['bar.baz_unittest'])

        # This should log an error, since it's outside the trees.
        oc = OutputCapture()
        oc.set_log_level(logging.ERROR)
        oc.capture_output()
        try:
            self.check_names(['/tmp/another_unittest.py'], [])
        finally:
            _, _, logs = oc.restore_output()
            self.assertTrue('another_unittest.py' in logs)

        # Paths that don't exist are errors.
        oc.capture_output()
        try:
            self.check_names(['/foo/bar/notexist_unittest.py'], [])
        finally:
            _, _, logs = oc.restore_output()
            self.assertTrue('notexist_unittest.py' in logs)

        # Names that don't exist are caught later, at load time.
        self.check_names(['bar.notexist_unittest'], ['bar.notexist_unittest'])
示例#4
0
class TestFinderTest(unittest.TestCase):
    def setUp(self):
        files = {
          '/foo/bar/baz.py': '',
          '/foo/bar/baz_unittest.py': '',
          '/foo2/bar2/baz2.py': '',
          '/foo2/bar2/baz2.pyc': '',
          '/foo2/bar2/baz2_integrationtest.py': '',
          '/foo2/bar2/missing.pyc': '',
          '/tmp/another_unittest.py': '',
        }
        self.fs = MockFileSystem(files)
        self.finder = TestFinder(self.fs)
        self.finder.add_tree('/foo', 'bar')
        self.finder.add_tree('/foo2')

        # Here we have to jump through a hoop to make sure test-webkitpy doesn't log
        # any messages from these tests :(.
        self.root_logger = logging.getLogger()
        self.log_handler = None
        for h in self.root_logger.handlers:
            if getattr(h, 'name', None) == 'webkitpy.test.main':
                self.log_handler = h
                break
        if self.log_handler:
            self.log_level = self.log_handler.level
            self.log_handler.level = logging.CRITICAL

    def tearDown(self):
        if self.log_handler:
            self.log_handler.setLevel(self.log_level)

    def test_additional_system_paths(self):
        self.assertEquals(self.finder.additional_paths(['/usr']),
                          ['/foo', '/foo2'])

    def test_is_module(self):
        self.assertTrue(self.finder.is_module('bar.baz'))
        self.assertTrue(self.finder.is_module('bar2.baz2'))
        self.assertTrue(self.finder.is_module('bar2.baz2_integrationtest'))

        # Missing the proper namespace.
        self.assertFalse(self.finder.is_module('baz'))

    def test_to_module(self):
        self.assertEquals(self.finder.to_module('/foo/test.py'), 'test')
        self.assertEquals(self.finder.to_module('/foo/bar/test.py'), 'bar.test')
        self.assertEquals(self.finder.to_module('/foo/bar/pytest.py'), 'bar.pytest')

    def test_clean(self):
        self.assertTrue(self.fs.exists('/foo2/bar2/missing.pyc'))
        self.finder.clean_trees()
        self.assertFalse(self.fs.exists('/foo2/bar2/missing.pyc'))

    def check_names(self, names, expected_names, skip_integrationtests=False, find_all=False):
        self.assertEquals(self.finder.find_names(names, skip_integrationtests, find_all),
                          expected_names)

    def test_default_names(self):
        self.check_names([], ['bar.baz_unittest', 'bar2.baz2_integrationtest'])
        self.check_names([], ['bar.baz_unittest'], skip_integrationtests=True, find_all=True)
        self.check_names([], ['bar.baz_unittest'], skip_integrationtests=True, find_all=False)

        # Should return the names given it, even if they don't exist.
        self.check_names(['foobar'], ['foobar'], skip_integrationtests=True, find_all=False)

    def test_paths(self):
        self.fs.chdir('/foo/bar')
        self.check_names(['baz_unittest.py'], ['bar.baz_unittest'])
        self.check_names(['./baz_unittest.py'], ['bar.baz_unittest'])
        self.check_names(['/foo/bar/baz_unittest.py'], ['bar.baz_unittest'])
        self.check_names(['.'], ['bar.baz_unittest'])
        self.check_names(['../../foo2/bar2'], ['bar2.baz2_integrationtest'])

        self.fs.chdir('/')
        self.check_names(['bar'], ['bar.baz_unittest'])
        self.check_names(['/foo/bar/'], ['bar.baz_unittest'])

        # This works 'by accident' since it maps onto a package.
        self.check_names(['bar/'], ['bar.baz_unittest'])

        # This should log an error, since it's outside the trees.
        oc = OutputCapture()
        oc.set_log_level(logging.ERROR)
        oc.capture_output()
        try:
            self.check_names(['/tmp/another_unittest.py'], [])
        finally:
            _, _, logs = oc.restore_output()
            self.assertTrue('another_unittest.py' in logs)

        # Paths that don't exist are errors.
        oc.capture_output()
        try:
            self.check_names(['/foo/bar/notexist_unittest.py'], [])
        finally:
            _, _, logs = oc.restore_output()
            self.assertTrue('notexist_unittest.py' in logs)

        # Names that don't exist are caught later, at load time.
        self.check_names(['bar.notexist_unittest'], ['bar.notexist_unittest'])