Commit b2bb903a authored by zhaoyangli's avatar zhaoyangli Committed by Commit Bot

[iOS][test runner] Prepare to run XCTest based unit tests on simulators.

Makes test runner run XCTest based unit tests with correct test app, by
testing args passed to test runner.

Use xctest arg to determine runner type only, but not parser type
anymore in test runner, except for special handling for WebRTC xctests
with a TODO.

Related CLs:
- GN building the arg to test runner: crrev/c/2314134.
- GN config change in some iOS FYI builders: crrev/c/2315638.

Bug: 1001667, 1006881
Change-Id: I3fcd69f21641894f12e315898ce29059449b1b6d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2315245
Commit-Queue: Zhaoyang Li <zhaoyangli@chromium.org>
Reviewed-by: default avatarJustin Cohen <justincohen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#792412}
parent 28742de9
......@@ -352,8 +352,7 @@ class EgtestsApp(GTestsApp):
class DeviceXCTestUnitTestsApp(GTestsApp):
"""XCTest hosted unit tests to run on devices.
This is for the XCTest framework hosted unit tests, which run on iOS 13+
real devices now.
This is for the XCTest framework hosted unit tests running on devices.
Stores data about tests:
tests_app: full path to tests app.
......@@ -381,13 +380,13 @@ class DeviceXCTestUnitTestsApp(GTestsApp):
E.g.
[ 'TestCaseClass1', 'TestCaseClass2/testMethod2']
test_args: List of strings to pass as arguments to the test when
launching.
launching. Test arg to run as XCTest based unit test will be appended.
env_vars: List of environment variables to pass to the test itself.
Raises:
AppNotFoundError: If the given app does not exist
"""
test_args = test_args or []
test_args = list(test_args or [])
test_args.append('--enable-run-ios-unittests-with-xctest')
super(DeviceXCTestUnitTestsApp,
self).__init__(tests_app, included_tests, excluded_tests, test_args,
......@@ -463,3 +462,118 @@ class DeviceXCTestUnitTestsApp(GTestsApp):
{'CommandLineArguments': self.test_args})
return xctestrun_data
class SimulatorXCTestUnitTestsApp(GTestsApp):
"""XCTest hosted unit tests to run on simulators.
This is for the XCTest framework hosted unit tests running on simulators.
Stores data about tests:
tests_app: full path to tests app.
project_path: root project folder.
module_name: egtests module name.
included_tests: List of tests to run.
excluded_tests: List of tests not to run.
"""
def __init__(self,
tests_app,
included_tests=None,
excluded_tests=None,
test_args=None,
env_vars=None,
release=False):
"""Initialize the class.
Args:
tests_app: (str) full path to tests app.
included_tests: (list) Specific tests to run
E.g.
[ 'TestCaseClass1/testMethod1', 'TestCaseClass2/testMethod2']
excluded_tests: (list) Specific tests not to run
E.g.
[ 'TestCaseClass1', 'TestCaseClass2/testMethod2']
test_args: List of strings to pass as arguments to the test when
launching. Test arg to run as XCTest based unit test will be appended.
env_vars: List of environment variables to pass to the test itself.
Raises:
AppNotFoundError: If the given app does not exist
"""
test_args = list(test_args or [])
test_args.append('--enable-run-ios-unittests-with-xctest')
super(SimulatorXCTestUnitTestsApp,
self).__init__(tests_app, included_tests, excluded_tests, test_args,
env_vars, release, None)
# TODO(crbug.com/1077277): Refactor class structure and remove duplicate code.
def _xctest_path(self):
"""Gets xctest-file from egtests/PlugIns folder.
Returns:
A path for xctest in the format of /PlugIns/file.xctest
Raises:
PlugInsNotFoundError: If no PlugIns folder found in egtests.app.
XCTestPlugInNotFoundError: If no xctest-file found in PlugIns.
"""
plugins_dir = os.path.join(self.test_app_path, 'PlugIns')
if not os.path.exists(plugins_dir):
raise test_runner.PlugInsNotFoundError(plugins_dir)
plugin_xctest = None
if os.path.exists(plugins_dir):
for plugin in os.listdir(plugins_dir):
if plugin.endswith('.xctest'):
plugin_xctest = os.path.join(plugins_dir, plugin)
if not plugin_xctest:
raise test_runner.XCTestPlugInNotFoundError(plugin_xctest)
return plugin_xctest.replace(self.test_app_path, '')
def fill_xctestrun_node(self):
"""Fills only required nodes for XCTest hosted unit tests in xctestrun file.
Returns:
A node with filled required fields about tests.
"""
xctestrun_data = {
'TestTargetName': {
'IsAppHostedTestBundle': True,
'TestBundlePath': '__TESTHOST__/%s' % self._xctest_path(),
'TestHostBundleIdentifier': get_bundle_id(self.test_app_path),
'TestHostPath': '%s' % self.test_app_path,
'TestingEnvironmentVariables': {
'DYLD_INSERT_LIBRARIES':
'__PLATFORMS__/iPhoneSimulator.platform/Developer/usr/lib/'
'libXCTestBundleInject.dylib',
'DYLD_LIBRARY_PATH':
'__PLATFORMS__/iPhoneSimulator.platform/Developer/Library',
'DYLD_FRAMEWORK_PATH':
'__PLATFORMS__/iPhoneSimulator.platform/Developer/'
'Library/Frameworks',
'XCInjectBundleInto':
'__TESTHOST__/%s' % self.module_name
}
}
}
if self.env_vars:
self.xctestrun_data['TestTargetName'].update(
{'EnvironmentVariables': self.env_vars})
gtest_filter = []
if self.included_tests:
gtest_filter = get_gtest_filter(self.included_tests, invert=False)
elif self.excluded_tests:
gtest_filter = get_gtest_filter(self.excluded_tests, invert=True)
if gtest_filter:
# Removed previous gtest-filter if exists.
self.test_args = [
el for el in self.test_args if not el.startswith('--gtest_filter=')
]
self.test_args.append('--gtest_filter=%s' % gtest_filter)
xctestrun_data['TestTargetName'].update(
{'CommandLineArguments': self.test_args})
return xctestrun_data
......@@ -382,6 +382,13 @@ class TestRunner(object):
# for XCtests and Gtests.
self.xctest = xctest
# TODO(crbug.com/1110375): Remove this when WebRTC xctests run with
# xcodebuild_runner.
webrtc_xctest_names = [
'apprtcmobile_tests', 'sdk_unittests', 'sdk_framework_unittests'
]
self.webrtc_xctest = self.xctest and self.app_name in webrtc_xctest_names
self.test_results = {}
self.test_results['version'] = 3
self.test_results['path_delimiter'] = '.'
......@@ -522,7 +529,8 @@ class TestRunner(object):
GTestResult instance.
"""
result = gtest_utils.GTestResult(cmd)
if self.xctest:
if self.webrtc_xctest:
parser = xctest_utils.XCTestLogParser()
else:
parser = gtest_utils.GTestLogParser()
......@@ -541,7 +549,7 @@ class TestRunner(object):
LOGGER.debug('Stdout flushed after test process.')
returncode = proc.returncode
if self.xctest and parser.SystemAlertPresent():
if self.webrtc_xctest and parser.SystemAlertPresent():
raise SystemAlertPresentError()
LOGGER.debug('Processing test results.')
......@@ -556,7 +564,7 @@ class TestRunner(object):
result.passed_tests.extend(parser.PassedTests(include_flaky=True))
# Only GTest outputs compiled tests in a json file.
if not self.xctest:
if not self.webrtc_xctest:
result.disabled_tests_from_compiled_tests_file.extend(
parser.DisabledTestsFromCompiledTestsFile())
......@@ -571,12 +579,21 @@ class TestRunner(object):
"""Launches the test app."""
self.set_up()
destination = 'id=%s' % self.udid
if self.xctest:
if self.webrtc_xctest:
test_app = test_apps.EgtestsApp(
self.app_path,
included_tests=self.test_cases,
env_vars=self.env_vars,
test_args=self.test_args)
# When current |launch| method is invoked, this is running a unit test
# target. For simulators, '--xctest' is passed to test runner scripts to
# make it run XCTest based unit test.
elif self.xctest:
test_app = test_apps.SimulatorXCTestUnitTestsApp(
self.app_path,
included_tests=self.test_cases,
env_vars=self.env_vars,
test_args=self.test_args)
elif self.xctest_path:
if self.__class__.__name__ == 'DeviceTestRunner':
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment