1import sys
2import imp
3import os
4import fnmatch
5import sys
6sys.stderr.write("Warning: You are using test runners in legacy mode\n. "
7                 "That means you have 'python.tests.enableUniversalTests=false' in registry.\n"
8                 "This mode will be dropped in 2021. Consider removing this entry from registry and migrating to new test runners")
9roots = sys.path[:]
10
11helpers_dir = os.getenv("PYCHARM_HELPERS_DIR", sys.path[0])
12if sys.path[0] != helpers_dir:
13  sys.path.insert(0, helpers_dir)
14
15from tcunittest import TeamcityTestRunner
16from nose_helper import TestLoader, ContextSuite
17from pycharm_run_utils import import_system_module
18from pycharm_run_utils import adjust_sys_path
19from pycharm_run_utils import debug, getModuleName, PYTHON_VERSION_MAJOR
20
21adjust_sys_path()
22
23os = import_system_module("os")
24re = import_system_module("re")
25
26modules = {}
27
28def loadSource(fileName):
29  baseName = os.path.basename(fileName)
30  moduleName = os.path.splitext(baseName)[0]
31
32  if os.path.isdir(fileName):
33    fileName = fileName.rstrip('/\\') + os.path.sep
34
35  # for users wanted to run unittests under django
36  # because of django took advantage of module name
37  settings_file = os.getenv('DJANGO_SETTINGS_MODULE')
38
39  if settings_file and moduleName == "models":
40    baseName = os.path.realpath(fileName)
41    moduleName = ".".join((baseName.split(os.sep)[-2], "models"))
42  else:
43    path = fileName
44    for p in roots:
45      # Python 2.6+
46      try:
47        rel_path = os.path.relpath(fileName, start=p)
48        if rel_path.find('..') == -1 and len(rel_path) < len(path):
49          path = rel_path
50      except:
51        pass # relpath can raise an error in case of different drives for a path and start on Windows
52
53    if path.endswith('.py'):
54      path = path[0:-3]
55
56    moduleName = path.replace('/', '.').replace('\\', '.')
57
58  if moduleName in modules and len(sys.argv[1:-1]) == 1:  # add unique number to prevent name collisions
59    cnt = 2
60    prefix = moduleName
61    while getModuleName(prefix, cnt) in modules:
62      cnt += 1
63    moduleName = getModuleName(prefix, cnt)
64
65  debug("/ Loading " + fileName + " as " + moduleName)
66
67  try:
68    module = imp.load_source(moduleName, fileName)
69  except SystemError:  # probably failed because of the relative imports
70    # first we import module with all its parents
71    __import__(moduleName)
72
73    # then load it by filename to be sure it is the one we need
74    module = imp.load_source(moduleName, fileName)
75
76  modules[moduleName] = module
77  return module
78
79def walkModules(modulesAndPattern, dirname, names):
80  modules = modulesAndPattern[0]
81  pattern = modulesAndPattern[1]
82  # fnmatch converts glob to regexp
83  prog_list = [re.compile(fnmatch.translate(pat.strip())) for pat in pattern.split(',')]
84  for name in names:
85    for prog in prog_list:
86      if name.endswith(".py") and prog.match(name):
87        modules.append(loadSource(os.path.join(dirname, name)))
88
89
90# For default pattern see https://docs.python.org/2/library/unittest.html#test-discovery
91def loadModulesFromFolderRec(folder, pattern="test*.py"):
92  modules = []
93  # fnmatch converts glob to regexp
94  prog_list = [re.compile(fnmatch.translate(pat.strip())) for pat in pattern.split(',')]
95  for root, dirs, files in os.walk(folder):
96    files = [f for f in files if not f[0] == '.']
97    dirs[:] = [d for d in dirs if not d[0] == '.']
98    for name in files:
99      for prog in prog_list:
100        if name.endswith(".py") and prog.match(name):
101          modules.append(loadSource(os.path.join(root, name)))
102  return modules
103
104testLoader = TestLoader()
105all = ContextSuite()
106pure_unittest = False
107
108def setLoader(module):
109  global testLoader, all
110  try:
111    module.__getattribute__('unittest2')
112    import unittest2
113
114    testLoader = unittest2.TestLoader()
115    all = unittest2.TestSuite()
116  except:
117    pass
118
119if __name__ == "__main__":
120  arg = sys.argv[-1]
121  if arg == "true":
122    import unittest
123
124    testLoader = unittest.TestLoader()
125    all = unittest.TestSuite()
126    pure_unittest = True
127
128    if len(sys.argv) == 2:  # If folder not provided, we need pretend folder is current
129     sys.argv.insert(1, ".")
130
131  options = {}
132  for arg in sys.argv[1:-1]:
133    arg = arg.strip()
134    if len(arg) == 0:
135      continue
136
137    if arg.startswith("--"):
138      options[arg[2:]] = True
139      continue
140
141    a = arg.split("::")
142    if len(a) == 1:
143      # From module or folder
144      a_splitted = a[0].split("_args_separator_")  # ";" can't be used with bash, so we use "_args_separator_"
145      if len(a_splitted) != 1:
146        # means we have pattern to match against
147        if os.path.isdir(a_splitted[0]):
148          debug("/ from folder " + a_splitted[0] + ". Use pattern: " + a_splitted[1])
149          modules = loadModulesFromFolderRec(a_splitted[0], a_splitted[1])
150      else:
151        if os.path.isdir(a[0]):
152          debug("/ from folder " + a[0])
153          modules = loadModulesFromFolderRec(a[0])
154        else:
155          debug("/ from module " + a[0])
156          modules = [loadSource(a[0])]
157
158      for module in modules:
159        all.addTests(testLoader.loadTestsFromModule(module))
160
161    elif len(a) == 2:
162      # From testcase
163      debug("/ from testcase " + a[1] + " in " + a[0])
164      module = loadSource(a[0])
165      setLoader(module)
166
167      if pure_unittest:
168        all.addTests(testLoader.loadTestsFromTestCase(getattr(module, a[1])))
169      else:
170        all.addTests(testLoader.loadTestsFromTestClass(getattr(module, a[1])),
171                     getattr(module, a[1]))
172    else:
173      # From method in class or from function
174      debug("/ from method " + a[2] + " in testcase " + a[1] + " in " + a[0])
175      module = loadSource(a[0])
176      setLoader(module)
177
178      if a[1] == "":
179        # test function, not method
180        all.addTest(testLoader.makeTest(getattr(module, a[2])))
181      else:
182        testCaseClass = getattr(module, a[1])
183        try:
184          all.addTest(testCaseClass(a[2]))
185        except:
186          # class is not a testcase inheritor
187          all.addTest(
188            testLoader.makeTest(getattr(testCaseClass, a[2]), testCaseClass))
189
190  debug("/ Loaded " + str(all.countTestCases()) + " tests")
191  TeamcityTestRunner().run(all, **options)
192