summaryrefslogtreecommitdiffstats
path: root/tools/telemetry/telemetry/unittest/run_tests.py
blob: 727bfc84421f1eb05e25997977c93fc3622fbc32 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# Copyright 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import logging
import sys
import unittest

from telemetry import decorators
from telemetry.core import browser_finder
from telemetry.core import browser_options
from telemetry.core import command_line
from telemetry.core import discover
from telemetry.core import util
from telemetry.unittest import gtest_unittest_results
from telemetry.unittest import options_for_unittests


class Environment(object):
  def __init__(self, top_level_dir, test_dirs):
    self._top_level_dir = top_level_dir
    self._test_dirs = tuple(test_dirs)

  @property
  def top_level_dir(self):
    return self._top_level_dir

  @property
  def test_dirs(self):
    return self._test_dirs


def Discover(start_dir, top_level_dir=None, pattern='test*.py'):
  loader = unittest.defaultTestLoader
  loader.suiteClass = gtest_unittest_results.GTestTestSuite

  test_suites = []
  modules = discover.DiscoverModules(start_dir, top_level_dir, pattern)
  for module in modules:
    if hasattr(module, 'suite'):
      suite = module.suite()
    else:
      suite = loader.loadTestsFromModule(module)
    if suite.countTestCases():
      test_suites.append(suite)
  return test_suites


def FilterSuite(suite, predicate):
  new_suite = suite.__class__()
  for test in suite:
    if isinstance(test, unittest.TestSuite):
      subsuite = FilterSuite(test, predicate)
      if subsuite.countTestCases():
        new_suite.addTest(subsuite)
    else:
      assert isinstance(test, unittest.TestCase)
      if predicate(test):
        new_suite.addTest(test)

  return new_suite


def DiscoverTests(search_dirs, top_level_dir, possible_browser,
                  selected_tests=None, run_disabled_tests=False):
  def IsTestSelected(test):
    if selected_tests:
      found = False
      for name in selected_tests:
        if name in test.id():
          found = True
      if not found:
        return False
    if run_disabled_tests:
      return True
    # pylint: disable=W0212
    if not hasattr(test, '_testMethodName'):
      return True
    method = getattr(test, test._testMethodName)
    return decorators.IsEnabled(method, possible_browser)

  wrapper_suite = gtest_unittest_results.GTestTestSuite()
  for search_dir in search_dirs:
    wrapper_suite.addTests(Discover(search_dir, top_level_dir, '*_unittest.py'))
  return FilterSuite(wrapper_suite, IsTestSelected)


def RestoreLoggingLevel(func):
  def _LoggingRestoreWrapper(*args, **kwargs):
    # Cache the current logging level, this needs to be done before calling
    # parser.parse_args, which changes logging level based on verbosity
    # setting.
    logging_level = logging.getLogger().getEffectiveLevel()
    try:
      return func(*args, **kwargs)
    finally:
      # Restore logging level, which may be changed in parser.parse_args.
      logging.getLogger().setLevel(logging_level)

  return _LoggingRestoreWrapper


environment = None


class RunTestsCommand(command_line.OptparseCommand):
  """Run unit tests"""

  usage = '[test_name ...] [<options>]'

  @classmethod
  def CreateParser(cls):
    options = browser_options.BrowserFinderOptions()
    options.browser_type = 'any'
    parser = options.CreateParser('%%prog %s' % cls.usage)
    return parser

  @classmethod
  def AddCommandLineArgs(cls, parser):
    parser.add_option('--repeat-count', dest='run_test_repeat_count',
                      type='int', default=1,
                      help='Repeats each a provided number of times.')
    parser.add_option('-d', '--also-run-disabled-tests',
                      dest='run_disabled_tests',
                      action='store_true', default=False,
                      help='Ignore @Disabled and @Enabled restrictions.')

  @classmethod
  def ProcessCommandLineArgs(cls, parser, args):
    if args.verbosity == 0:
      logging.getLogger().setLevel(logging.WARN)

    try:
      possible_browser = browser_finder.FindBrowser(args)
    except browser_finder.BrowserFinderException, ex:
      parser.error(ex)

    if not possible_browser:
      parser.error('No browser found of type %s. Cannot run tests.\n'
                   'Re-run with --browser=list to see '
                   'available browser types.' % args.browser_type)

    cls.test_suite = DiscoverTests(
        environment.test_dirs, environment.top_level_dir, possible_browser,
        args.positional_args, args.run_disabled_tests)

  @RestoreLoggingLevel
  def Run(self, args):
    util.AddDirToPythonPath(util.GetUnittestDataDir())

    result = gtest_unittest_results.GTestUnittestResults(sys.stdout)
    try:
      options_for_unittests.Set(args)
      for _ in xrange(args.run_test_repeat_count):
        self.test_suite(result)
    finally:
      options_for_unittests.Set(None)

    result.PrintSummary()
    return len(result.failures) + len(result.errors)