| #!/usr/bin/env python |
| # |
| # Copyright 2017 Google Inc. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| """Runs all Franky test cases for a given channel.""" |
| |
| import argparse |
| import logging |
| import os |
| |
| from actions import system |
| from appium_util import appium_driver_util |
| from appium_util import path_constants |
| import device_info |
| import download_testcases_csv |
| import oauth2client.tools as tools |
| from test_util import franky_testsuite |
| from utilities import gsutil_download |
| from utilities import util |
| |
| |
| # App file extensions. |
| _APP_EXTENSION = { |
| appium_driver_util.IOS: '.app', |
| appium_driver_util.ANDROID: '.apk', |
| } |
| |
| # A list to keep track of temporary files created. |
| _TEMPFILES = util.TempFiles() |
| |
| # Prefix of Monochrome[Canary|Dev|Beta|Stable].apk. |
| _PREFIX_MONOCHROME = 'Monochrome' |
| |
| |
| def _ParseArgs(passed_args=None): |
| """Parses the command line arguments. |
| |
| |
| Args: |
| passed_args: a list of args. |
| |
| Returns: |
| The parsed commandline arguments. |
| """ |
| html = gsutil_download.HTML |
| json = gsutil_download.JSON |
| arg_parser = argparse.ArgumentParser( |
| description='Runs Franky test cases on a Chrome Channel.', |
| parents=[tools.argparser]) |
| arg_parser.add_argument( |
| 'channel', |
| choices=[ |
| path_constants.BETA, path_constants.CANARY, path_constants.DEV, |
| path_constants.STABLE |
| ], |
| help='The Chrome channel to run test cases against.') |
| arg_parser.add_argument( |
| 'platform', |
| choices=[appium_driver_util.IOS, appium_driver_util.ANDROID], |
| help='The platform to run tests against.') |
| arg_parser.add_argument( |
| '-i', |
| '--app-intent', |
| default=None, |
| help='A string specifying which intent to use.') |
| arg_parser.add_argument( |
| '-a', |
| '--app-path', |
| help='The full path to the .app bundle to be tested. ' |
| 'The default location is the current directory.') |
| arg_parser.add_argument( |
| '--appium-command', |
| default=appium_driver_util.ChooseAppiumClient(), |
| help='The command to invoke appium server. A special value of NONE ' |
| 'disables Appium invocation and relies on an already running server. ' |
| 'Default: "%(default)s".') |
| arg_parser.add_argument( |
| '-s', |
| '--appium-dir-path', |
| default=appium_driver_util.ChooseAppiumDirPath(), |
| help='The full path to appium server directory. A special value NONE ' |
| 'will keep it unset. The default location is %(default)s.') |
| arg_parser.add_argument( |
| '-p', |
| '--package-pull', |
| help='The package name of installed apk on the device ' |
| 'that will be pulled.') |
| arg_parser.add_argument( |
| '-c', |
| '--copy-to-cloud-storage', |
| action='store_true', |
| default=False, |
| help='Copy generated HTML reports to ' |
| 'Google Cloud Storage. Run "gcloud auth" before' |
| ' first use.') |
| arg_parser.add_argument( |
| '--prerun-script', |
| default=None, |
| help='A string set in quotes of a script with arguments to be ran prior' |
| ' to test execution.') |
| arg_parser.add_argument( |
| '-gs', |
| '--gsutil-download', |
| default=None, |
| help='A version of Chrome to download or "Latest."') |
| arg_parser.add_argument( |
| '-d', |
| '--host-address', |
| action='store_true', |
| default='127.0.0.1', |
| help='Default Host for Appium ' |
| 'server.') |
| arg_parser.add_argument( |
| '--appium-port', |
| default='4723', |
| help='Port for Appium server.') |
| arg_parser.add_argument( |
| '-n', |
| '--no-retry', |
| action='store_true', |
| default=False, |
| help='Do not rerun a test.' |
| 'If not set, a test will rerun after it fails.') |
| arg_parser.add_argument( |
| '-r', |
| '--report-format', |
| choices=[html, json], |
| default=html, |
| help='Generate a json or html report ' |
| 'out of the test results.') |
| arg_parser.add_argument( |
| '-sc', |
| '--screen-capture', |
| action='store_true', |
| default=False, |
| help='Store screenshots with failures or not. Default is False.') |
| arg_parser.add_argument( |
| '--skip-reset', |
| action='store_true', |
| default=False, |
| help='Do not reset app between ' |
| 'test cases.') |
| arg_parser.add_argument( |
| '-f', |
| '--test-filter', |
| default=None, |
| help='A comma separated string of numbers indicating' |
| ' which tests to run in the suite.') |
| arg_parser.add_argument( |
| '-t', |
| '--test-suite', |
| action='append', |
| help='Test suite file(s) to run; can be a glob. Multiple arguments ' |
| 'add up. Default are all files matching "*<channel>*.csv" in CWD.' |
| 'File type is determined by extension: .csv is CSV, .txt is text proto.') |
| arg_parser.add_argument( |
| '--report-folder', |
| default=None, |
| help='The full path to the directory where report will store. ' |
| 'If not specified, folder of 1st test_suite will be report_folder.') |
| arg_parser.add_argument( |
| '--csv', |
| default=None, |
| help='Download the specified workbook as a CSV file. To download multiple' |
| 'workbooks use comma as delimiter. The format of parameter is' |
| '"spreadsheet_key, workbook_id1,..., workbook_idN"') |
| arg_parser.add_argument( |
| '--use-prebuilt-wda', |
| action='store_true', |
| default=False, |
| help='Do not rebuild the WebDriverAgent app.') |
| arg_parser.add_argument( |
| '-ui2', |
| '--use-uiautomator2', |
| action='store_true', |
| default=False, |
| help='Use uiautomator2.') |
| arg_parser.add_argument( |
| '-v', |
| '--verbose', |
| action='store_true', |
| default=False, |
| help='Increase test output verbosity.') |
| arg_parser.add_argument( |
| '--webview', |
| action='store_true', |
| default=False, |
| help='Run webview test setup steps.') |
| arg_parser.add_argument( |
| '--xcconfig', |
| metavar='FILE', |
| help='XCode config for xcodebuild launching WDA.') |
| arg_parser.add_argument( |
| '-id', '--device-id', help='The device ID/serial number to run test on.') |
| arg_parser.add_argument( |
| '-flags', '--exp-flags', action='append', |
| help='[iOS ONLY] List of command line flags that need to be ' |
| 'enabled/disabled before launching the Chrome App' |
| 'Example1: -flags=--enable-features=F1,F2' |
| 'Example2: -flags=--enabled-features=F1,--disable-features=F2') |
| |
| args = arg_parser.parse_args(passed_args) |
| |
| if args.platform == appium_driver_util.ANDROID: |
| devices = util.GetAndroidDeviceSerialNumbers() |
| elif args.platform == appium_driver_util.IOS: |
| devices = util.GetIOSDeviceUDIDNumbers() |
| if not devices: |
| logging.error('No device connected to machine') |
| elif not args.device_id: |
| args.device_id = devices[0] |
| elif args.device_id not in devices: |
| logging.error('Device with ID %s not found in connected devices %s' % |
| (args.device_id, devices)) |
| |
| if args.appium_command == 'NONE': |
| args.appium_command = None |
| else: |
| args.appium_command = args.appium_command.split(' ') |
| if args.appium_dir_path == 'NONE': |
| args.appium_dir_path = None |
| |
| webview_package = system.CHANNEL_TO_WEBVIEW_PACKAGE[args.channel] |
| |
| if args.prerun_script: |
| util.ExecuteProcess(util.ExpandPaths(args.prerun_script.split(' '))) |
| # TODO(bjoyce): Remove when prerun script works for webview. |
| if args.gsutil_download: |
| if args.webview: |
| webview_apk = gsutil_download.DownloadAndroidApp( |
| args.gsutil_download, args.channel, args.device_id, True) |
| # Uninstall Monochrome apk first if it is already installed. |
| if _PREFIX_MONOCHROME in webview_apk: |
| util.ADBUninstallPackage(webview_package, args.device_id) |
| out = util.ADBInstallPackage(webview_apk, args.device_id) |
| if 'Success' in out: |
| print '%s installation succeeded.' % webview_apk |
| else: |
| print '%s installation failed.' % webview_apk |
| # It is Clank test then downloaded app is the test app. |
| elif args.platform == appium_driver_util.ANDROID: |
| args.app_path = gsutil_download.DownloadAndroidApp( |
| args.gsutil_download, args.channel, args.device_id, False) |
| else: |
| args.app_path = gsutil_download.DownloadIOSApp( |
| args.gsutil_download, args.channel) |
| if args.app_path: |
| _TEMPFILES.Add(args.app_path) |
| |
| if args.webview: |
| api_level = device_info.GetAndroidAPILevel(args.device_id) |
| exists_package = util.CheckPackage(webview_package, args.device_id) |
| if api_level >= device_info.ANDROID_N_API_VERSION and exists_package: |
| cmd = [ |
| 'shell', 'cmd', 'webviewupdate', 'set-webview-implementation', |
| webview_package |
| ] |
| util.RunADBProcess(cmd, args.device_id) |
| if args.package_pull: |
| args.app_path = gsutil_download.PullApp(args.package_pull, args.device_id) |
| _TEMPFILES.Add(args.app_path) |
| if not args.app_path: |
| args.app_path = os.path.abspath(args.channel + |
| _APP_EXTENSION[args.platform]) |
| if not args.test_suite: |
| if args.csv: |
| spreadsheet_data = [el.strip() for el in args.csv.split(',')] |
| if len(spreadsheet_data) < 2: |
| raise franky_testsuite.ArgumentError(' '.join([ |
| '--csv has to have at least 2 comma separated parameters:', |
| '"spreadsheet_key, workbook_id"'])) |
| args.test_suite = download_testcases_csv.DownloadCSVFromGoogleSheet( |
| args, spreadsheet_data[0], set(spreadsheet_data[1:])) |
| for filename in args.test_suite: |
| _TEMPFILES.Add(filename) |
| else: |
| args.test_suite = ['*%s*.csv' % args.channel] |
| |
| if not args.report_folder: |
| args.report_folder = os.path.split(args.test_suite[0])[0] |
| |
| return args |
| |
| |
| def main(passed_args=None): |
| try: |
| franky_testsuite.ExecutTests(_ParseArgs(passed_args)) |
| finally: |
| _TEMPFILES.DeleteAll() |
| |
| |
| if __name__ == '__main__': |
| main() |