def _display_emulator_binaries(self): emulator_binaries = dict() emulator_dir = clean_path( add_ending_slash(str(GlobalConfig.SDK_DIR)) + "emulator/") try: for the_file in list_files_in_dir(emulator_dir): file_path = os.path.join(emulator_dir, the_file) if os.path.isfile(file_path) and "emulator" in file_path: binary_name = re.findall("emulator\/(emulator*.+)", file_path) if binary_name: emulator_binaries[str(binary_name[0])] = file_path finally: if len(emulator_binaries) == 0: message = "Unable to find emulator binary files in direction '{}' of Android SDK." message = message.format(str(emulator_dir)) raise LauncherFlowInterruptedException(self.TAG, message) else: Printer.system_message( self.TAG, "Emulator related binary files found in Android SDK:") for path in emulator_binaries.values(): Printer.system_message( self.TAG, " * " + Color.GREEN + path + Color.BLUE) return emulator_binaries
def _wait_for_adb_statuses_change_to(self, status, monitored_devices): Printer.system_message( self.TAG, "Waiting until (" + " ".join("'" + device.adb_name + "'" for device in monitored_devices) + ") devices status will change to '" + status + "'.") timeout = GlobalConfig.AVD_ADB_BOOT_TIMEOUT start_time = last_scan_ended = time.time() * 1000 while True: current_time = time.time() * 1000 if current_time - last_scan_ended >= GlobalConfig.ADB_SCAN_INTERVAL or start_time == last_scan_ended: Printer.system_message(self.TAG, "Scanning...") self.device_store.update_model_statuses() Printer.system_message(self.TAG, " * Current wait status:") for device in monitored_devices: Printer.system_message( self.TAG, " " + device.adb_name + " " + Color.GREEN + "('" + device.status + "')") if all(device.status == status for device in monitored_devices): break last_scan_ended = time.time() * 1000 if current_time - start_time >= timeout: message = "Devices took longer than {} seconds to launch (ADB launch). Timeout quit." message = message.format(str(timeout)) raise LauncherFlowInterruptedException(self.TAG, message) Printer.system_message(self.TAG, "ADB wait finished with success!")
def display_picked_apk_info(self): self.apk_store.display_candidates() if self.apk_store.usable_apk_candidate is not None: Printer.system_message( self.TAG, "Picked .*apk with highest version code:\n" + Color.GREEN + str(self.apk_store.usable_apk_candidate) + Color.BLUE + ".")
def _find_latest_build_tools(self): build_tools = list_files_in_dir( clean_path(add_ending_slash(GlobalConfig.SDK_DIR) + "build-tools")) build_tools = [ build_tool for build_tool in build_tools if build_tool[0].isdigit() ] build_tools_folder_with_highest_ver = None Printer.system_message( self.TAG, "Available Android SDK Build-Tools versions: " + str(build_tools)) for build_tools_folder in build_tools: if build_tools_folder_with_highest_ver is None: build_tools_folder_with_highest_ver = build_tools_folder continue ver = int(re.sub("[^0-9]", "", build_tools_folder)) highest_ver = int( re.sub("[^0-9]", "", build_tools_folder_with_highest_ver)) if ver > highest_ver: build_tools_folder_with_highest_ver = build_tools_folder if build_tools_folder_with_highest_ver is None: message = "Android SDK Build-Tools not found. Launcher will quit." raise LauncherFlowInterruptedException(self.TAG, message) else: Printer.system_message( self.TAG, "Android SDK Build-Tools with latest version were selected: " + Color.GREEN + str(build_tools_folder_with_highest_ver) + Color.BLUE + ".") return build_tools_folder_with_highest_ver
def prepare_session_devices(self, avd_set, avd_schemas): avd_ports = PortManager.get_open_ports(avd_set) for avd in avd_set.avd_list: instances_of_schema = avd.instances for i in range(instances_of_schema): avd_schema = copy.deepcopy(avd_schemas[avd.avd_name]) avd_schema.avd_name = avd_schema.avd_name + "-" + str(i) port = avd_ports.pop(0) log_file = FileUtils.clean_path( GlobalConfig.OUTPUT_AVD_LOG_DIR + avd_schema.avd_name + ".txt") FileUtils.create_file(GlobalConfig.OUTPUT_AVD_LOG_DIR, avd_schema.avd_name, "txt") Printer.system_message( self.TAG, "Created file " + Color.GREEN + log_file + Color.BLUE + ".") session_device = SessionVirtualDevice( avd_schema, port, log_file, self.avdmanager_controller, self.emulator_controller, self.adb_controller, self.adb_package_manager_controller, self.adb_settings_controller) self.session_devices.append(session_device) Printer.system_message( self.TAG, "Android Virtual Device model was created according to schema " + Color.GREEN + avd_schema.avd_name + Color.BLUE + ". Instance number: " + str(i) + ". Assigned to port: " + str(port) + ".")
def _assert_bin_directory_exists(self): if os.path.isfile(self.adb_bin): Printer.system_message( self.TAG, "ADB binary file found at " + Color.GREEN + self.adb_bin + Color.BLUE + ".") else: message = "Unable to find ADB binary at '{}'." message = message.format(self.adb_bin) raise LauncherFlowInterruptedException(self.TAG, message)
def _load_avd_set_name(): avd_set_name = ArgLoader.get_arg_loaded_by(ArgLoader.AVD_SET_PREFIX) if avd_set_name is None: Printer.system_message(TAG, "No AVD set selected. ""Currently available real devices will be used in test " "session.") else: Printer.system_message(TAG, "Selected avd set: " + Color.GREEN + avd_set_name + Color.BLUE + ".") return avd_set_name
def _load_launch_plan(launch_manifest, launch_plan_name): if launch_manifest.contains_plan(launch_plan_name): Printer.system_message(TAG, "Launch plan " + Color.GREEN + launch_plan_name + Color.BLUE + " was found in LaunchManifest.") return launch_manifest.get_plan(launch_plan_name) else: message = "Invalid launch plan with name '{}' does not exist in LaunchManifest!" message = message.format(launch_plan_name) raise LauncherFlowInterruptedException(TAG, message)
def _load_launch_plan_name(): launch_plan_name = ArgLoader.get_arg_loaded_by(ArgLoader.LAUNCH_PLAN_PREFIX) if launch_plan_name is None: message = "No launch plan selected. Launcher will quit." raise LauncherFlowInterruptedException(TAG, message) else: Printer.system_message(TAG, "Selected launch plan: " + Color.GREEN + launch_plan_name + Color.BLUE + ".") return launch_plan_name
def remove_device_from_session(self, device): if device in self.outside_session_virtual_devices: self.outside_session_virtual_devices.remove(device) elif device in self.outside_session_devices: self.outside_session_devices.remove(device) elif device in self.session_devices: self.session_devices.remove(device) Printer.system_message( self.TAG, "Device with name " + Color.GREEN + device.adb_name + Color.BLUE + " was removed from session.")
def python_check(): if sys.version_info >= MIN_PYTHON_VER: Printer.system_message( "", "Minimum Python version requirement met! Your version: " + Color.GREEN + str(sys.version_info) + Color.BLUE + ".") else: message = ("Invalid Python version. Please use at least Python " + str(MIN_PYTHON_VER[0]) + "." + str(MIN_PYTHON_VER[1]) + ".") raise LauncherFlowInterruptedException("", message)
def _create_apk_dir_if_not_exists(self): if FileUtils.dir_exists(GlobalConfig.APK_DIR): Printer.system_message( self.TAG, "Directory " + Color.GREEN + GlobalConfig.APK_DIR + Color.BLUE + " was found.") else: Printer.system_message( self.TAG, "Directory " + Color.GREEN + GlobalConfig.APK_DIR + Color.BLUE + " not found. Creating...") FileUtils.create_dir(GlobalConfig.APK_DIR)
def _load_test_set_name(): test_set_name = ArgLoader.get_arg_loaded_by(ArgLoader.TEST_SET_PREFIX) if test_set_name is None: message = "No test set inserted. Launcher will quit." raise LauncherFlowInterruptedException(TAG, message) else: Printer.system_message( TAG, "Selected test set: " + Color.GREEN + test_set_name + Color.BLUE + ".") return test_set_name
def _load_path_set_name(): path_set_name = ArgLoader.get_arg_loaded_by(ArgLoader.PATH_SET_PREFIX) if path_set_name is None: message = "No path set was selected. Launcher will quit." raise LauncherFlowInterruptedException(TAG, message) else: Printer.system_message( TAG, "Selected path set: " + Color.GREEN + path_set_name + Color.BLUE + ".") return path_set_name
def _load_path_set(path_manifest, path_set_name): if path_manifest.contains_set(path_set_name): Printer.system_message( TAG, "Path set " + Color.GREEN + path_set_name + Color.BLUE + " was found in PathManifest.") return path_manifest.get_set(path_set_name) else: message = "Invalid path set with name '{}' does not exist in PathManifest!" message = message.format(path_set_name) raise LauncherFlowInterruptedException(TAG, message)
def print_test_summary(): Printer.system_message(TAG, "Test details:") Printer.system_message(TAG, " * Total number of test cases: " + Color.GREEN + str(session_log.test_summary.test_number) + Color.BLUE + ".") Printer.system_message(TAG, " * Tests passed: " + Color.GREEN + str(session_log.test_summary.test_passed) + Color.BLUE + ".") Printer.system_message(TAG, " * Tests failed: " + Color.GREEN + str(session_log.test_summary.test_failed) + Color.BLUE + ".") if session_log.test_summary.health_rate is not None: Printer.system_message(TAG, " * Health rate: " + Color.GREEN + "{0:.2f}%".format(session_log.test_summary.health_rate * 100) + Color.BLUE + ".")
def _load_launch_plan_manifest(): launch_manifest_dir = make_path_absolute(ArgLoader.get_manifest_dir(ArgLoader.LAUNCH_MANIFEST_DIR_KEY)) if launch_manifest_dir is None: message = ("LaunchManifest file directory was not found. Check if config_files_dir.json exists in root " "of project. Otherwise check if it's linking to existing file.") raise LauncherFlowInterruptedException(TAG, message) else: launch_manifest = LaunchManifest(launch_manifest_dir) Printer.system_message(TAG, "Created LaunchManifest from file: " + Color.GREEN + launch_manifest_dir + Color.BLUE + ".") return launch_manifest
def _load_avd_manifest(): avd_manifest_dir = make_path_absolute(ArgLoader.get_manifest_dir(ArgLoader.AVD_MANIFEST_DIR_KEY)) if avd_manifest_dir is None: message = ("AvdManifest file directory was not found. Check if config_files_dir.json exists in root of" + "project. Otherwise check if it's linking to existing file.") raise LauncherFlowInterruptedException(TAG, message) else: avd_manifest = AvdManifest(avd_manifest_dir) Printer.system_message(TAG, "Created AvdManifest from file: " + Color.GREEN + avd_manifest_dir + Color.BLUE + ".") return avd_manifest
def set_instrumentation_runner_according_to(self, apk): Printer.system_message( self.TAG, "Scanning test .*apk file for Instrumentation Runner data.") resources = self.aapt_controller.list_resources(apk.test_apk_path) target_package = "" instrumentation_runner_name = "" inside_instrumentation_section = False inside_manifest_section = False for line in resources.splitlines(): if "E: instrumentation" in line: inside_instrumentation_section = True continue if "E: manifest" in line: inside_manifest_section = True continue if inside_instrumentation_section and "E: " in line: inside_instrumentation_section = False if inside_manifest_section and "E: " in line: inside_manifest_section = False if inside_instrumentation_section: if "A: android:name" in line: regex_result = re.findall("=\"(.+?)\"", line) if regex_result: instrumentation_runner_name = str(regex_result[0]) if inside_manifest_section: if "A: package" in line: regex_result = re.findall("=\"(.+?)\"", line) if regex_result: target_package = str(regex_result[0]) if target_package == "": message = "Unable to find package of tested application in test .*apk file. Tests won't start without it." raise LauncherFlowInterruptedException(self.TAG, message) if instrumentation_runner_name == "": message = ( "Unable to find Instrumentation Runner name of tested application in test .*apk file." " Tests won't start without it.") raise LauncherFlowInterruptedException(self.TAG, message) GlobalConfig.INSTRUMENTATION_RUNNER = target_package + "/" + instrumentation_runner_name Printer.system_message( self.TAG, "Instrumentation Runner found: " + Color.GREEN + GlobalConfig.INSTRUMENTATION_RUNNER + Color.BLUE + ".")
def _check_if_gradle_binary_was_found(self): self.project_root_found = GlobalConfig.PROJECT_ROOT_DIR != "" and os.path.isdir( GlobalConfig.PROJECT_ROOT_DIR) self.gradlew_found = os.path.isfile(self.gradle_bin) if self.project_root_found: Printer.system_message( self.TAG, "Project root dir " + Color.GREEN + GlobalConfig.PROJECT_ROOT_DIR + Color.BLUE + " was found! Building new .*apk is possible.") if self.gradlew_found: Printer.system_message( self.TAG, "gradlew binary found at " + Color.GREEN + str(self.gradle_bin) + Color.BLUE + ".")
def _load_avd_schema(avd_manifest, avd_set, avd_set_name): avd_schema_dict = avd_manifest.avd_schema_dict for avd in avd_set.avd_list: if avd_manifest.contains_schema(avd.avd_name): Printer.system_message(TAG, "AVD schema " + Color.GREEN + avd.avd_name + Color.BLUE + " was found in AvdManifest.") else: message = "Set '{}' requests usage of AVD schema with name '{}' which doesn't exists in AVD schema list." message = message.format(avd_set_name, avd.avd_name) raise LauncherFlowInterruptedException(TAG, message) return avd_schema_dict
def run_tests(self, test_set, test_list): devices = self.device_store.get_devices() test_packages = self.test_store.get_packages(test_set, test_list) test_cmd_templates = self._prepare_launch_test_cmds_for_run( test_packages, devices, test_set.shard) launch_variant_string = "TESTS SPLIT INTO SHARDS" if test_set.shard else "EACH TEST ON EACH DEVICE" Printer.system_message( self.TAG, "According to test set settings, tests will be run with following variant: " + Color.GREEN + launch_variant_string + Color.BLUE + ".") self._run_tests(devices, test_cmd_templates)
def build_apk(self, test_set): Printer.system_message( self.TAG, "Building application and test .*apk from scratch.") session_logger.log_app_apk_build_start_time() self.gradle_controller.build_application_apk(test_set) session_logger.log_app_apk_build_end_time() session_logger.log_test_apk_build_start_time() self.gradle_controller.build_test_apk(test_set) session_logger.log_test_apk_build_end_time() return self.get_existing_apk(test_set)
def _load_test_set(test_manifest, test_set_name): if test_manifest.contains_set(test_set_name): Printer.system_message( TAG, "Test set " + Color.GREEN + test_set_name + Color.BLUE + " was found in TestManifest.") test_set = test_manifest.get_set(test_set_name) Printer.system_message(TAG, "Test set contains following package names: ") for package_name in test_set.set_package_names: Printer.system_message( TAG, " * " + Color.GREEN + package_name + Color.BLUE) found_all_packages = True errors = "" for package_name in test_set.set_package_names: if not test_manifest.contains_package(package_name): found_all_packages = False errors += "\n - Test package '" + package_name + "' was not found in TestManifest!" if found_all_packages: Printer.system_message( TAG, "All test packages from set " + Color.GREEN + test_set_name + Color.BLUE + " were found in TestManifest.") else: raise LauncherFlowInterruptedException(TAG, errors) else: message = "Test set '{}' not found in TestManifest. Launcher will quit." message = message.format(test_set_name) raise LauncherFlowInterruptedException(TAG, message) return test_set
def run(self): start_time = int(round(time.time() * 1000)) package = self._get_apk_package() installed_packages_str = self.device.get_installed_packages() if package in installed_packages_str: Printer.system_message(self.TAG, "Package " + Color.GREEN + package + Color.BLUE + " is currently installed on device " + Color.GREEN + self.device.adb_name + Color.BLUE + ". Removing from device...") self.device.uninstall_package(package) else: Printer.system_message(self.TAG, "Package " + Color.GREEN + package + Color.BLUE + " was not found on device " + Color.GREEN + self.device.adb_name + Color.BLUE + ".") Printer.system_message(self.TAG, "Installing .*apk file...") self.device.install_apk(self.apk_path) end_time = int(round(time.time() * 1000)) self.install_time = (end_time - start_time) / 1000 Printer.system_message(self.TAG, ".*apk " + Color.GREEN + self.apk_path + Color.BLUE + " was successfully installed on device " + Color.GREEN + self.device.adb_name + Color.BLUE + ". It took " + Color.GREEN + str(self.install_time) + Color.BLUE + " seconds.") self.is_finished = True
def _get_apk_package(self): dump = ShellHelper.execute_shell(self.dump_badging_cmd, False, False) regex_result = re.findall("package: name='(.+?)'", dump) if regex_result: package = str(regex_result[0]) if ".test" in package: GlobalConfig.APP_TEST_PACKAGE = package else: GlobalConfig.APP_PACKAGE = package Printer.system_message(self.TAG, "Package that is about to be installed: " + Color.GREEN + package + Color.BLUE + ".") else: message = "Unable to find package of .*apk file: " + self.apk_name raise LauncherFlowInterruptedException(self.TAG, message) return package
def clear_models_with_android_ids_in_ignore_list(self): for device in self.device_store.get_devices(): if device.get_android_id() in GlobalConfig.IGNORED_DEVICE_LIST: Printer.system_message( self.TAG, "Android-ID " + Color.GREEN + device.android_id + Color.BLUE + " of device " + Color.GREEN + device.adb_name + Color.BLUE + " was found in ignore list.") self.device_store.remove_device_from_session(device) else: Printer.system_message( self.TAG, "Android-ID " + Color.GREEN + device.android_id + Color.BLUE + " of device " + Color.GREEN + device.adb_name + Color.BLUE + " is allowed to run in session.")
def kill_all_avd(self): self.device_store.update_model_statuses() Printer.system_message(self.TAG, "Currently visible AVD:") avd_list = list() for device in self.device_store.get_devices(): if isinstance(device, OutsideSessionVirtualDevice) or isinstance( device, SessionVirtualDevice): avd_list.append(device) Printer.system_message( self.TAG, "- " + device.adb_name + Color.GREEN + " ('" + device.status + "')" + Color.BLUE) if device.status != "not-launched": device.kill() time.sleep(2) self._wait_for_adb_statuses_change_to("not-launched", avd_list)
def prepare_output_directories(self): if FileUtils.dir_exists(GlobalConfig.OUTPUT_DIR): Printer.system_message( self.TAG, "Directory " + Color.GREEN + GlobalConfig.OUTPUT_DIR + Color.BLUE + " found!. Only session related directories and files will be cleaned." ) else: Printer.system_message( self.TAG, "Directory " + Color.GREEN + GlobalConfig.OUTPUT_DIR + Color.BLUE + " not found. Creating...") for directory in [ GlobalConfig.OUTPUT_SUMMARY_LOG_DIR, GlobalConfig.OUTPUT_AVD_LOG_DIR, GlobalConfig.OUTPUT_TEST_LOG_DIR, GlobalConfig.OUTPUT_TEST_LOGCAT_DIR, GlobalConfig.OUTPUT_STYLES_FOLDER_DIR, GlobalConfig.OUTPUT_LOGCAT_HTML_DIR, GlobalConfig.OUTPUT_TEST_RECORDINGS_DIR ]: if FileUtils.dir_exists(directory): files_num = 0 if FileUtils.list_files_in_dir( directory) is None else len( FileUtils.list_files_in_dir(directory)) Printer.system_message( self.TAG, "Directory " + Color.GREEN + directory + Color.BLUE + " was found. Removing (" + Color.GREEN + str(files_num) + " files" + Color.BLUE + ").") FileUtils.clear_dir(directory) else: Printer.system_message( self.TAG, "Directory " + Color.GREEN + directory + Color.BLUE + " not found. Creating...") FileUtils.create_dir(directory) if FileUtils.file_exists(GlobalConfig.OUTPUT_INDEX_HTML_DIR): Printer.system_message( self.TAG, "Removing " + Color.GREEN + GlobalConfig.OUTPUT_INDEX_HTML_DIR + Color.BLUE + " file from previous session.")
def _find_candidates(self, test_set): name_part = test_set.apk_name_part.replace(".apk", "") Printer.system_message( self.TAG, "Checking " + Color.GREEN + GlobalConfig.APK_DIR + Color.BLUE + " directory for .*apk" + " list with names containing " + Color.GREEN + name_part + Color.BLUE + ":") app_apk_list = self.get_list_with_application_apk( name_part, GlobalConfig.APK_DIR) test_apk_list = self.get_list_with_test_apk(name_part, GlobalConfig.APK_DIR) path = 0 name = 1 if app_apk_list: for apk in app_apk_list: apk_filename = apk[name] apk_filepath = FileUtils.clean_folder_only_dir( FileUtils.add_ending_slash(apk[path])) + apk[name] apk_test_filename = "" apk_test_filepath = "" for test_apk in test_apk_list: if apk_filename.replace( ".apk", "" ) in test_apk[name] and "-androidTest" in test_apk[name]: apk_test_filename = test_apk[name] apk_test_filepath = FileUtils.clean_folder_only_dir( FileUtils.add_ending_slash( test_apk[path])) + test_apk[name] dump = self.aapt_controller.dump_badging(apk_filepath) version_code = re.findall("versionCode='(.+?)'", dump) version_code = int(version_code[0]) self.apk_candidates.append( ApkCandidate(apk_filename, apk_filepath, apk_test_filename, apk_test_filepath, version_code)) else: Printer.system_message(self.TAG, " * No .apk* files found.")