OLD | NEW |
---|---|
1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Test runners for iOS.""" | 5 """Test runners for iOS.""" |
6 | 6 |
7 import argparse | 7 import argparse |
8 import collections | 8 import collections |
9 import errno | 9 import errno |
10 import os | 10 import os |
11 import plistlib | |
11 import shutil | 12 import shutil |
12 import subprocess | 13 import subprocess |
13 import sys | 14 import sys |
14 import tempfile | 15 import tempfile |
15 import time | 16 import time |
16 | 17 |
17 import find_xcode | 18 import find_xcode |
18 import gtest_utils | 19 import gtest_utils |
19 import xctest_utils | 20 import xctest_utils |
20 | 21 |
21 | 22 |
22 DERIVED_DATA = os.path.expanduser('~/Library/Developer/Xcode/DerivedData') | 23 DERIVED_DATA = os.path.expanduser('~/Library/Developer/Xcode/DerivedData') |
23 | 24 |
24 | 25 |
25 XCTEST_PROJECT = os.path.abspath(os.path.join( | |
26 os.path.dirname(__file__), | |
27 'TestProject', | |
28 'TestProject.xcodeproj', | |
29 )) | |
30 | |
31 XCTEST_SCHEME = 'TestProject' | |
32 | |
33 | |
34 class Error(Exception): | 26 class Error(Exception): |
35 """Base class for errors.""" | 27 """Base class for errors.""" |
36 pass | 28 pass |
37 | 29 |
38 | 30 |
39 class TestRunnerError(Error): | 31 class TestRunnerError(Error): |
40 """Base class for TestRunner-related errors.""" | 32 """Base class for TestRunner-related errors.""" |
41 pass | 33 pass |
42 | 34 |
43 | 35 |
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
650 out_dir, | 642 out_dir, |
651 env_vars=env_vars, | 643 env_vars=env_vars, |
652 retries=retries, | 644 retries=retries, |
653 test_args=test_args, | 645 test_args=test_args, |
654 xctest=xctest, | 646 xctest=xctest, |
655 ) | 647 ) |
656 | 648 |
657 self.udid = subprocess.check_output(['idevice_id', '--list']).rstrip() | 649 self.udid = subprocess.check_output(['idevice_id', '--list']).rstrip() |
658 if len(self.udid.splitlines()) != 1: | 650 if len(self.udid.splitlines()) != 1: |
659 raise DeviceDetectionError(self.udid) | 651 raise DeviceDetectionError(self.udid) |
652 if xctest: | |
653 self.xctestrun_file = tempfile.mkstemp()[1] | |
654 self.xctestrun_data = { | |
655 'TestTargetName': { | |
656 'IsAppHostedTestBundle': True, | |
657 'TestBundlePath': '%s' % self.xctest_path, | |
658 'TestHostPath': '%s' % self.app_path, | |
659 'TestingEnvironmentVariables': { | |
660 'DYLD_INSERT_LIBRARIES': | |
661 '__PLATFORMS__/iPhoneOS.platform/Developer/Library/' | |
662 'PrivateFrameworks/IDEBundleInjection.framework/IDEBundleInjection', | |
663 'DYLD_LIBRARY_PATH': | |
664 '__PLATFORMS__/iPhoneOS.platform/Developer/Library', | |
665 'DYLD_FRAMEWORK_PATH': | |
666 '__PLATFORMS__/iPhoneOS.platform/Developer/Library/Frameworks', | |
667 'XCInjectBundleInto':'__TESTHOST__/%s' % self.app_name | |
668 } | |
669 } | |
670 } | |
660 | 671 |
661 def uninstall_apps(self): | 672 def uninstall_apps(self): |
662 """Uninstalls all apps found on the device.""" | 673 """Uninstalls all apps found on the device.""" |
663 for app in subprocess.check_output( | 674 for app in subprocess.check_output( |
664 ['idevicefs', '--udid', self.udid, 'ls', '@']).splitlines(): | 675 ['idevicefs', '--udid', self.udid, 'ls', '@']).splitlines(): |
665 subprocess.check_call( | 676 subprocess.check_call( |
666 ['ideviceinstaller', '--udid', self.udid, '--uninstall', app]) | 677 ['ideviceinstaller', '--udid', self.udid, '--uninstall', app]) |
667 | 678 |
668 def install_app(self): | 679 def install_app(self): |
669 """Installs the app.""" | 680 """Installs the app.""" |
670 subprocess.check_call( | 681 subprocess.check_call( |
671 ['ideviceinstaller', '--udid', self.udid, '--install', self.app_path]) | 682 ['ideviceinstaller', '--udid', self.udid, '--install', self.app_path]) |
672 | 683 |
673 def set_up(self): | 684 def set_up(self): |
674 """Performs setup actions which must occur prior to every test launch.""" | 685 """Performs setup actions which must occur prior to every test launch.""" |
675 self.uninstall_apps() | 686 # self.uninstall_apps() |
676 self.wipe_derived_data() | 687 # self.wipe_derived_data() |
677 self.install_app() | 688 # self.install_app() |
huangml1
2017/04/07 23:54:01
sorry.
| |
678 | 689 |
679 def extract_test_data(self): | 690 def extract_test_data(self): |
680 """Extracts data emitted by the test.""" | 691 """Extracts data emitted by the test.""" |
681 try: | 692 try: |
682 subprocess.check_call([ | 693 subprocess.check_call([ |
683 'idevicefs', | 694 'idevicefs', |
684 '--udid', self.udid, | 695 '--udid', self.udid, |
685 'pull', | 696 'pull', |
686 '@%s/Documents' % self.cfbundleid, | 697 '@%s/Documents' % self.cfbundleid, |
687 os.path.join(self.out_dir, 'Documents'), | 698 os.path.join(self.out_dir, 'Documents'), |
(...skipping 28 matching lines...) Expand all Loading... | |
716 | 727 |
717 Args: | 728 Args: |
718 test_filter: List of test cases to filter. | 729 test_filter: List of test cases to filter. |
719 invert: Whether to invert the filter or not. Inverted, the filter will | 730 invert: Whether to invert the filter or not. Inverted, the filter will |
720 match everything except the given test cases. | 731 match everything except the given test cases. |
721 | 732 |
722 Returns: | 733 Returns: |
723 A list of strings forming the command to launch the test. | 734 A list of strings forming the command to launch the test. |
724 """ | 735 """ |
725 if self.xctest_path: | 736 if self.xctest_path: |
737 if test_filter: | |
738 if invert: | |
739 self.xctestrun_data['TestTargetName'].update( | |
740 {'SkipTestIdentifiers': test_filter}) | |
741 else: | |
742 self.xctestrun_data['TestTargetName'].update( | |
743 {'OnlyTestIdentifiers': test_filter}) | |
744 plistlib.writePlist(self.xctestrun_data, self.xctestrun_file) | |
726 return [ | 745 return [ |
727 'xcodebuild', | 746 'xcodebuild', |
728 'test-without-building', | 747 'test-without-building', |
729 'BUILT_PRODUCTS_DIR=%s' % os.path.dirname(self.app_path), | 748 '-xctestrun', self.xctestrun_file, |
730 '-destination', 'id=%s' % self.udid, | 749 '-destination', 'id=%s' % self.udid, |
731 '-project', XCTEST_PROJECT, | |
732 '-scheme', XCTEST_SCHEME, | |
733 ] | 750 ] |
734 | 751 |
735 cmd = [ | 752 cmd = [ |
736 'idevice-app-runner', | 753 'idevice-app-runner', |
737 '--udid', self.udid, | 754 '--udid', self.udid, |
738 '--start', self.cfbundleid, | 755 '--start', self.cfbundleid, |
739 ] | 756 ] |
740 args = [] | 757 args = [] |
741 | 758 |
742 if test_filter: | 759 if test_filter: |
(...skipping 20 matching lines...) Expand all Loading... | |
763 """ | 780 """ |
764 env = super(DeviceTestRunner, self).get_launch_env() | 781 env = super(DeviceTestRunner, self).get_launch_env() |
765 if self.xctest_path: | 782 if self.xctest_path: |
766 env['NSUnbufferedIO'] = 'YES' | 783 env['NSUnbufferedIO'] = 'YES' |
767 # e.g. ios_web_shell_egtests | 784 # e.g. ios_web_shell_egtests |
768 env['APP_TARGET_NAME'] = os.path.splitext( | 785 env['APP_TARGET_NAME'] = os.path.splitext( |
769 os.path.basename(self.app_path))[0] | 786 os.path.basename(self.app_path))[0] |
770 # e.g. ios_web_shell_egtests_module | 787 # e.g. ios_web_shell_egtests_module |
771 env['TEST_TARGET_NAME'] = env['APP_TARGET_NAME'] + '_module' | 788 env['TEST_TARGET_NAME'] = env['APP_TARGET_NAME'] + '_module' |
772 return env | 789 return env |
OLD | NEW |