bug 1255479 - make `mach python-tests` use TestResolver for discovery, make `mach test` work for python tests. r?nalexander
MozReview-Commit-ID: CK2Vh6gdnb0
--- a/build/compare-mozconfig/compare-mozconfigs-wrapper.py
+++ b/build/compare-mozconfig/compare-mozconfigs-wrapper.py
@@ -1,63 +1,68 @@
#!/usr/bin/python
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from __future__ import unicode_literals
+import logging
+import mozunit
import subprocess
import sys
+import unittest
+
from os import path
from buildconfig import substs
-import logging
log = logging.getLogger(__name__)
def determine_platform():
platform_mapping = {'WINNT': {'x86_64': 'win64',
'i686': 'win32'},
'Darwin': {'x86_64': 'macosx-universal',
'i386':'macosx-universal'},
'Linux': {'x86_64': 'linux64',
'i686': 'linux32'}}
os_type = substs['OS_TARGET']
cpu_type = substs['TARGET_CPU']
return platform_mapping.get(os_type, {}).get(cpu_type, None)
-def main():
- """ A wrapper script that calls compare-mozconfig.py
- based on the platform that the machine is building for"""
- platform = determine_platform()
- if platform is not None:
- python_exe = substs['PYTHON']
- topsrcdir = substs['top_srcdir']
+class TestCompareMozconfigs(unittest.TestCase):
+ def test_compare_mozconfigs(self):
+ """ A wrapper script that calls compare-mozconfig.py
+ based on the platform that the machine is building for"""
+ platform = determine_platform()
- # construct paths and args for compare-mozconfig
- browser_dir = path.join(topsrcdir, 'browser')
- script_path = path.join(topsrcdir, 'build/compare-mozconfig/compare-mozconfigs.py')
- whitelist_path = path.join(browser_dir, 'config/mozconfigs/whitelist')
- beta_mozconfig_path = path.join(browser_dir, 'config/mozconfigs', platform, 'beta')
- release_mozconfig_path = path.join(browser_dir, 'config/mozconfigs', platform, 'release')
- nightly_mozconfig_path = path.join(browser_dir, 'config/mozconfigs', platform, 'nightly')
+ if platform is not None:
+ python_exe = substs['PYTHON']
+ topsrcdir = substs['top_srcdir']
- log.info("Comparing beta against nightly mozconfigs")
- ret_code = subprocess.call([python_exe, script_path, '--whitelist',
- whitelist_path, '--no-download',
- platform + ',' + beta_mozconfig_path +
- ',' + nightly_mozconfig_path])
+ # construct paths and args for compare-mozconfig
+ browser_dir = path.join(topsrcdir, 'browser')
+ script_path = path.join(topsrcdir, 'build/compare-mozconfig/compare-mozconfigs.py')
+ whitelist_path = path.join(browser_dir, 'config/mozconfigs/whitelist')
+ beta_mozconfig_path = path.join(browser_dir, 'config/mozconfigs', platform, 'beta')
+ release_mozconfig_path = path.join(browser_dir, 'config/mozconfigs', platform, 'release')
+ nightly_mozconfig_path = path.join(browser_dir, 'config/mozconfigs', platform, 'nightly')
- if ret_code > 0:
- return ret_code
+ log.info("Comparing beta against nightly mozconfigs")
+ ret_code = subprocess.call([python_exe, script_path, '--whitelist',
+ whitelist_path, '--no-download',
+ platform + ',' + beta_mozconfig_path +
+ ',' + nightly_mozconfig_path])
- log.info("Comparing release against nightly mozconfigs")
- ret_code = subprocess.call([python_exe, script_path, '--whitelist',
- whitelist_path, '--no-download',
- platform + ',' + release_mozconfig_path +
- ',' + nightly_mozconfig_path])
+ if ret_code > 0:
+ return ret_code
- return ret_code
+ log.info("Comparing release against nightly mozconfigs")
+ ret_code = subprocess.call([python_exe, script_path, '--whitelist',
+ whitelist_path, '--no-download',
+ platform + ',' + release_mozconfig_path +
+ ',' + nightly_mozconfig_path])
+
+ self.assertEqual(0, ret_code)
if __name__ == '__main__':
- sys.exit(main())
+ mozunit.main()
--- a/python/mach_commands.py
+++ b/python/mach_commands.py
@@ -72,58 +72,49 @@ class MachCommands(MachCommandBase):
@CommandArgument('--verbose',
default=False,
action='store_true',
help='Verbose output.')
@CommandArgument('--stop',
default=False,
action='store_true',
help='Stop running tests after the first error or failure.')
- @CommandArgument('tests', nargs='+',
+ @CommandArgument('tests', nargs='*',
metavar='TEST',
help='Tests to run. Each test can be a single file or a directory.')
- def python_test(self, tests, verbose=False, stop=False):
+ def python_test(self,
+ tests=[],
+ test_objects=None,
+ subsuite=None,
+ verbose=False,
+ stop=False):
self._activate_virtualenv()
import glob
# Python's unittest, and in particular discover, has problems with
# clashing namespaces when importing multiple test modules. What follows
# is a simple way to keep environments separate, at the price of
# launching Python multiple times. This also runs tests via mozunit,
# which produces output in the format Mozilla infrastructure expects.
return_code = 0
- files = []
- # We search for files in both the current directory (for people running
- # from topsrcdir or cd'd into their test directory) and topsrcdir (to
- # support people running mach from the objdir). The |break|s in the
- # loop below ensure that we don't run tests twice if we're running mach
- # from topsrcdir
- search_dirs = ['.', self.topsrcdir]
- last_search_dir = search_dirs[-1]
- for t in tests:
- for d in search_dirs:
- test = mozpath.join(d, t)
- if test.endswith('.py') and os.path.isfile(test):
- files.append(test)
- break
- elif os.path.isfile(test + '.py'):
- files.append(test + '.py')
- break
- elif os.path.isdir(test):
- files += glob.glob(mozpath.join(test, 'test*.py'))
- files += glob.glob(mozpath.join(test, 'unit*.py'))
- break
- elif d == last_search_dir:
- self.log(logging.WARN, 'python-test',
- {'test': t},
- 'TEST-UNEXPECTED-FAIL | Invalid test: {test}')
- if stop:
- return 1
+ if test_objects is None:
+ # If we're not being called from `mach test`, do our own
+ # test resolution.
+ from mozbuild.testing import TestResolver
+ resolver = self._spawn(TestResolver)
+ if tests:
+ # If we were given test paths, try to find tests matching them.
+ test_objects = resolver.resolve_tests(paths=tests,
+ flavor='python')
+ else:
+ # Otherwise just run all Python tests.
+ test_objects = resolver.resolve_tests(flavor='python')
- for f in files:
+ for test in test_objects:
+ f = test['path']
file_displayed_test = [] # Used as a boolean.
def _line_handler(line):
if not file_displayed_test and line.startswith('TEST-'):
file_displayed_test.append(True)
inner_return_code = self.run_process(
[self.virtualenv_manager.python_path, f],
--- a/python/moz.build
+++ b/python/moz.build
@@ -15,44 +15,34 @@ SPHINX_PYTHON_PACKAGE_DIRS += [
'mozbuild/mozbuild',
'mozbuild/mozpack',
'mozversioncontrol/mozversioncontrol',
]
SPHINX_TREES['mach'] = 'mach/docs'
PYTHON_UNIT_TESTS += [
- 'mach/mach/test/__init__.py',
- 'mach/mach/test/common.py',
'mach/mach/test/test_conditions.py',
'mach/mach/test/test_config.py',
'mach/mach/test/test_entry_point.py',
'mach/mach/test/test_error_output.py',
'mach/mach/test/test_logger.py',
- 'mozbuild/dumbmake/test/__init__.py',
'mozbuild/dumbmake/test/test_dumbmake.py',
- 'mozbuild/mozbuild/test/__init__.py',
'mozbuild/mozbuild/test/action/test_buildlist.py',
'mozbuild/mozbuild/test/action/test_generate_browsersearch.py',
- 'mozbuild/mozbuild/test/backend/__init__.py',
- 'mozbuild/mozbuild/test/backend/common.py',
'mozbuild/mozbuild/test/backend/test_android_eclipse.py',
'mozbuild/mozbuild/test/backend/test_build.py',
'mozbuild/mozbuild/test/backend/test_configenvironment.py',
'mozbuild/mozbuild/test/backend/test_recursivemake.py',
'mozbuild/mozbuild/test/backend/test_visualstudio.py',
- 'mozbuild/mozbuild/test/common.py',
- 'mozbuild/mozbuild/test/compilation/__init__.py',
'mozbuild/mozbuild/test/compilation/test_warnings.py',
'mozbuild/mozbuild/test/configure/test_configure.py',
'mozbuild/mozbuild/test/configure/test_options.py',
- 'mozbuild/mozbuild/test/controller/__init__.py',
'mozbuild/mozbuild/test/controller/test_ccachestats.py',
'mozbuild/mozbuild/test/controller/test_clobber.py',
- 'mozbuild/mozbuild/test/frontend/__init__.py',
'mozbuild/mozbuild/test/frontend/test_context.py',
'mozbuild/mozbuild/test/frontend/test_emitter.py',
'mozbuild/mozbuild/test/frontend/test_namespaces.py',
'mozbuild/mozbuild/test/frontend/test_reader.py',
'mozbuild/mozbuild/test/frontend/test_sandbox.py',
'mozbuild/mozbuild/test/test_base.py',
'mozbuild/mozbuild/test/test_containers.py',
'mozbuild/mozbuild/test/test_dotproperties.py',
@@ -61,17 +51,16 @@ PYTHON_UNIT_TESTS += [
'mozbuild/mozbuild/test/test_line_endings.py',
'mozbuild/mozbuild/test/test_makeutil.py',
'mozbuild/mozbuild/test/test_mozconfig.py',
'mozbuild/mozbuild/test/test_mozinfo.py',
'mozbuild/mozbuild/test/test_preprocessor.py',
'mozbuild/mozbuild/test/test_pythonutil.py',
'mozbuild/mozbuild/test/test_testing.py',
'mozbuild/mozbuild/test/test_util.py',
- 'mozbuild/mozpack/test/__init__.py',
'mozbuild/mozpack/test/test_chrome_flags.py',
'mozbuild/mozpack/test/test_chrome_manifest.py',
'mozbuild/mozpack/test/test_copier.py',
'mozbuild/mozpack/test/test_errors.py',
'mozbuild/mozpack/test/test_files.py',
'mozbuild/mozpack/test/test_manifests.py',
'mozbuild/mozpack/test/test_mozjar.py',
'mozbuild/mozpack/test/test_packager.py',
--- a/testing/mach_commands.py
+++ b/testing/mach_commands.py
@@ -91,16 +91,20 @@ TEST_SUITES = {
'mochitest-plain': {
'mach_command': 'mochitest',
'kwargs': {'flavor': 'plain', 'test_paths': None},
},
'luciddream': {
'mach_command': 'luciddream',
'kwargs': {'test_paths': None},
},
+ 'python': {
+ 'mach_command': 'python-test',
+ 'kwargs': {'tests': None},
+ },
'reftest': {
'aliases': ('RR', 'rr', 'Rr'),
'mach_command': 'reftest',
'kwargs': {'tests': None},
},
'reftest-ipc': {
'aliases': ('Ripc',),
'mach_command': 'reftest-ipc',
@@ -141,16 +145,20 @@ TEST_FLAVORS = {
'marionette': {
'mach_command': 'marionette-test',
'kwargs': {'tests': []},
},
'mochitest': {
'mach_command': 'mochitest',
'kwargs': {'flavor': 'mochitest', 'test_paths': []},
},
+ 'python': {
+ 'mach_command': 'python-test',
+ 'kwargs': {},
+ },
'reftest': {
'mach_command': 'reftest',
'kwargs': {'tests': []}
},
'steeplechase': {},
'web-platform-tests': {
'mach_command': 'web-platform-tests',
'kwargs': {'include': []}
--- a/testing/xpcshell/selftest.py
+++ b/testing/xpcshell/selftest.py
@@ -1,20 +1,25 @@
#!/usr/bin/env python
#
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
#
-from __future__ import with_statement
-import sys, os, unittest, tempfile, shutil, re, pprint
import mozinfo
+import mozunit
+import os
+import pprint
+import re
+import shutil
+import sys
+import tempfile
+import unittest
from StringIO import StringIO
-
from mozlog import structured
from mozbuild.base import MozbuildObject
os.environ.pop('MOZ_OBJDIR', None)
build_obj = MozbuildObject.from_environment()
from runxpcshelltests import XPCShellTests
mozinfo.find_and_update_from_json()
@@ -1336,9 +1341,9 @@ add_test({
self.assertEquals(1, self.x.testCount)
self.assertEquals(1, self.x.passCount)
self.assertEquals(0, self.x.failCount)
self.assertEquals(0, self.x.todoCount)
self.assertInLog(TEST_PASS_STRING)
self.assertNotInLog(TEST_FAIL_STRING)
if __name__ == "__main__":
- unittest.main(verbosity=3)
+ mozunit.main()
--- a/toolkit/crashreporter/tools/unit-symbolstore.py
+++ b/toolkit/crashreporter/tools/unit-symbolstore.py
@@ -1,15 +1,16 @@
#!/usr/bin/env python
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import concurrent.futures
import mock
+import mozunit
import os
import platform
import shutil
import struct
import subprocess
import sys
import tempfile
import unittest
@@ -523,10 +524,10 @@ class TestFunctional(HelperMixin, unitte
self.assertEqual('hg:', filename[:3])
if __name__ == '__main__':
# use ThreadPoolExecutor to use threading instead of processes so
# that our mocking/module-patching works.
symbolstore.Dumper.GlobalInit(concurrent.futures.ThreadPoolExecutor)
- unittest.main()
+ mozunit.main()