def get_screen(self, path, log_level=logging.INFO): """ Save screen of mobile device. :param path: Path to image that will be saved. :param log_level: Log level. """ # Ensure folder to save the screen exists File.delete(path) Folder.create(folder=os.path.dirname(path)) if self.type is DeviceType.EMU or self.type is DeviceType.ANDROID: Adb.get_screen(device_id=self.id, file_path=path) if self.type is DeviceType.SIM: Simctl.get_screen(sim_id=self.id, file_path=path) if self.type is DeviceType.IOS: IDevice.get_screen(device_id=self.id, file_path=path) image_saved = False if File.exists(path): size = os.path.getsize(path) if size > 10: image_saved = True if image_saved: message = "Image of {0} saved at {1}".format(self.id, path) Log.log(level=log_level, msg=message) else: message = "Failed to save image of {0} saved at {1}".format( self.id, path) Log.error(message) raise Exception(message)
def __get_simulators(): result = Simctl.run_simctl_command(command='list --json devices') try: return json.loads(result.output) except ValueError: Log.error('Failed to parse json ' + os.linesep + result.output) return json.loads('{}')
def get_log_file(device_id): command = 'spawn {0} log stream --level=debug'.format(device_id) Process.kill_by_commandline(command) log_file = Simctl.run_simctl_command(command=command, wait=False).log_file if File.exists(log_file): Log.debug('Log of {0} redirected to {1}'.format(device_id, log_file)) return log_file else: message = 'Failed to get logs of {0}'.format(device_id) Log.error(message) raise Exception(message)
def get_devices(): """ Get available iOS devices (only real devices). """ device_ids = list() output = run(cmd='idevice_id --list', timeout=60).output for line in output.splitlines(): command = 'instruments -s | grep {0}'.format(line) check_connected = run(cmd=command, timeout=30).output if 'null' not in check_connected: device_ids.append(line) else: message = '{0} is not trusted!'.format(line) Log.error(message) return device_ids
def get_max_runtime_version(version): # Parse runtimes result = Simctl.run_simctl_command(command='list --json runtimes') try: runtimes = json.loads(result.output) except ValueError: Log.error('Failed to parse json ' + os.linesep + result.output) return json.loads('{}') # Get max runtime version exact_sdk_version = None for runtime in runtimes['runtimes']: if str(version) in runtime['version'] and runtime[ 'name'].startswith('iOS') and runtime['isAvailable']: exact_sdk_version = Version.get(runtime['version']) if exact_sdk_version is None: raise Exception('Can not find iOS SDK {0}'.format(version)) return exact_sdk_version
def save_screen(path, log_level=logging.DEBUG): """ Save screen of host machine. :param path: Path where screen will be saved. :param log_level: Log level of the command. """ Log.log(level=log_level, msg='Save current host screen at {0}'.format(path)) if Settings.HOST_OS is OSType.LINUX: os.system("import -window root {0}".format(path)) else: try: from PIL import ImageGrab image = ImageGrab.grab() image.save(path) except IOError: Log.error('Failed to take screen of host OS') if Settings.HOST_OS is OSType.OSX: Log.info('Retry...') run(cmd='screencapture ' + path)
def clean(folder): if Folder.exists(folder=folder): Log.debug("Clean folder: " + folder) try: shutil.rmtree(folder) except OSError as error: try: for root, dirs, files in os.walk(folder, topdown=False): for name in files: filename = os.path.join(root, name) if Settings.HOST_OS != OSType.WINDOWS: os.chmod(filename, stat.S_IWUSR) os.remove(filename) for name in dirs: os.rmdir(os.path.join(root, name)) os.rmdir(folder) Log.error('Error: %s - %s.' % (error.filename, error.strerror)) except Exception: Log.info('Kill processes with handle to ' + folder) Process.kill_by_handle(folder) os.system('rm -rf {0}'.format(folder))
def wait_for_log(log_file, string_list, not_existing_string_list=None, timeout=60, check_interval=3): """ Wait until log file contains list of string. :param log_file: Path to log file. :param string_list: List of strings. :param not_existing_string_list: List of string that should not be in logs. :param timeout: Timeout. :param check_interval: Check interval. """ end_time = time.time() + timeout all_items_found = False not_found_list = [] log = "" verified_flag = '[VERIFIED]' while time.time() < end_time: not_found_list = [] log = File.read(log_file) # Extract the part of the log that hasn't been previously verified if verified_flag in log: log = File.extract_part_of_text(log, verified_flag) for item in string_list: if item in log: Log.info("'{0}' found.".format(item)) else: not_found_list.append(item) string_list = not_found_list if not not_found_list: all_items_found = True Log.info("All items found") break else: Log.debug("'{0}' NOT found. Wait...".format(not_found_list)) time.sleep(check_interval) if 'BUILD FAILED' in log: Log.error('BUILD FAILED. No need to wait more time!') break if 'Unable to sync files' in log: Log.error('Sync process failed. No need to wait more time!') break if 'errors were thrown' in log: Log.error('Multiple errors were thrown. No need to wait more time!') break # Mark that part of the log as verified by appending a flag at the end. # The second time we read the file we will verify only the text after that flag if Settings.HOST_OS != OSType.WINDOWS: File.append(log_file, verified_flag) if all_items_found: if not_existing_string_list is None: pass else: for item in not_existing_string_list: assert item not in log, "{0} found! It should not be in logs.\nLog:\n{1}".format(item, log) else: Log.info("NOT FOUND: {0}".format(not_found_list)) Log.info('##### ACTUAL LOG #####\n') Log.info(log) Log.info('######################\n') assert False, "Output does not contain {0}".format(not_found_list)
def serve(project=Settings.AppName.DEFAULT, prod=False): """ Execute `ng serve` inside project dir. :param project: Project name. :param prod: If true passes `--prod` flag. :return: ProcessInfo object. :rtype: core.utils.process_info.ProcessInfo """ project_path = os.path.join(Settings.TEST_RUN_HOME, project) command = 'serve' if prod: command = command + ' --prod' result = NG.exec_command(command=command, cwd=project_path, wait=False) compiled = Wait.until( lambda: 'Compiled successfully' in File.read(result.log_file), timeout=180) if not compiled: Log.error('NG Serve failed to compile in 90 sec.') Log.error('Logs:{0}{1}'.format(os.linesep, File.read(result.log_file))) NG.kill() assert compiled, 'Failed to compile NG app at {0}'.format(project) return result
def run(cmd, cwd=Settings.TEST_RUN_HOME, wait=True, timeout=600, fail_safe=False, register=True, log_level=logging.DEBUG): # Init result values time_string = datetime.now().strftime('%Y_%m_%d_%H_%M_%S_%f') log_file = os.path.join(Settings.TEST_OUT_LOGS, 'command_{0}.txt'.format(time_string)) complete = False duration = None output = '' # Ensure logs folder exists dir_path = os.path.dirname(os.path.realpath(log_file)) Folder.create(dir_path) # Command settings if not wait: # Redirect output to file File.write(path=log_file, text=cmd + os.linesep + '====>' + os.linesep) cmd = cmd + ' >> ' + log_file + ' 2>&1 &' # Log command that will be executed: Log.log(level=log_level, msg='Execute command: ' + cmd) Log.log(level=logging.DEBUG, msg='CWD: ' + cwd) # Execute command: if wait: start = time.time() with open(log_file, mode='w') as log: if Settings.HOST_OS == OSType.WINDOWS: process = subprocess.Popen(cmd, cwd=cwd, shell=True, stdout=log, stderr=log) else: process = subprocess.Popen(cmd, cwd=cwd, shell=True, stdout=subprocess.PIPE, stderr=log) # Wait until command complete try: process.wait(timeout=timeout) complete = True out, err = process.communicate() if out is not None: if Settings.PYTHON_VERSION < 3: output = str(out.decode('utf8').encode('utf8')).strip() else: output = out.decode("utf-8").strip() except subprocess.TimeoutExpired: process.kill() if fail_safe: Log.error('Command "{0}" timeout after {1} seconds.'.format( cmd, timeout)) else: raise # Append stderr to output stderr = File.read(path=log_file) if stderr: output = output + os.linesep + File.read(path=log_file) # noinspection PyBroadException try: File.delete(path=log_file) except Exception: Log.debug('Failed to clean log file: {0}'.format(log_file)) log_file = None end = time.time() duration = end - start else: process = psutil.Popen(cmd, cwd=cwd, shell=True, stdin=None, stdout=None, stderr=None, close_fds=True) # Get result pid = process.pid exit_code = process.returncode # Log output of the process if wait: Log.log(level=log_level, msg='OUTPUT: ' + os.linesep + output + os.linesep) else: Log.log(level=log_level, msg='OUTPUT REDIRECTED: ' + log_file + os.linesep) # Construct result result = ProcessInfo(cmd=cmd, pid=pid, exit_code=exit_code, output=output, log_file=log_file, complete=complete, duration=duration) # Register in TestContext if psutil.pid_exists(result.pid) and register: TestContext.STARTED_PROCESSES.append(result) # Return the result return result