OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """Contains test runners for launching tests on simulators and devices.""" | 6 """Contains test runners for launching tests on simulators and devices.""" |
7 | 7 |
8 # pylint: disable=relative-import | 8 # pylint: disable=relative-import |
9 import environment_setup | 9 import environment_setup |
10 | 10 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 'Unexpected app path: %s. %s' % (app_path, valid_extensions)) | 84 'Unexpected app path: %s. %s' % (app_path, valid_extensions)) |
85 | 85 |
86 | 86 |
87 class SimulatorNotFoundError(TestRunnerError): | 87 class SimulatorNotFoundError(TestRunnerError): |
88 """The iossim path was not found.""" | 88 """The iossim path was not found.""" |
89 def __init__(self, iossim_path): | 89 def __init__(self, iossim_path): |
90 super(SimulatorNotFoundError, self).__init__( | 90 super(SimulatorNotFoundError, self).__init__( |
91 'Simulator does not exist: %s.' % iossim_path) | 91 'Simulator does not exist: %s.' % iossim_path) |
92 | 92 |
93 | 93 |
94 class XctestNotFoundError(TestRunnerError): | |
95 """The xctest intended to be run was not found.""" | |
96 def __init__(self, xctest_path): | |
97 super(XctestNotFoundError, self).__init__( | |
98 'Xctest does not exist: %s.' % xctest_path) | |
99 | |
100 | |
101 class AppLaunchError(TestRunnerError): | 94 class AppLaunchError(TestRunnerError): |
102 """There was an error launching the app.""" | 95 """There was an error launching the app.""" |
103 pass | 96 pass |
104 | 97 |
105 | 98 |
106 class TestRunner(object): | 99 class TestRunner(object): |
107 """Base class containing common TestRunner functionality.""" | 100 """Base class containing common TestRunner functionality.""" |
108 def __init__( | 101 def __init__( |
109 self, | 102 self, |
110 app_path, | 103 app_path, |
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
786 result = self._Run(self.GetLaunchCommand(), *args, **kwargs) | 779 result = self._Run(self.GetLaunchCommand(), *args, **kwargs) |
787 | 780 |
788 return self.RunAllTests(result, *args, **kwargs) | 781 return self.RunAllTests(result, *args, **kwargs) |
789 | 782 |
790 | 783 |
791 class XCTestRunner(TestRunner): | 784 class XCTestRunner(TestRunner): |
792 """Base class containing common functionalities to run xctests.""" | 785 """Base class containing common functionalities to run xctests.""" |
793 def __init__( | 786 def __init__( |
794 self, | 787 self, |
795 app_path, | 788 app_path, |
| 789 test_host, |
| 790 test_project_dir, |
796 xcode_version=None, | 791 xcode_version=None, |
797 gs_bucket=None, | 792 gs_bucket=None, |
798 perf_bot_name=None, | 793 perf_bot_name=None, |
799 perf_build_number=None, | 794 perf_build_number=None, |
800 perf_builder_name=None, | 795 perf_builder_name=None, |
801 perf_master_name=None, | 796 perf_master_name=None, |
802 perf_revision=None, | 797 perf_revision=None, |
803 perf_x_value=None, | 798 perf_x_value=None, |
804 test_args=None, | 799 test_args=None, |
805 env_vars=None, | 800 env_vars=None, |
806 ): | 801 ): |
807 """Initializes an instance of the SimulatorXCTestRunner class. | 802 """Initializes an instance of the SimulatorXCTestRunner class. |
808 | 803 |
809 Args: | 804 Args: |
810 app_path: Full path to the compiled app to run. | 805 app_path: Full path to the compiled app to run. |
| 806 test_host: Name of the compiled test host app to run tests. |
| 807 test_project_dir: Directory of the dummy test project. |
811 xcode_version: Version of Xcode to use. | 808 xcode_version: Version of Xcode to use. |
812 gs_bucket: Google Storage bucket to upload test data to, or None if the | 809 gs_bucket: Google Storage bucket to upload test data to, or None if the |
813 test data should not be uploaded. | 810 test data should not be uploaded. |
814 perf_bot_name: Name of this bot as indicated to the perf dashboard. | 811 perf_bot_name: Name of this bot as indicated to the perf dashboard. |
815 perf_build_number: Build number to indicate to the perf dashboard. | 812 perf_build_number: Build number to indicate to the perf dashboard. |
816 perf_builder_name: Name of this builder as indicated to the perf | 813 perf_builder_name: Name of this builder as indicated to the perf |
817 dashboard. | 814 dashboard. |
818 perf_master_name: Name of the master as indicated to the perf dashboard. | 815 perf_master_name: Name of the master as indicated to the perf dashboard. |
819 perf_revision: Revision to indicate to the perf dashboard. | 816 perf_revision: Revision to indicate to the perf dashboard. |
820 perf_x_value: Value to use on the x axis for all data uploaded to the | 817 perf_x_value: Value to use on the x axis for all data uploaded to the |
(...skipping 12 matching lines...) Expand all Loading... |
833 perf_bot_name=perf_bot_name, | 830 perf_bot_name=perf_bot_name, |
834 perf_build_number=perf_build_number, | 831 perf_build_number=perf_build_number, |
835 perf_builder_name=perf_builder_name, | 832 perf_builder_name=perf_builder_name, |
836 perf_master_name=perf_master_name, | 833 perf_master_name=perf_master_name, |
837 perf_revision=perf_revision, | 834 perf_revision=perf_revision, |
838 perf_x_value=perf_x_value, | 835 perf_x_value=perf_x_value, |
839 test_args=test_args, | 836 test_args=test_args, |
840 xcode_version=xcode_version, | 837 xcode_version=xcode_version, |
841 ) | 838 ) |
842 self.app_path = os.path.abspath(app_path) | 839 self.app_path = os.path.abspath(app_path) |
| 840 self.test_host_name = test_host |
| 841 # Test target name is its host name without '_host' suffix. |
| 842 self.test_target_name = test_host.rsplit('_', 1)[0] |
| 843 self.test_project_dir = test_project_dir |
843 self.timeout = '120' | 844 self.timeout = '120' |
844 self.homedir = '' | 845 self.homedir = '' |
845 self.start_time = None | 846 self.start_time = None |
846 | 847 |
847 def TearDown(self): | 848 def TearDown(self): |
848 """Performs post-test tear down.""" | 849 """Performs post-test tear down.""" |
849 raise NotImplementedError | 850 raise NotImplementedError |
850 | 851 |
851 def HandleJsonFileWithPath(self, summary): | 852 def HandleJsonFileWithPath(self, summary): |
852 """Parse data in summarydir and send to perf dashboard.""" | 853 """Parse data in summarydir and send to perf dashboard.""" |
853 with open(summary) as jsonFile: | 854 with open(summary) as jsonFile: |
854 return json.load(jsonFile) | 855 return json.load(jsonFile) |
855 | 856 |
856 def GetLaunchEnvironment(self): | 857 def GetLaunchEnvironment(self): |
857 """Returns the environment which is used to run the xctest. | 858 """Returns the environment which is used to run the xctest. |
858 """ | 859 """ |
859 env = dict(os.environ, | 860 env = dict(os.environ, APP_TARGET_NAME=self.test_host_name, |
| 861 TEST_TARGET_NAME=self.test_target_name, |
860 NSUnbufferedIO='YES') | 862 NSUnbufferedIO='YES') |
861 return env | 863 return env |
862 | 864 |
863 def GetLaunchCommand(self, test_filter=None, blacklist=False): | 865 def GetLaunchCommand(self, test_filter=None, blacklist=False): |
864 """Returns the command which is used to launch the test. | 866 """Returns the command which is used to launch the test. |
865 | 867 |
866 Args: | 868 Args: |
867 test_filter: A list of tests to filter by, or None to mean all. | 869 test_filter: A list of tests to filter by, or None to mean all. |
868 blacklist: Whether to blacklist the elements of test_filter or not. Only | 870 blacklist: Whether to blacklist the elements of test_filter or not. Only |
869 works when test_filter is not None. | 871 works when test_filter is not None. |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1011 # At this point, all the tests have run, so used failed_tests to determine | 1013 # At this point, all the tests have run, so used failed_tests to determine |
1012 # the success/failure. | 1014 # the success/failure. |
1013 return not failed_tests | 1015 return not failed_tests |
1014 | 1016 |
1015 | 1017 |
1016 class SimulatorXCTestRunner(XCTestRunner): | 1018 class SimulatorXCTestRunner(XCTestRunner): |
1017 """Class for running xctests on an iOS simulator.""" | 1019 """Class for running xctests on an iOS simulator.""" |
1018 def __init__( | 1020 def __init__( |
1019 self, | 1021 self, |
1020 app_path, | 1022 app_path, |
1021 xctest_path, | 1023 test_host, |
1022 iossim_path, | 1024 test_project_dir, |
1023 platform, | 1025 platform, |
1024 version, | 1026 version, |
1025 xcode_version=None, | 1027 xcode_version=None, |
1026 gs_bucket=None, | 1028 gs_bucket=None, |
1027 perf_bot_name=None, | 1029 perf_bot_name=None, |
1028 perf_build_number=None, | 1030 perf_build_number=None, |
1029 perf_builder_name=None, | 1031 perf_builder_name=None, |
1030 perf_master_name=None, | 1032 perf_master_name=None, |
1031 perf_revision=None, | 1033 perf_revision=None, |
1032 perf_x_value=None, | 1034 perf_x_value=None, |
1033 test_args=None, | 1035 test_args=None, |
1034 env_vars=None, | 1036 env_vars=None, |
1035 ): | 1037 ): |
1036 """Initializes an instance of the SimulatorXCTestRunner class. | 1038 """Initializes an instance of the SimulatorXCTestRunner class. |
1037 | 1039 |
1038 Args: | 1040 Args: |
1039 app_path: Full path to the compiled app to run. | 1041 app_path: Full path to the compiled app to run. |
1040 iossim_path: Full path to the iossim executable to launch. | 1042 test_host: Name of the compiled test host app to run tests. |
1041 xctest_path: Full path to the compiled test bundle. | 1043 test_project_dir: Directory of the dummy test project. |
1042 platform: The platform to simulate. Supported values can be found by | 1044 platform: The platform to simulate. Supported values can be found by |
1043 running 'xcodebuild -list'. e.g. 'iPhone 5', 'iPhone 5s'. | 1045 running 'xcodebuild -list'. e.g. 'iPhone 5', 'iPhone 5s'. |
1044 version: The iOS version the simulator should be running. Supported values | 1046 version: The iOS version the simulator should be running. Supported values |
1045 can be found by running 'xcodebuild -list'. e.g. '8.0', '7.1'. | 1047 can be found by running 'xcodebuild -list'. e.g. '8.0', '7.1'. |
1046 xcode_version: Version of Xcode to use. | 1048 xcode_version: Version of Xcode to use. |
1047 gs_bucket: Google Storage bucket to upload test data to, or None if the | 1049 gs_bucket: Google Storage bucket to upload test data to, or None if the |
1048 test data should not be uploaded. | 1050 test data should not be uploaded. |
1049 perf_bot_name: Name of this bot as indicated to the perf dashboard. | 1051 perf_bot_name: Name of this bot as indicated to the perf dashboard. |
1050 perf_build_number: Build number to indicate to the perf dashboard. | 1052 perf_build_number: Build number to indicate to the perf dashboard. |
1051 perf_builder_name: Name of this builder as indicated to the perf | 1053 perf_builder_name: Name of this builder as indicated to the perf |
1052 dashboard. | 1054 dashboard. |
1053 perf_master_name: Name of the master as indicated to the perf dashboard. | 1055 perf_master_name: Name of the master as indicated to the perf dashboard. |
1054 perf_revision: Revision to indicate to the perf dashboard. | 1056 perf_revision: Revision to indicate to the perf dashboard. |
1055 perf_x_value: Value to use on the x axis for all data uploaded to the | 1057 perf_x_value: Value to use on the x axis for all data uploaded to the |
1056 perf dashboard. | 1058 perf dashboard. |
1057 test_args: Arguments to pass when launching the test. | 1059 test_args: Arguments to pass when launching the test. |
1058 env_vars: Environment variables to set when launching the test. | 1060 env_vars: Environment variables to set when launching the test. |
1059 | 1061 |
1060 Raises: | 1062 Raises: |
1061 SimulatorNotFoundError: If the given iossim path cannot be found. | 1063 SimulatorNotFoundError: If the given iossim path cannot be found. |
1062 """ | 1064 """ |
1063 super(SimulatorXCTestRunner, self).__init__( | 1065 super(SimulatorXCTestRunner, self).__init__( |
1064 app_path, | 1066 app_path, |
| 1067 test_host, |
| 1068 test_project_dir, |
1065 env_vars=env_vars, | 1069 env_vars=env_vars, |
1066 gs_bucket=gs_bucket, | 1070 gs_bucket=gs_bucket, |
1067 perf_bot_name=perf_bot_name, | 1071 perf_bot_name=perf_bot_name, |
1068 perf_build_number=perf_build_number, | 1072 perf_build_number=perf_build_number, |
1069 perf_builder_name=perf_builder_name, | 1073 perf_builder_name=perf_builder_name, |
1070 perf_master_name=perf_master_name, | 1074 perf_master_name=perf_master_name, |
1071 perf_revision=perf_revision, | 1075 perf_revision=perf_revision, |
1072 perf_x_value=perf_x_value, | 1076 perf_x_value=perf_x_value, |
1073 test_args=test_args, | 1077 test_args=test_args, |
1074 xcode_version=xcode_version, | 1078 xcode_version=xcode_version, |
1075 ) | 1079 ) |
1076 | |
1077 if not os.path.exists(iossim_path): | |
1078 raise SimulatorNotFoundError(iossim_path) | |
1079 | |
1080 if not os.path.exists(xctest_path): | |
1081 raise XctestNotFoundError(xctest_path) | |
1082 | |
1083 self.iossim_path = iossim_path | |
1084 self.xctest_path = xctest_path | |
1085 self.platform = platform | 1080 self.platform = platform |
1086 self.version = version | 1081 self.version = version |
1087 | 1082 |
1088 def UploadTestData(self): | 1083 def UploadTestData(self): |
1089 """Uploads the contents of the test's Documents directory. | 1084 """Uploads the contents of the test's Documents directory. |
1090 | 1085 |
1091 Returns: | 1086 Returns: |
1092 True if test data was uploaded, False otherwise. | 1087 True if test data was uploaded, False otherwise. |
1093 """ | 1088 """ |
1094 if not self.gs_bucket: | 1089 if not self.gs_bucket: |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1263 """Returns the invocation command which is used to run the test. | 1258 """Returns the invocation command which is used to run the test. |
1264 | 1259 |
1265 Args: | 1260 Args: |
1266 test_filter: A list of tests to filter by, or None to mean all. | 1261 test_filter: A list of tests to filter by, or None to mean all. |
1267 blacklist: Whether to blacklist the elements of test_filter or not. Only | 1262 blacklist: Whether to blacklist the elements of test_filter or not. Only |
1268 works when test_filter is not None. | 1263 works when test_filter is not None. |
1269 | 1264 |
1270 Returns: | 1265 Returns: |
1271 A list whose elements are the args representing the command. | 1266 A list whose elements are the args representing the command. |
1272 """ | 1267 """ |
| 1268 built_dir = os.path.split(self.app_path)[0] |
| 1269 |
1273 cmd = [ | 1270 cmd = [ |
1274 self.iossim_path, | 1271 'xcodebuild', 'test-without-building', |
1275 '-d', self.platform, | 1272 'BUILT_PRODUCTS_DIR=%s' % built_dir, |
1276 '-s', self.version, | 1273 '-project', self.test_project_dir, |
1277 self.app_path, | 1274 '-scheme','TestProject', |
1278 self.xctest_path | 1275 '-destination','platform=iOS Simulator,name=%s,OS=%s' |
| 1276 % (self.platform, self.version), |
| 1277 '-archivePath', self.homedir, |
| 1278 'APP_TARGET_NAME=%s' % self.test_host_name, |
| 1279 'TEST_TARGET_NAME=%s' % self.test_target_name, |
| 1280 'NSUnbufferedIO=YES' |
1279 ] | 1281 ] |
1280 return cmd | 1282 return cmd |
1281 | 1283 |
1282 @TestRunner.RequireTearDown | 1284 @TestRunner.RequireTearDown |
1283 def Launch(self, *args, **kwargs): | 1285 def Launch(self, *args, **kwargs): |
1284 """Launches the test.""" | 1286 """Launches the test.""" |
1285 self.SetUp() | 1287 self.SetUp() |
1286 | 1288 |
1287 result = self._Run( | 1289 result = self._Run( |
1288 self.GetLaunchCommand(), self.GetLaunchEnvironment(), *args, **kwargs) | 1290 self.GetLaunchCommand(), self.GetLaunchEnvironment(), *args, **kwargs) |
(...skipping 15 matching lines...) Expand all Loading... |
1304 self.GetLaunchCommand(), self.GetLaunchEnvironment(), *args, **kwargs) | 1306 self.GetLaunchCommand(), self.GetLaunchEnvironment(), *args, **kwargs) |
1305 | 1307 |
1306 return self.RunAllTests(result, *args, **kwargs) | 1308 return self.RunAllTests(result, *args, **kwargs) |
1307 | 1309 |
1308 | 1310 |
1309 class DeviceXCTestRunner(XCTestRunner): | 1311 class DeviceXCTestRunner(XCTestRunner): |
1310 """Class for running xctests on an iOS device.""" | 1312 """Class for running xctests on an iOS device.""" |
1311 def __init__( | 1313 def __init__( |
1312 self, | 1314 self, |
1313 app_path, | 1315 app_path, |
1314 xctest_path, | 1316 test_host, |
1315 xcodeproj_path, | 1317 test_project_dir, |
1316 xcode_version=None, | 1318 xcode_version=None, |
1317 gs_bucket=None, | 1319 gs_bucket=None, |
1318 perf_bot_name=None, | 1320 perf_bot_name=None, |
1319 perf_build_number=None, | 1321 perf_build_number=None, |
1320 perf_builder_name=None, | 1322 perf_builder_name=None, |
1321 perf_master_name=None, | 1323 perf_master_name=None, |
1322 perf_revision=None, | 1324 perf_revision=None, |
1323 perf_x_value=None, | 1325 perf_x_value=None, |
1324 test_args=None, | 1326 test_args=None, |
1325 env_vars=None, | 1327 env_vars=None, |
(...skipping 19 matching lines...) Expand all Loading... |
1345 env_vars: Environment variables to set when launching the test. | 1347 env_vars: Environment variables to set when launching the test. |
1346 | 1348 |
1347 Raises: | 1349 Raises: |
1348 DeviceDetectionError: If this machine does not have exactly one device | 1350 DeviceDetectionError: If this machine does not have exactly one device |
1349 connected. Having more than one device connected causes problems when | 1351 connected. Having more than one device connected causes problems when |
1350 trying to issue commands to any one device, which interfere with | 1352 trying to issue commands to any one device, which interfere with |
1351 installing and running the test app. | 1353 installing and running the test app. |
1352 """ | 1354 """ |
1353 super(DeviceXCTestRunner, self).__init__( | 1355 super(DeviceXCTestRunner, self).__init__( |
1354 app_path, | 1356 app_path, |
| 1357 test_host, |
| 1358 test_project_dir, |
1355 env_vars=env_vars, | 1359 env_vars=env_vars, |
1356 gs_bucket=gs_bucket, | 1360 gs_bucket=gs_bucket, |
1357 perf_bot_name=perf_bot_name, | 1361 perf_bot_name=perf_bot_name, |
1358 perf_build_number=perf_build_number, | 1362 perf_build_number=perf_build_number, |
1359 perf_builder_name=perf_builder_name, | 1363 perf_builder_name=perf_builder_name, |
1360 perf_master_name=perf_master_name, | 1364 perf_master_name=perf_master_name, |
1361 perf_revision=perf_revision, | 1365 perf_revision=perf_revision, |
1362 perf_x_value=perf_x_value, | 1366 perf_x_value=perf_x_value, |
1363 test_args=test_args, | 1367 test_args=test_args, |
1364 xcode_version=xcode_version, | 1368 xcode_version=xcode_version, |
1365 ) | 1369 ) |
1366 # The scheme name is the app name without the '.app' suffix. | |
1367 app_name = os.path.split(self.app_path)[1] | |
1368 self.scheme_name = app_name.split('.', 1)[0] | |
1369 self.xcodeproj_path = xcodeproj_path | |
1370 self.cfbundleid = utils.call( | 1370 self.cfbundleid = utils.call( |
1371 utils.PLIST_BUDDY, | 1371 utils.PLIST_BUDDY, |
1372 '-c', 'Print:CFBundleIdentifier', | 1372 '-c', 'Print:CFBundleIdentifier', |
1373 os.path.join(self.app_path, 'Info.plist'), | 1373 os.path.join(self.app_path, 'Info.plist'), |
1374 ).stdout[0] | 1374 ).stdout[0] |
1375 | 1375 |
1376 call_result = utils.call('idevice_id', '--list') | 1376 call_result = utils.call('idevice_id', '--list') |
1377 self.device_id = call_result.stdout[0] | 1377 self.device_id = call_result.stdout[0] |
1378 | 1378 |
1379 if len(call_result.stdout) != 1: | 1379 if len(call_result.stdout) != 1: |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1420 """Returns the invocation command which is used to run the test. | 1420 """Returns the invocation command which is used to run the test. |
1421 | 1421 |
1422 Args: | 1422 Args: |
1423 test_filter: A list of tests to filter by, or None to mean all. | 1423 test_filter: A list of tests to filter by, or None to mean all. |
1424 blacklist: Whether to blacklist the elements of test_filter or not. Only | 1424 blacklist: Whether to blacklist the elements of test_filter or not. Only |
1425 works when test_filter is not None. | 1425 works when test_filter is not None. |
1426 | 1426 |
1427 Returns: | 1427 Returns: |
1428 A list whose elements are the args representing the command. | 1428 A list whose elements are the args representing the command. |
1429 """ | 1429 """ |
| 1430 built_dir = os.path.split(self.app_path)[0] |
| 1431 |
1430 cmd = [ | 1432 cmd = [ |
1431 'xcodebuild', 'test-without-building', | 1433 'xcodebuild', 'test-without-building', |
1432 '-project', self.xcodeproj_path, | 1434 'BUILT_PRODUCTS_DIR=%s' % built_dir, |
1433 '-scheme', self.scheme_name, | 1435 'CONFIGURATION_BUILD_DIR=%s' % built_dir, |
1434 '-destination', 'id=%s' % self.device_id | 1436 '-project', self.test_project_dir, |
| 1437 '-configuration', 'iphoneos', |
| 1438 '-scheme', 'TestProject', |
| 1439 '-destination','id=%s' % self.device_id, |
| 1440 'APP_TARGET_NAME=%s' % self.test_host_name, |
| 1441 'TEST_TARGET_NAME=%s' % self.test_target_name, |
| 1442 'NSUnbufferedIO=YES' |
1435 ] | 1443 ] |
1436 return cmd | 1444 return cmd |
1437 | 1445 |
1438 @TestRunner.RequireTearDown | 1446 @TestRunner.RequireTearDown |
1439 def Launch(self, *args, **kwargs): | 1447 def Launch(self, *args, **kwargs): |
1440 """Launches the test.""" | 1448 """Launches the test.""" |
1441 self.InstallApp() | 1449 self.InstallApp() |
1442 | 1450 |
1443 result = self._Run( | 1451 result = self._Run( |
1444 self.GetLaunchCommand(), self.GetLaunchEnvironment(), *args, **kwargs) | 1452 self.GetLaunchCommand(), self.GetLaunchEnvironment(), *args, **kwargs) |
1445 | 1453 |
1446 if result.crashed and not result.crashed_test: | 1454 if result.crashed and not result.crashed_test: |
1447 # If the app crashed, but there is no specific test which crashed, | 1455 # If the app crashed, but there is no specific test which crashed, |
1448 # then the app must have failed to even start. Try one more time. | 1456 # then the app must have failed to even start. Try one more time. |
1449 self.Print( | 1457 self.Print( |
1450 '%s appears to have crashed on startup. Retrying...' % self.app_name, | 1458 '%s appears to have crashed on startup. Retrying...' % self.app_name, |
1451 blank_lines=2, | 1459 blank_lines=2, |
1452 time_to_sleep=5, | 1460 time_to_sleep=5, |
1453 ) | 1461 ) |
1454 | 1462 |
1455 # Uninstall and re-install the app. | 1463 # Uninstall and re-install the app. |
1456 self.UninstallApp() | 1464 self.UninstallApp() |
1457 self.InstallApp() | 1465 self.InstallApp() |
1458 | 1466 |
1459 result = self._Run( | 1467 result = self._Run( |
1460 self.GetLaunchCommand(), self.GetLaunchEnvironment(), *args, **kwargs) | 1468 self.GetLaunchCommand(), self.GetLaunchEnvironment(), *args, **kwargs) |
1461 | 1469 |
1462 return self.RunAllTests(result, *args, **kwargs) | 1470 return self.RunAllTests(result, *args, **kwargs) |
OLD | NEW |