def __init__(self, args, context, history_id, gcs_results_root): """Construct a MatrixCreator to be used to create a single test matrix. Args: args: an argparse namespace. All the arguments that were provided to this gcloud command invocation (i.e. group and command arguments combined). context: {str:obj} dict containing the gcloud command context, which includes the Testing API client+messages libs generated by Apitools. history_id: {str} A history ID to publish Tool Results to. gcs_results_root: the root dir for a matrix within the GCS results bucket. """ self._project = util.GetProject() self._args = args self._history_id = history_id self._gcs_results_root = gcs_results_root self._client = context['testing_client'] self._messages = context['testing_messages']
def Run(self, args): """Run the 'gcloud test run' command to invoke a test in Firebase Test Lab. Args: args: an argparse namespace. All the arguments that were provided to this command invocation (i.e. group and command arguments combined). Returns: One of: - a list of TestOutcome tuples (if ToolResults are available). - a URL string pointing to the user's results in ToolResults or GCS. """ device_catalog = util.GetAndroidCatalog(self.context) arg_manager.AndroidArgsManager(device_catalog).Prepare(args) project = util.GetProject() tr_client = self.context['toolresults_client'] tr_messages = self.context['toolresults_messages'] storage_client = self.context['storage_client'] bucket_ops = results_bucket.ResultsBucketOps(project, args.results_bucket, _UniqueGcsObjectName(), tr_client, tr_messages, storage_client) bucket_ops.UploadFileToGcs(args.app) if args.test: bucket_ops.UploadFileToGcs(args.test) for obb_file in (args.obb_files or []): bucket_ops.UploadFileToGcs(obb_file) bucket_ops.LogGcsResultsUrl() tr_history_picker = history_picker.ToolResultsHistoryPicker( project, tr_client, tr_messages) history_name = PickHistoryName(args) history_id = tr_history_picker.GetToolResultsHistoryId(history_name) matrix = matrix_creator.CreateMatrix(args, self.context, history_id, bucket_ops.gcs_results_root) monitor = matrix_ops.MatrixMonitor(matrix.testMatrixId, args.type, self.context) with ctrl_c_handler.CancellableTestSection(monitor): supported_executions = monitor.HandleUnsupportedExecutions(matrix) tr_ids = tool_results.GetToolResultsIds(matrix, monitor) url = tool_results.CreateToolResultsUiUrl(project, tr_ids) log.status.Print('') if args. async: return url log.status.Print( 'Test results will be streamed to [{0}].'.format(url)) # If we have exactly one testExecution, show detailed progress info. if len(supported_executions) == 1: monitor.MonitorTestExecutionProgress( supported_executions[0].id) else: monitor.MonitorTestMatrixProgress() log.status.Print('\nMore details are available at [{0}].'.format(url)) # Fetch the per-dimension test outcomes list, and also the "rolled-up" # matrix outcome from the Tool Results service. summary_fetcher = results_summary.ToolResultsSummaryFetcher( project, tr_client, tr_messages, tr_ids) self.exit_code = exit_code.ExitCodeFromRollupOutcome( summary_fetcher.FetchMatrixRollupOutcome(), tr_messages.Outcome.SummaryValueValuesEnum) return summary_fetcher.CreateMatrixOutcomeSummary()
def __init__(self, matrix_id, test_type, context, clock=datetime.datetime.now, status_interval_secs=None): """Construct a MatrixMonitor to monitor a single test matrix instance. Args: matrix_id: {str} the unique ID of the matrix being monitored. test_type: {str} the type of matrix test being run (e.g. 'robo') context: {str:obj} dict containing the gcloud command context, which includes the Testing API client & messages libs generated by Apitools. clock: injected function which returns a current datetime object when called. Used to generate time-stamps on progress messages. status_interval_secs: {float} how long to sleep between status checks. """ self.matrix_id = matrix_id self._test_type = test_type self._client = context['testing_client'] self._messages = context['testing_messages'] self._clock = clock self._project = util.GetProject() self._max_status_length = 0 if status_interval_secs is not None: self._status_interval_secs = status_interval_secs else: self._status_interval_secs = ( properties.VALUES.test.matrix_status_interval.GetInt() or _DEFAULT_STATUS_INTERVAL_SECS) # Poll for matrix status half as fast if the end user is not running in # interactive mode (i.e. either sys.stdin or sys.stderr is not a terminal # i/o stream) such as when gcloud is called by a CI system like Jenkins). # This reduces Testing service load and API quota usage. if not console_io.IsInteractive(error=True): self._status_interval_secs *= 2 exec_states = self._messages.TestExecution.StateValueValuesEnum self._state_names = { exec_states.VALIDATING: 'Validating', exec_states.PENDING: 'Pending', exec_states.RUNNING: 'Running', exec_states.FINISHED: 'Finished', exec_states.ERROR: 'Error', exec_states.UNSUPPORTED_ENVIRONMENT: 'Unsupported', exec_states.INCOMPATIBLE_ENVIRONMENT: 'Incompatible Environment', exec_states.INCOMPATIBLE_ARCHITECTURE: 'Incompatible Architecture', exec_states.CANCELLED: 'Cancelled', exec_states.INVALID: 'Invalid', exec_states.TEST_STATE_UNSPECIFIED: '*Unspecified*', } self._completed_execution_states = set([ exec_states.FINISHED, exec_states.ERROR, exec_states.UNSUPPORTED_ENVIRONMENT, exec_states.INCOMPATIBLE_ENVIRONMENT, exec_states.INCOMPATIBLE_ARCHITECTURE, exec_states.CANCELLED, exec_states.INVALID, ]) matrix_states = self._messages.TestMatrix.StateValueValuesEnum self.completed_matrix_states = set([ matrix_states.FINISHED, matrix_states.ERROR, matrix_states.CANCELLED, matrix_states.INVALID, ])
def Run(self, args): """Run the 'gcloud test run' command to invoke a Google Cloud Test Lab test. Args: args: an argparse namespace. All the arguments that were provided to this command invocation (i.e. group and command arguments combined). Returns: One of: - a list of TestOutcome tuples (if ToolResults are available). - a URL string pointing to the user's results in ToolResults or GCS. """ _EnsureUserAcceptsTermsOfService() arg_util.Prepare(args, util.GetAndroidCatalog(self.context)) project = util.GetProject() tr_client = self.context['toolresults_client'] tr_messages = self.context['toolresults_messages'] storage_client = self.context['storage_client'] # The Testing back-end needs a unique GCS object name within the results # bucket to prevent race conditions while processing test results. This # client uses the current time down to the microsecond in ISO format plus a # random 4-letter suffix. The format is: "YYYY-MM-DD_hh:mm:ss.ssssss_rrrr" unique_object = '{0}_{1}'.format( datetime.datetime.now().isoformat('_'), ''.join(random.sample(string.letters, 4))) bucket_ops = results_bucket.ResultsBucketOps(project, args.results_bucket, unique_object, tr_client, tr_messages, storage_client) bucket_ops.UploadFileToGcs(args.app) if args.test: bucket_ops.UploadFileToGcs(args.test) for obb_file in (args.obb_files or []): bucket_ops.UploadFileToGcs(obb_file) bucket_ops.LogGcsResultsUrl() tr_history_picker = history_picker.ToolResultsHistoryPicker( project, tr_client, tr_messages) history_id = tr_history_picker.FindToolResultsHistoryId(args) matrix = matrix_ops.CreateMatrix(args, self.context, history_id, bucket_ops.gcs_results_root) matrix_id = matrix.testMatrixId monitor = matrix_ops.MatrixMonitor(matrix_id, args.type, self.context) with ctrl_c_handler.CancellableTestSection(monitor): supported_executions = monitor.HandleUnsupportedExecutions(matrix) tr_ids = tool_results.GetToolResultsIds(matrix, monitor) url = tool_results.CreateToolResultsUiUrl(project, tr_ids) log.status.Print('') if args. async: return url log.status.Print( 'Test results will be streamed to [{0}].'.format(url)) # If we have exactly one testExecution, show detailed progress info. if len(supported_executions) == 1: monitor.MonitorTestExecutionProgress( supported_executions[0].id) else: monitor.MonitorTestMatrixProgress() log.status.Print('\nMore details are available at [{0}].'.format(url)) # Fetch the per-dimension test outcomes list, and also the "rolled-up" # matrix outcome from the Tool Results service. summary_fetcher = results_summary.ToolResultsSummaryFetcher( project, tr_client, tr_messages, tr_ids) self.exit_code = exit_code.ExitCodeFromRollupOutcome( summary_fetcher.FetchMatrixRollupOutcome(), tr_messages.Outcome.SummaryValueValuesEnum) return summary_fetcher.CreateMatrixOutcomeSummary()