Appium Server源码分析之作为Bootstrap客户端
var http = require('http') , express = require('express') , ... , routing = require('./routing.js') 可以看到routing是在main.js所在目录的routing.js文件里导出来的,我们打开该文件: var controller = require('./controller.js'); module.exports = function (appium) { var rest = appium.rest; var globalBeforeFilter = controller.getGlobalBeforeFilter(appium); // Make appium available to all REST http requests. rest.all('/wd/*', globalBeforeFilter); routeNotYetImplemented(rest); rest.all('/wd/hub/session/*', controller.sessionBeforeFilter); rest.get('/wd/hub/status', controller.getStatus); rest.post('/wd/hub/session', controller.createSession); rest.get('/wd/hub/session/:sessionId?', controller.getSession); rest.delete('/wd/hub/session/:sessionId?', controller.deleteSession); rest.get('/wd/hub/sessions', controller.getSessions); rest.get('/wd/hub/session/:sessionId?/context', controller.getCurrentContext); rest.post('/wd/hub/session/:sessionId?/context', controller.setContext); rest.get('/wd/hub/session/:sessionId?/contexts', controller.getContexts); rest.post('/wd/hub/session/:sessionId?/element', controller.findElement); rest.post('/wd/hub/session/:sessionId?/elements', controller.findElements); rest.post('/wd/hub/session/:sessionId?/element/:elementId?/value', controller.setValue); rest.post('/wd/hub/session/:sessionId?/element/:elementId?/click', controller.doClick); ... |
Appium.prototype.start = function (desiredCaps, cb) { var configureAndStart = function () { this.desiredCapabilities = new Capabilities(desiredCaps); this.updateResetArgsFromCaps(); this.args.webSocket = this.webSocket; // allow to persist over many sessions this.configure(this.args, this.desiredCapabilities, function (err) { if (err) { logger.debug("Got configuration error, not starting session"); this.cleanupSession(); cb(err, null); } else { this.invoke(cb); } }.bind(this)); }.bind(this); if (this.sessionId === null) { configureAndStart(); } else if (this.sessionOverride) { logger.info("Found an existing session to clobber, shutting it down " + "first..."); this.stop(function (err) { if (err) return cb(err); logger.info("Old session shut down OK, proceeding to new session"); configureAndStart(); }); } else { return cb(new Error("Requested a new session but one was in progress")); } }; |
Appium.prototype.getNewDevice = function (deviceType) { var DeviceClass = (function () { switch (deviceType) { case DT_IOS: return IOS; case DT_SAFARI: return Safari; case DT_ANDROID: return Android; case DT_CHROME: return Chrome; case DT_SELENDROID: return Selendroid; case DT_FIREFOX_OS: return FirefoxOs; default: throw new Error("Tried to start a device that doesn't exist: " + deviceType); } })(); return new DeviceClass(); }; |
Android.prototype.initQueue = function () { this.queue = async.queue(function (task, cb) { var action = task.action, params = task.params; this.cbForCurrentCmd = cb; if (this.adb && !this.shuttingDown) { this.uiautomator.sendAction(action, params, function (response) { this.cbForCurrentCmd = null; if (typeof cb === 'function') { this.respond(response, cb); } }.bind(this)); } else { this.cbForCurrentCmd = null; var msg = "Tried to send command to non-existent Android device, " + "maybe it shut down?"; if (this.shuttingDown) { msg = "We're in the middle of shutting down the Android device, " + "so your request won't be executed. Sorry!"; } this.respond({ status: status.codes.UnknownError.code , value: msg }, cb); } }.bind(this), 1); }; |
Appium.prototype.invoke = function (cb) { this.sessionId = UUID.create().hex; logger.debug('Creating new appium session ' + this.sessionId); if (this.device.args.autoLaunch === false) { ... } else { // the normal case, where we launch the device for folks var onStart = function (err, sessionIdOverride) { if (sessionIdOverride) { this.sessionId = sessionIdOverride; logger.debug("Overriding session id with " + JSON.stringify(sessionIdOverride)); } if (err) return this.cleanupSession(err, cb); logger.debug("Device launched! Ready for commands"); this.setCommandTimeout(this.desiredCapabilities.newCommandTimeout); cb(null, this.device); }.bind(this); this.device.start(onStart, _.once(this.cleanupSession.bind(this))); } }; |
Android.prototype.start = function (cb, onDie) { this.launchCb = cb; this.uiautomatorExitCb = onDie; logger.info("Starting android appium"); if (this.adb === null) { this.adb = new ADB(this.args); } if (this.uiautomator === null) { this.uiautomator = new UiAutomator(this.adb, this.args); this.uiautomator.setExitHandler(this.onUiautomatorExit.bind(this)); } logger.debug("Using fast reset? " + this.args.fastReset); async.series([ this.prepareDevice.bind(this), this.packageAndLaunchActivityFromManifest.bind(this), this.checkApiLevel.bind(this), this.pushStrings.bind(this), this.processFromManifest.bind(this), this.uninstallApp.bind(this), this.installAppForTest.bind(this), this.forwardPort.bind(this), this.pushAppium.bind(this), this.initUnicode.bind(this), this.pushSettingsApp.bind(this), this.pushUnlock.bind(this), this.uiautomator.start.bind(this.uiautomator), this.wakeUp.bind(this), this.unlock.bind(this), this.getDataDir.bind(this), this.setupCompressedLayoutHierarchy.bind(this), this.startAppUnderTest.bind(this), this.initAutoWebview.bind(this) ], function (err) { if (err) { this.shutdown(function () { this.launchCb(err); }.bind(this)); } else { this.didLaunch = true; this.launchCb(null, this.proxySessionId); } }.bind(this)); }; |
UiAutomator.prototype.start = function (readyCb) { logger.info("Starting App"); this.adb.killProcessesByName('uiautomator', function (err) { if (err) return readyCb(err); logger.debug("Running bootstrap"); var args = ["shell", "uiautomator", "runtest", "AppiumBootstrap.jar", "-c", "io.appium.android.bootstrap.Bootstrap"]; this.alreadyExited = false; this.onSocketReady = readyCb; this.proc = this.adb.spawn(args); this.proc.on("error", function (err) { logger.error("Unable to spawn adb: " + err.message); if (!this.alreadyExited) { this.alreadyExited = true; readyCb(new Error("Unable to start Android Debug Bridge: " + err.message)); } }.bind(this)); this.proc.stdout.on('data', this.outputStreamHandler.bind(this)); this.proc.stderr.on('data', this.errorStreamHandler.bind(this)); this.proc.on('exit', this.exitHandler.bind(this)); }.bind(this)); }; |
Android.prototype.initQueue = function () { this.queue = async.queue(function (task, cb) { var action = task.action, params = task.params; this.cbForCurrentCmd = cb; if (this.adb && !this.shuttingDown) { this.uiautomator.sendAction(action, params, function (response) { this.cbForCurrentCmd = null; if (typeof cb === 'function') { this.respond(response, cb); } }.bind(this)); } else { this.cbForCurrentCmd = null; var msg = "Tried to send command to non-existent Android device, " + "maybe it shut down?"; if (this.shuttingDown) { msg = "We're in the middle of shutting down the Android device, " + "so your request won't be executed. Sorry!"; } this.respond({ status: status.codes.UnknownError.code , value: msg }, cb); } }.bind(this), 1); }; |
UiAutomator.prototype.sendCommand = function (type, extra, cb) { ... else if (this.socketClient) { ... var cmd = {cmd: type}; cmd = _.extend(cmd, extra); var cmdJson = JSON.stringify(cmd) + "\n"; this.cmdCb = cb; var logCmd = cmdJson.trim(); if (logCmd.length > 1000) { logCmd = logCmd.substr(0, 1000) + "..."; } this.debug("Sending command to android: " + logCmd); this.socketClient.write(cmdJson); } ... } |
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
赛门铁克:孟加拉央行失窃案黑客还攻击过索尼影业
据路透社报道,网络安全公司赛门铁克本周在一篇博客中称,从孟加拉中央银行转走8100万美元巨款的黑客,除了与发生在菲律宾的另一起银行电脑系统被黑事件存在关联外,还涉嫌在2014年攻击了索尼影业公司的电脑系统。 美国联邦调查局(FBI)曾批评朝鲜是索尼影业公司遭黑客攻击事件的罪魁祸首。数字安全公司Mandiant对孟加拉中央银行巨款失窃案进行了调查。该公司一位高管在接受路透社采访时表示,实施这起盗窃案的黑客最近还对东南亚地区的多家银行电脑系统进行过攻击。 赛门铁克在周四的一篇博文中并未点名菲律宾哪家银行遭到黑客攻击,也未透露是否有资金被窃,但该公司表示这一系列攻击的线索最早可以追溯到去年10月份。赛门铁克也没有确认黑客的身份。 东南亚银行接连遭黑客攻击 菲律宾中央银行副行长内斯托·埃斯佩尼拉(Nestor Espenilla)告诉路透社,该国没有银行被黑客转走资金,但他并未排除网络攻击的可能性。埃斯佩尼拉表示:“我们正在调查菲律宾银行是否遭到类似攻击。但是,到目前为止还没有接到资金被盗的报告。”他还补充说:“遭到黑客攻击是一回事,资金被转走又是一回事。” Mandiant副总裁马绍尔·海尔...
- 下一篇
移植MonkeyRunner的图片对比功能实现-Appium篇
如果你的目标测试app有很多imageview组成的话,这个时候monkeyrunner的截图比较功能就体现出来了。而其他几个流行的框架如Robotium,UIAutomator以及 Appium都提供了截图,但少了两个功能: 获取子图 图片比较 既然 Google开发的MonkeyRunner能盛行这么久,且它体功能的结果验证功能只有截屏比较,那么必然有它的道理,有它存在的价值,所以我们很有必要在需要的情况下把它相应的功能给移植到其他框架上面上来。 经过本人前面 文章描述的几个框架的源码的研究(robotium还没有做),大家可以知道MonkeyRunner是跑在PC端的,只有在需要发送相应的命令事件时才会驱动目标机器的monkey或者 shell等。比如获取图片是从目标机器的buffer设备得到,但是比较图片和获取子图是从客户PC端做的。 这里Appium工作的方式非常的类似,因为它也是在客户端跑,但需要注入事件发送命令时还是通过目标机器段的bootstrap来驱动uiatuomator来完成的,所以要把MonkeyRunner的获取子图已经图片比较的功能移植过来是非常容易的事情。...
相关文章
文章评论
共有0条评论来说两句吧...