手機自動化測試:Appium源碼分析之跟蹤代碼分析六
加載子產品
var logger = require('./logger.js').get('appium')
, status = require('./status.js')
, _ = require('underscore')
, safely = require('./helpers').safely;
加載了4個子產品,3個本地子產品(logger,status,helpers)和一個核心工具子產品(underscore)。本地子產品我們後續再講解,這個工具子產品是做什麼用的,我找到一篇文章講解這個underscore,從這篇文章可以了解到這個子產品主要提供了一些常用的函數,大概80個。
7個函數
reponses子產品中包含7個函數,下面我們一步一步解釋
getSessionId函數
//得到session的id号,每一個session都有一個獨特的id用來辨別
var getSessionId = function (req, response) {
//判斷傳遞過來的參數response是否初始化,如果已經初始化,sessionId的值就指派為response的屬性sessionId的值
//否則指派為undefined
var sessionId = (typeof response === 'undefined') ? undefined : response.sessionId;
//經過上面的指派後,如果sessionId的值為undefined,那麼就要進一步處理
if (typeof sessionId === "undefined") {
if (req.appium) {
//如果req.appium初始化過,就将appium中的屬性sessionId指派給目前變量sessionId
//需要注意的是後面的||null寫法,如果req.appium.sessionId是沒有定義的,那麼會走到||後面,意思也是
//給sessionId定義為null,如果不加||null,會發生什麼呢?(sessionId=undefined)...
sessionId = req.appium.sessionId || null;
} else {
//如果req.appium沒有初始化,那麼就直接将sessionId置為空
sessionId = null;
}
}
//因為我們要求傳回的sessionId是一個字元串,那麼我就要判斷該類型是否正确,如果不正确,也需要置為null值
if (typeof sessionId !== "string" && sessionId !== null) {
sessionId = null;
return sessionId;
};
notImplementedInThisContext
//當我們調用的方法,并不存在的時候,會調用該方法,該方法一般是在裝置端,執行查找或對某一個控件進行操作的。
var notImplementedInThisContext = function (req, res) {
//首先列印提示資訊
logger.debug("Responding to client that a method is not implemented " +
"in this context");
safely(req, function () {
//狀态設定為501,并傳回一個json字元串
res.status(501).send({
status: status.codes.UnknownError.code
, sessionId: getSessionId(req)
, value: {
//提示資訊消息體
message: "Not implemented in this context, try switching " +
"into or out of a web view"
}
});
});
上面的函數體内有2個地方需要了解:safely()和res.status(501).send()
函數 | 意義 |
safely | helpers.js子產品中safely方法 |
res.status(501).send | 将response狀态設定為501,然後發送一個消息 |
下面是safely方法的源碼,也很簡單,就是調用了嵌套的回調函數。
// Mainly used to wrap http response methods, or for cases where errors
// perdure the domain
var safely = function () {
var args = new (Args)(arguments);
var req = args.all[0];
var fn = args.callback;
try {
fn();
} catch (err) {
logger.error('Unexpected error:', err.stack, getRequestContext(req));
respondError
//傳回錯誤資訊
var respondError = exports.respondError = function (req, res, statusObj, value) {
//設定錯誤資訊的内容和狀态碼,因為message要求是字元串類型,code是×××類型
var code = 1, message = "An unknown error occurred";
var newValue = value;
if (typeof statusObj === "string") {
message = statusObj;
} else if (typeof statusObj === "undefined") {
message = "undefined status object";
} else if (typeof statusObj === "number") {
code = statusObj;
message = status.getSummaryByCode(code);
} else if (typeof statusObj.code !== "undefined") {
code = statusObj.code;
message = statusObj.summary;
} else if (typeof statusObj.message !== "undefined") {
message = statusObj.message;
//如果value的值是一個對象類型的值,需要從這個對象中解析出message屬性
//然後進行拼接組成一個json字元串,指派給newValue,如果不是一個對象類型的值
//直接組裝成json字元串
if (typeof newValue === "object") {
if (newValue !== null && _.has(value, "message")) {
// make sure this doesn't get obliterated
value.origValue = value.message;
message += " (Original error: " + value.message + ")";
newValue = _.extend({message: message}, value);
} else {
newValue = {message: message, origValue: value};
//拼接傳回資訊json字元串對象reponse
var response = {status: code, value: newValue};
//擷取sessionId
response.sessionId = getSessionId(req, response);
logger.debug("Responding to client with error: " + JSON.stringify(response));
//調用helpers.js子產品的safely函數,就是調用裡面的嵌套函數
res.status(500).send(response);
respondSuccess
var respondSuccess = exports.respondSuccess = function (req, res, value, sid) {
var response = {status: status.codes.Success.code, value: value};
response.sessionId = getSessionId(req, response) || sid;
if (typeof response.value === "undefined") {
response.value = '';
var printResponse = _.clone(response);
var maxLen = 1000;
if (printResponse.value !== null &&
typeof printResponse.value.length !== "undefined" &&
printResponse.value.length > maxLen) {
printResponse.value = printResponse.value.slice(0, maxLen) + "...";
res.jsonResp = JSON.stringify(printResponse);
logger.debug("Responding to client with success: " + res.jsonResp);
res.status(200).send(response);
這個函數我就不解釋了,因為大緻的方式都是一樣的,都是先解析出列印的消息體,然後發送出去,隻是這裡面的response狀态是200,因為是成功的。該方法調用的log資訊,我們會經常見到。
getResponseHandler
exports.getResponseHandler = function (req, res) {
//直接傳回匿名函數
return function (err, response) {
//先判斷response是否已經初始化,或者是否初始化為空
if (typeof response === "undefined" || response === null) {
//設定為空的json字元串
response = {};
//判斷錯誤的資訊,符合如下條件的,直接抛出異常
if (err !== null && typeof err !== "undefined" && typeof err.status !== 'undefined' && typeof err.value !== 'undefined') {
throw new Error("Looks like you passed in a response object as the " +
"first param to getResponseHandler. Err is always the " +
"first param! Fix your codes!");
} else if (err !== null && typeof err !== "undefined") {
if (typeof err.name !== 'undefined') {
if (err.name === 'NotImplementedError') {
//如果錯誤的name值為NotImplementedError,就調用notImplementedInThisContext函數
notImplementedInThisContext(req, res);
} else if (err.name === "NotYetImplementedError") {
//如果錯誤的name值為NotYetImplementedError,就調用notYetImplemented函數
notYetImplemented(req, res);
} else {
//其他類型都調用respondError
respondError(req, res, status.codes.UnknownError.code, err);
}
} else {
var value = response.value;
if (typeof value === "undefined") {
value = '';
//如果錯誤類型name屬性值為undefined,我們調用respondError的時候傳入的參數為value值
respondError(req, res, err.message, value);
//如果錯誤資訊為空或者未定義,我們需要根據狀态碼的不同,調用不同函數處理
if (response.status === 0) {
respondSuccess(req, res, response.value, response.sessionId);
respondError(req, res, response.status, response.value);
};
終于到了我們真正要解釋的函數了-getResponseHandler,從我上面的解釋可以看出來,該函數是一個控制類的函數,所有的調用經過該函數處理後,會根據傳入參數的不同,調用不同的函數,是以這個函數名字取為handler,以為回複處理器。
checkMissingParams
exports.checkMissingParams = function (req, res, params, strict) {
//如果strict未定義,設定為false,說明strict為boolean類型的值
if (typeof strict === "undefined") {
strict = false;
var missingParamNames = [];
//疊代params所有的元素,擷取所有沒有定義的或者值與strict相反的參數,添加到missingParamNames數組中
_.each(params, function (param, paramName) {
if (typeof param === "undefined" || (strict && !param)) {
missingParamNames.push(paramName);
if (missingParamNames.length > 0) {
//将數組轉化為json字元串
var missingList = JSON.stringify(missingParamNames);
logger.debug("Missing params for request: " + missingList);
//response的狀态為400,消息體為上面的json字元串的
safely(req, function () {
res.status(400).send("Missing parameters: " + missingList);
return false;
return true;
上面的函數是找到為定義的參數或者為null的參數
notYetImplemented
//在getResponseHandler函數中我們看到當err.name為NotYetImplementedError時,會調用該函數
var notYetImplemented = exports.notYetImplemented = function (req, res) {
//與notImplementedInThisContext類似,都是将response的狀态設定為501,然後消息體不同
logger.debug("Responding to client that a method is not implemented");
message: "Not yet implemented. " +
"Please help us: http://appium.io/get-involved.html"