def unzip(archive, path): log_new('unzip') logg('archive', archive) logg('path', path) with zipfile.ZipFile(archive, "r") as z: z.extractall(path)
def adb_load_base(config, parameters): log_new('load_base') [ base, device_name, ] = parameters base_name = os.path.basename(base) logg('base', base) logg('device_name', device_name) adb_client = get_adb_client() adb_device = AdbDevice(device_name, config, adb_client) adb_device.echo('Recreating work dir {}'.format(config.ANDROID_WORK_DIR)) if config.ANDROID_WORK_DIR == config.ANDROID_MAIN_DIR: raise Exception('Incorrect work dir: {}'.format( config.ANDROID_WORK_DIR)) adb_device.delete_path_on_android(config.ANDROID_WORK_DIR) adb_device.create_dir_on_android(config.ANDROID_WORK_DIR) adb_device.echo('Loading base to Android device: {}'.format(device_name)) adb_device.copy_file_to_android( base, '{}/{}'.format(config.ANDROID_WORK_DIR, base_name)) adb_device.list_dir_content_on_android(config.ANDROID_WORK_DIR) adb_device.echo('Loading base finished')
def list_dir_content_on_android(self, dir_path): log_new('list_dir_content_on_android') logg('dir_path', dir_path) cl = 'ls {}'.format(dir_path) log('-------------------') self._execute_shell_command_on_device(cl) log('-------------------')
def get_tags(tcserver_info, build_id): log_new('get_tags') url = ''.join(( tcserver_info.url, '/app/rest/builds/buildType:', tcserver_info.project, ',id:', build_id, '/tags/', )) logg('url', url) response = requests.get(url, auth=(tcserver_info.login, tcserver_info.password)) answer = response.content logg('answer', answer) if response.status_code != 200: raise Exception( 'Unable to get builds information from server, status code: {}'. format(str(response.status_code))) tags = parse_xml_answer(answer, "//tag/@name") return tags
def run_process(config, cl): log_new('run_process') def wait_process(process, timeout): log_new('wait_process') start_time = time.time() wait_key = True while wait_key: time.sleep(config.PROCESS_WAIT_TIME_STEP_SEC) if process.poll() is None: # process is running / not terminated current_time = time.time() seconds_passed = int(current_time - start_time) if seconds_passed > int(timeout): log(' '.join(('timeout:', str(seconds_passed), 'sec'))) wait_key = False subprocess.call( ['taskkill', '/F', '/T', '/PID', str(process.pid)]) log('process terminated') else: wait_key = False logg('cl', cl) process = subprocess.Popen(cl) wait_process(process, config.SHORT_TIMEOUT_SEC)
def __init__(self, device_name, config, client): self.device_name = device_name self.config = config self.client = client device_code = config.DEVICE_CODES[device_name] logg('device_code', device_code) self.device = client.device(device_code)
def _get_parameters(): log_new('_get_parameters') logg('cl', sys.argv) parser = argparse.ArgumentParser() parser.add_argument("--current-results-build", type=str, required=False) #left for backward compatability parser.add_argument("--baseline-results-build", type=str, required=False) #left for backward compatability parser.add_argument("--current-build", type=str, required=True) parser.add_argument("--baseline-build", type=str, required=True) parser.add_argument("--base-name", type=str, required=True) parser.add_argument("--test-name", type=str, required=True) parser.add_argument("--devices", type=str, required=True) parser.add_argument("--rgb-filter-threshold", type=str, required=True) parser.add_argument("--size-filter-threshold", type=str, required=True) parser.add_argument("--test-branch", type=str, required=True) parser.add_argument("--recreate-artifacts", type=str, default="false", required=True) parser.add_argument("--qa-tcserver", type=str, required=True) parameters = parser.parse_args() logg('parameters', parameters) return parameters
def get_test_data(parameters, config): log_new('prepare_test_data') artifacts = select_artifact(parameters.device_name, config) build_base = add_build_to_filename(artifacts.base, config.ARTIFACT_EXTENSIONS, parameters.build_number) build_dynamic_layout = add_build_to_filename( artifacts.dynamic_layout, config.ARTIFACT_EXTENSIONS, parameters.build_number) build_app = add_build_to_filename(artifacts.app, config.ARTIFACT_EXTENSIONS, parameters.build_number) scenario_name = '.'.join((parameters.test_name, 'json')) device_config_name = config.DEFAULT_DEVICE_CONFIG.replace('device', str(parameters.device_name)) test_data = Data( base=os.path.join(config.TEMP_DATA_DIR, build_base), app_src=os.path.join(config.TEMP_DATA_DIR, build_app), scenario_name=scenario_name, scenario_src=os.path.join(config.ENV_TESTS_DIR, scenario_name), sh_script_src=os.path.join(config.ENV_SHELL_SCRIPTS_DIR, config.ANDROID_SIDE_RUN_SCRIPT_NAME), wait_script_src=os.path.join(config.ENV_PROJECT_DIR, config.WAIT_SCRIPT_NAME), result_screens_dir=os.path.join(config.TEMP_ARTIFACTS_DIR, 'screens'), result_logs_dir=os.path.join(config.TEMP_ARTIFACTS_DIR, 'logs'), device_config_src=os.path.join(config.ENV_CONFIG_DIR, device_config_name), device_config_name=device_config_name, log_name=config.LOG_NAME.replace('build', str(parameters.build_number)), dynamic_layout=os.path.join(config.TEMP_DATA_DIR, build_dynamic_layout), ) logg('test_data', test_data) return test_data
def check_result_file(cb, result_name): log_new('check_result_file') def is_existing_file(path): log_new('is_existing_file') return os.path.exists(path) and os.path.isfile(path) if 'current' in cb: cb_build = os.path.split(parameters.current_dir)[-1] cb_dir = parameters.current_dir elif 'baseline' in cb: cb_build = os.path.split(parameters.baseline_dir)[-1] cb_dir = parameters.baseline_dir if result_name == 'scenario': result_file_name = '_'.join(( result_name, parameters.test_name, parameters.city_name )) + config.ARTIFACT_FORMAT else: result_file_name = '_'.join(( result_name, parameters.device_name, parameters.test_name, parameters.city_name, cb_build )) + config.ARTIFACT_FORMAT result_file = os.path.join(cb_dir, result_file_name) logg('result_file', result_file) assert is_existing_file(result_file), 'result file not found: {}'.format(result_file)
def remove_files_if(func, files): log_new('remove_files_if') for file in files: if func(file): if os.path.isfile(file): logg('deleting file', file) os.remove(file) else: delete_directory(file)
def get_parameters(): log_new('_get_parameters') logg('cl', sys.argv) parser = argparse.ArgumentParser() parser.add_argument("-b", "--build-number", type=str, required=True) args = parser.parse_args() logg('args', args) return args
def _set_tag(chosen_build, builds_info, del_tags, new_tag, tcserver_info): log_new('_set_tag') log('{} -> {}'.format(del_tags, new_tag)) build_info = builds_info[chosen_build] old_tags = set(build_info.tags) logg('old_tags', old_tags) tags_to_delete = set(del_tags) new_tags = (old_tags - tags_to_delete) | {new_tag} add_tags(chosen_build, new_tags, tcserver_info)
def get_teamcity_artifact_file_name(build_number, config): log_new('get_artifact_file_name') artifact_file_name = ''.join(( config.ARTIFACT_NAME, '-', build_number, config.ARTIFACT_FORMAT )) logg('artifact_file_name', artifact_file_name) return artifact_file_name
def check_input_artifacts(artifacts_path, build_number, device, config): log_new('check_input_artifacts') logg('artifacts_path', artifacts_path) artifacts = select_artifact(device, config) artifact_files = os.listdir(artifacts_path) expected_artifact_files = map(lambda name: add_build_to_filename(name, config.ARTIFACT_EXTENSIONS, build_number), artifacts) logg('expected_artifact_files', expected_artifact_files) not_found_files = filter(lambda name: name not in artifact_files, expected_artifact_files) assert len(not_found_files) is 0, 'Artifact files not found: {}'.format(not_found_files)
def get_parameters(): log_new('_get_parameters') logg('cl', sys.argv) parser = argparse.ArgumentParser() parser.add_argument("-b", "--build-number", type=str, required=True) parser.add_argument("-d", "--device-name", type=str, required=True) parser.add_argument("-t", "--test-name", type=str, required=True) parameters = parser.parse_args() logg('parameters', parameters) return parameters
def get_teamcity_artifact_url(build_number, artifact_file_name, config): log_new('get_artifact_url') url = '/'.join(( config.REMOTE_TC_SERVER_GUEST_URL, 'repository/download', config.REMOTE_TC_PROJECT, build_number, artifact_file_name )) logg('url created', url) return url
def parse_response(response, build_fields): log_new('parse_response') response_content = response.content root = etree.fromstring(response_content) node = root.xpath('/builds/build')[0] result = {} for field_name in build_fields: value = node.get(field_name) logg(field_name, value) assert value is not None result[field_name] = value return result
def _choose_build(config, tcserver_info): log_new('_choose_build') builds_info = get_builds(tcserver_info) queue = _create_queue(builds_info, config) chosen_build = str(queue[0]) log_new('* * * * * * *') logg('chosen_build', chosen_build) log('* * * * * * *') return chosen_build.strip('"')
def get_files_list_on_android(self, dir_path, extension): log_new('get_files_list_on_android') log('in dir: {} with extension: {}'.format(dir_path, extension)) cl = 'ls {}'.format(dir_path) dir_content = self.device.shell(cl) dir_content = dir_content.encode("utf-8") logg('dir_content', dir_content) dir_content = dir_content.replace('\n', ' ') result = [] for item in dir_content.split(' '): item = item.encode("utf-8") if item.strip().endswith('.{}'.format(extension)): result.append(item) return result
def parse_xml_answer(answer, xpath_pattern): log_new('parse_xml_answer') doc = etree.fromstring(answer.strip()) result = [] for element in doc: el = etree.fromstring(etree.tostring(element)) name = ensure_not_single_element_list(el.xpath(xpath_pattern)) logg('name', name) result.append(name.lower()) return result
def _find_tagged_baseline_build(config, tcserver_info): log_new('_find_tagged_baseline_build') builds_info = get_builds(tcserver_info) tagged = [] for build_number, build_info in builds_info.iteritems(): if config.tag_baseline in build_info.tags: tagged.append(int(build_number)) logg('tagged baseline build', tagged) return str(max(tagged)) if len(tagged) > 0 else None
def save_diff_image(l_path, r_path, count): # saving resulting diff png on disk if count == 0: return None image1_name = os.path.basename(l_path) image2_name = os.path.basename(r_path) assert image1_name == image2_name diff_name = image1_name.replace('.png', '_{}.png'.format(str(count))) diff_path = os.path.join(diff_dir, diff_name) diff_image = build_diff_image(diff_gray_alpha, image1, whitening_ratio) cv2.imwrite(diff_path, diff_image) logg('diff', diff_path) return diff_path
def get_parameters(): log_new('_get_parameters') logg('cl', sys.argv) parser = argparse.ArgumentParser() parser.add_argument('--current-dir', '-c', type=str, required=True) parser.add_argument('--baseline-dir', '-b', type=str, required=True) parser.add_argument('--device-name', '-d', type=str, required=True) parser.add_argument('--test-name', '-t', type=str, required=True) parser.add_argument('--city-name', '-city', type=str, required=True) parameters = parser.parse_args() logg('parameters', parameters) return parameters
def get_image_set_info(image_set): log_new('get_image_set_info') correct_name = image_set.correct info_set = correct_name.rstrip('.png').split('_') screen_name = correct_name.rstrip('.png') if image_set.diff is not None: diff_name = os.path.basename(image_set.diff) logg('diff_name', diff_name) diff_info_set = diff_name.rstrip('.png').split('_') if len(diff_info_set) == 7: diff_sum = diff_info_set[6] else: raise Exception( 'Incorrect format of diff name: number of "_"-devided items = {} (expected 7)' .format(len(diff_info_set))) else: diff_sum = None if len(info_set) == 6: result = ScreenInfo( screen_name, info_set[0], get_testcase_name(screen_name), info_set[1].replace('scr', ''), info_set[2], info_set[3], info_set[4], info_set[5], diff_sum, status[screen_name], ) else: raise Exception( 'Incorrect format of screenshot name: number of "_"-devided items = {} (expected 6)"' .format(len(info_set))) return result
def get_parameters(config): log_new('_get_parameters') logg('cl', sys.argv) parser = argparse.ArgumentParser() parser.add_argument('--current-dir', '-c', type=str, required=True) parser.add_argument('--baseline-dir', '-b', type=str, required=True) parser.add_argument('--diff-dir', '-d', type=str, required=True) parser.add_argument('--rgb-threshold', '-f1', type=int, required=False, default=config.DEFAULT_RGB_THRESHOLD) parser.add_argument('--size-threshold', '-f2', type=int, required=False, default=config.DEFAULT_SIZE_THRESHOLD) parser.add_argument('--test_name', '-t', type=str, required=False) parser.add_argument('--base_name', '-base', type=str, required=True) parser.add_argument('--device_name', '-device', type=str, required=True) parser.add_argument('--current-build', '-cb', type=int, required=True) parser.add_argument('--baseline-build', '-bb', type=int, required=True) parser.add_argument('--current-test-build', '-ct', type=int, required=True) parser.add_argument('--baseline-test-build', '-bt', type=int, required=True) parameters = parser.parse_args() logg('parameters', parameters) assert isinstance(parameters.rgb_threshold, int) assert isinstance(parameters.size_threshold, int) assert isinstance(parameters.current_build, int) assert isinstance(parameters.baseline_build, int) assert isinstance(parameters.current_test_build, int) assert isinstance(parameters.baseline_test_build, int) return parameters
def create_tag(tcserver_info, build_id, tag): log_new('create_tag') logg('tag', tag) build_id = str(build_id) tags_xml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><tags count="1"><tag name="{}"/></tags>'. \ format(tag.lower()) logg('tags_xml', tags_xml) headers = {'Content-Type': 'application/xml'} url = '{}/app/rest/builds/buildType:{},id:{}/tags/'.format( tcserver_info.url, tcserver_info.project, str(build_id)) response = requests.put(url, data=tags_xml, headers=headers, auth=(tcserver_info.login, tcserver_info.password)) log(response.content)
def _create_queue(builds_info, config): log_new('_create_queue') tagged_for_execution = [] ready_for_execution = [] processed_tags = [ config.tag_finished, config.tag_progress, config.tag_broken, config.tag_baseline ] processed_tags_set = set(processed_tags) for build_number, build_info in builds_info.iteritems(): if not build_info.status == 'SUCCESS': continue is_tagged = len(build_info.tags) > 0 is_root = config.tag_root in build_info.tags is_processed = len(set(build_info.tags) & processed_tags_set) > 0 if is_root: logg('tagged for execution', build_number) tagged_for_execution.append(int(build_number)) elif not is_processed: if is_tagged: logg('tagged with irrelevant tag(s) ready for execution', build_number) else: logg('untagged ready for execution', build_number) ready_for_execution.append(int(build_number)) queue = tagged_for_execution + ready_for_execution logg('unsorted queue', queue) queue.sort(reverse=True) logg('sorted queue', queue) if len(queue) == 0: raise Exception('No builds in queue') return queue
def _check_artifacts(test_name, base_name, device_name, build_number, build_artifacts): log_new('_check_artifacts') logg('build_number', build_number) logg('build_artifacts', build_artifacts) correct_artifacts = [ 'logs_{}_{}_{}_{}.zip'.format(device_name.lower(), test_name, base_name, build_number), 'screens_{}_{}_{}_{}.zip'.format(device_name.lower(), test_name, base_name, build_number), 'scenario_{}_{}.zip'.format(test_name, base_name), ] result = True for artifact in correct_artifacts: if artifact not in build_artifacts: result = False log('artifact not found {}'.format(artifact)) return result
def download_teamcity_artifact(artifact_url, artifact_file): log_new('download_teamcity_artifact') logg('artifact_url', artifact_url) logg('artifact_file', artifact_file) response = requests.get(artifact_url) logg('response', response) status_code = response.status_code logg('status_code', status_code) assert status_code == 200, 'wrong status code: {}'.format(status_code) with open(artifact_file, 'wb') as f: for chunk in response.iter_content(1024): f.write(chunk)
def create_correct_list(scenario1, scenario2): """ :param scenario: path to scenario json file :type scenario: str :return: list of expected screenshots obtained from json :rtype: list[str] """ log_new('create_correct_list') logg('scenario1', scenario1) logg('scenario2', scenario2) _check_jsons_identity(scenario1, scenario2) screenshots = [] with open(scenario1, 'r') as json_file: json_data = json.load(json_file) for json_line in json_data: if json_line['name'] == 'make_screenshot': screenshot_name = json_line['arguments']['file_name'].replace( 'screens/', '') if screenshot_name != 'finish.png': screenshots.append(screenshot_name) return screenshots