def is_working(self): '''检查当前Agent是否在工作,如果Agent无法退到后台,重启手机 :returns: boolean ''' try: response = self._execute(Command.HEALTH) return response['value'] == 'XCTestAgent is ready' except XCTestAgentDeadException: self.log.exception('XCTestAgentDead') # Agent无法退到后台,重启手机 try: self.log.info('Reboot device %s' % self.udid) dt.DT().reboot(self.udid) for _ in xrange(20): device = dt.DT().get_device_by_udid(self.udid) if device is not None: break else: raise RuntimeError("after reboot, device disconnected!") except Exception: self.log.exception('device reboot error') except XCTestAgentTimeoutException: if self._relay_error: self.log.error("TcpRelay error:%s" % self._relay_error) self.stop(True) return False
def _get_fbsimctl_agent_cmd_for_simulator(self, xcode_version): agent_dir = self._build_agent_for_simulator(xcode_version) xctest_path = os.path.join( agent_dir, 'XCTestAgent-Runner.app/PlugIns/XCTestAgent.xctest') attached_app = settings.get('QT4I_SIM_ATTACHED_APP', 'com.apple.reminders') return ' '.join([ dt.DT().fbsimctl, self.udid, 'launch_xctest', xctest_path, attached_app, '--port %s -- listen' % self._server_port ])
def __init__(self, device_id, server_ip=DEFAULT_IP, server_port=DEFAULT_PORT, keep_alive=False, retry=3, timeout=60): self.log_name = "xctest_%s" % device_id self.log = logger.get_logger(self.log_name) self.version = '0.0.0' version_file = os.path.join(os.path.expanduser('~'), 'XCTestAgent', 'version.txt') if os.path.exists(version_file): with open(version_file, 'r') as f: self.version = f.read() # XCTestAgent工程默认路径:~/XCTestAent/XCTestAgent.xcodeproj self.XCTestAgentPath = os.path.join(os.path.expanduser('~'), "XCTestAgent", "XCTestAgent.xcodeproj") if not os.path.exists(self.XCTestAgentPath): msg = 'XCTestAgent does not exist. Please use command line: "python manage.py qt4i.setup" to setup XCTestAgent.xcodeproj' self.log.error(msg) raise Exception(msg) self.udid = device_id self._server_ip = server_ip self._server_port = server_port self._server_url = 'http://%s:%d' % (server_ip, server_port) self.type = EnumDevice.Simulator if dt.DT().is_simulator( device_id) else EnumDevice.Device self._is_remote = True self.session_id = None self.crash_flag = False self.capabilities = {} self.mjpeg_port = 9100 + self._server_port - 8100 self.stub_remote_port = 18123 self.stub_port = 18123 + self._server_port - 8100 self.stub_server_url = 'http://%s:%d' % (DEFAULT_IP, self.stub_port) self.stub_client = RemoteConnection(self.stub_server_url, keep_alive=False, logger_name=self.log_name) self.stub_client.set_timeout(0.01) self.error_handler = ErrorHandler() self._command_executor = RemoteConnection(self._server_url, keep_alive=keep_alive, logger_name=self.log_name) self._is_relay_quit = threading.Event() self.start(retry, timeout)
def start(self, retry=1, timeout=CommandTimeout): '''启动Agent,类初始化即调用 :param retry: 启动尝试次数 :type retry: int :param timeout: 单次启动超时 (秒) :type timeout: int ''' if self.type == EnumDevice.Simulator: dt.DT().reboot(self.udid) xcode_version = dt.DT.get_xcode_version().split(".")[0] if int(xcode_version) >= 9: self._agent_cmd = self._get_xcodebuild_agent_cmd_for_simulator( xcode_version) else: self._agent_cmd = self._get_fbsimctl_agent_cmd_for_simulator( xcode_version) else: self._agent_cmd = ' '.join([ 'xcodebuild', '-project %s' % self.XCTestAgentPath, '-scheme %s' % 'XCTestAgent', '-destination "platform=%s,id=%s"' % (self.type, self.udid), 'test' ]) # 清理遗留的xcodebuild进程 print self._agent_cmd Process().kill_process_by_name(self._agent_cmd.replace('"', '')) Process().kill_process_by_port(self._server_port) start_time = time.time() # 启动端口转发线程 self._tcp_relay() for _ in range(retry): self.log.info("Start XCTestAgent: %s" % self._agent_cmd) self.log.info("XCTestAgent Version: %s" % self.version) self._process = ThreadTask( command=self._agent_cmd, stdout_line_callback=self._stdout_line_callback, stderr_line_callback=self._stderr_line_callback) time0 = time.time() while time.time() - time0 < timeout: if self.is_working(): exec_time = (time.time() - start_time) * 1000 self.log.info('[ %s ] consumed [ %dms ]' % ('Start XCTestAgent', exec_time)) return time.sleep(3) _dt = dt.DT() self.log.info("Uninstall com.apple.test.XCTestAgent-Runner") result = _dt.uninstall("com.apple.test.XCTestAgent-Runner", self.udid) if not result: self.log.error(_dt.uninstall_error) self.stop() error_log_name = 'xctest_%s' % self.udid agent_error_log = logger.get_agent_error_log(error_log_name, start_time) raise AgentStartError("Failed to start XCTestAgent.\nDetails:%s" % agent_error_log)
def start(self, retry=1, timeout=CommandTimeout): '''启动Agent,类初始化即调用 :param retry: 启动尝试次数 :type retry: int :param timeout: 单次启动超时 (秒) :type timeout: int ''' if self.type == EnumDevice.Simulator: dt.DT().reboot(self.udid) xct_root = pkg_resources.resource_filename( "qt4i", "driver/xctest/bin") #@UndefinedVariable standard_xctestfile = os.path.join( xct_root, "iphonesimulator-x86_64.xctestrun") xctestfile = os.path.join(xct_root, "%s.xctestrun" % self.udid) if not os.path.isfile(xctestfile): shutil.copyfile(standard_xctestfile, xctestfile) cmd = "/usr/libexec/PlistBuddy -c 'Set :XCTestAgent:EnvironmentVariables:USE_PORT %s' %s" % ( self._server_port, xctestfile) subprocess.call(cmd, shell=True) self._agent_cmd = ' '.join([ 'xcodebuild', 'test-without-building', '-xctestrun', xctestfile, '-destination', '"platform=%s,id=%s"' % (self.type, self.udid) ]) else: self._agent_cmd = ' '.join([ 'xcodebuild', '-project %s' % self.XCTestAgentPath, '-scheme %s' % 'XCTestAgent', '-destination "platform=%s,id=%s"' % (self.type, self.udid), 'test' ]) # 清理遗留的xcodebuild进程 print self._agent_cmd Process().kill_process_by_name(self._agent_cmd.replace('"', '')) Process().kill_process_by_port(self._server_port) start_time = time.time() # 启动端口转发线程 self._tcp_relay() for _ in range(retry): self.log.info("Start XCTestAgent: %s" % self._agent_cmd) self.log.info("XCTestAgent Version: %s" % self.version) self._process = ThreadTask( command=self._agent_cmd, stdout_line_callback=self._stdout_line_callback, stderr_line_callback=self._stderr_line_callback) time0 = time.time() while time.time() - time0 < timeout: if self.is_working(): exec_time = (time.time() - start_time) * 1000 self.log.info('[ %s ] consumed [ %dms ]' % ('Start XCTestAgent', exec_time)) return time.sleep(3) _dt = dt.DT() self.log.info("Uninstall com.apple.test.XCTestAgent-Runner") result = _dt.uninstall("com.apple.test.XCTestAgent-Runner", self.udid) if not result: self.log.error(_dt.uninstall_error) self.stop() error_log_name = 'xctest_%s' % self.udid agent_error_log = logger.get_agent_error_log(error_log_name, start_time) raise AgentStartError("Failed to start XCTestAgent.\nDetails:%s" % agent_error_log)