(二)appium-desktop錄制腳本二次開發,生成我司自動化腳本


目的

 對appium-desktop腳本錄制功能進行二次開發,增加錄制ATK腳本功能。錄制樣式為

{
"preSteps": [
                 ----------前置條件為打開頁面PG或者啟動Driver(需要根據page參數判斷)
],
"stepSets": [
[
                ----------支持 點擊、輸入、滑動、坐標點擊、返回操作、校驗功能(新增校驗功能)
]
],
"afterSteps": [

]
}

思路

新增ATK錄制腳本的JS-----准備腳本需要的參數----增加新功能---編寫腳本

實現步驟

1、增加AutoTestKit.js

     新增js腳本用於實現錄制ATK腳本

1.1、實現方案

     新增AutoTestKit.js腳本關聯到Framework,並設置為默認腳本

1.2、代碼修改

1.2.1、新增腳本

     注意設置腳本最后面的readableName和export

AutoTestKit.readableName = 'Java - ATK';
export default AutoTestKit;

1.2.2、增加到frameworks

在lib/client-frameworks/index.js 常量中增加atk: AutoTestKit,注意要import AutoTestKit.

1.2.3、特殊處理AutoTestKit

AutoTestKit.js與其它語言錄制腳本格式不一致,不能采用默認的跳轉,需要重新設置。

首先需要在Inspector/RecordedActions.js中進行actionFramework參數傳遞。注意本次除了增加actionFramework參數外,還增加了sendElementName、page后面會用到

其次根據actionFramework路由到AutoTestKit.js

1.2.4、設置為默認

在reducers/Inspector.js中設置DEFAULT_FRAMEWORK='atk'

2、增加當前Activity值參數

     腳本中需要根據activity值的不同設置前置條件

2.1、實現方案

   在startRecording和RefreshSource操作中獲取當前頁面的activity, 並設置為action,如果是RegisterGuideActivity前置條件設置為啟動driver,否則設置為打開PG。

   在ClearActions時把設置的activity重置為空

2.2、代碼修改

2.2.1、獲取activity

     在Inspector/Inspector.js  修改refreshSource和startRecording的onClick 方法,在原來操作的基礎上增加設置當前頁面的activity到全部變量中。注意:refreshSource是先跟device交互再獲取activity.

 

atkStartRecording(){
  this.props.startRecording();
  this.getPage();
}

atkRefreshSource(){
  this.props.applyClientMethod({methodName: 'source'});
  this.getPage();
}

/**
 * 獲取當前頁面的activity
 * @returns {*}
 */
getPage() {

  let exec = require('child_process').execSync;
  let last = exec('adb shell dumpsys window windows | grep mCurrent');
  let page=last.toString("utf8").trim();
  this.props.setFieldValue("page",page.substring(page.lastIndexOf(".")+1,page.length-1));
}

2.2.2、傳遞到Framework

在Inspector/RecordedActions.js中進行page參數傳遞。

如1.2.3圖

2.2.3、設置前置條件

  目前沒有辦法直接獲取當前頁面的PG,只能手動維護一個activity與PG的對應關系,后續如果出現新的activity,需要手動維護。RegisterGuideActivity 是啟動成功頁面。

2.2.4、clearActions

清楚actions時需要重置全局變量中page的值,否則不能獲取新頁面的值。

atkClearActions(){

  this.props.clearRecording();
  this.props.setFieldValue("page","");
}

3、增加assert校驗功能

自動化腳本需要assert校驗,現有錄制沒有該功能,需要新增。

3.1、實現方案

在Tap、Send Keys、Clear后面增加Assert功能,Assert只需要校驗定位的元素存在即可,不需要和device交互。

3.2、代碼修改

3.2.1、增加Assert按鍵

由於不需要和device交互,所以參數中不存在定位元素的屬性,需要手動把findDataSource參數傳遞下去。

actions/Inspector.js中增加atkAssertResult()方法

export function atkAssertResult (params) {
  return (dispatch) => {
    let args = [];
    args = args.concat(params.args || []);
    dispatch({type: RECORD_ACTION, action: params.methodName, params: args });----說明是錄屏操作
    dispatch({type: METHOD_CALL_DONE});---方法調用結束標示
  };
}

4、ATK腳本編寫

  錄制為ATK腳本

4.1、實現方案

   根據操作類型action對應不同的AW,action=findAndAssign 獲取定位元素的屬性(ID 、xpath);action=click、sendKeys、swipe、tap對應AWAppiumComponentInit;action=back對應AWKeyBoardAction;action=assert對應AWDriverActionAssertBatch

4.2、代碼實現

4.2.1、獲取元素的描述信息

      獲取元素的text或者content-desc信息用於顯示腳本中remark

let note="";

if(selectedElement&&selectedElement.attributes.text!==""){

  note=selectedElement.attributes.text;
}else if(selectedElement&&selectedElement.attributes["content-desc"]!==""){

  note=selectedElement.attributes["content-desc"];
}

 因為一個腳本會有多個action,所以要把元素和action進行綁定。

修改reducers/Inspector.js,每個錄屏操作原來都有action、params參數,現在增加selectedElement

case RECORD_ACTION:
  return {
    ...state,
    recordedActions: [
      ...state.recordedActions,
      {action: action.action, params: action.params,selectedElement:state.selectedElement}
    ]
  };

結果如圖:

 
        

4.2.2、switch-case

其中assert與back邏輯一致

switch(action){

  case "findAndAssign":

    //取出type和value

type=params[0];
    value=params[1];
    break;
  case "click":

    str+=` ["${note}", "${type}","${action}","${value}"]`;
    break;
  case "sendKeys":

    str+=` ["${note}", "${type}","${action}","${params[2]}", "${value}"]`;
    break;
  case "swipe":

    str+=` ["滑屏", "","${action}","${params[2]}","${params[3]}","${params[4]}","${params[5]}"]`;
    break;
  case "tap":

    str+=` ["坐標點擊", "","${action}","${params[2]}","${params[3]}"]`;
    break;
  case "back":

    let backAction="back",frontAction="back";

    //獲取下一次操作

if(i!==actions.length-1){

      backAction=actions[i+1].action;
    }

    //獲取上一步操作

if(i!==0){

      frontAction=actions[i-1].action;
    }

      //如果返回操作是第一個操作的情況

if(i===0){

          str=`{\n \"preSteps\": [\n${preStep} ],\n \"stepSets\": [\n [\n`;
      }else{

        if("back"!==frontAction&&"assert"!==frontAction){

          //上一步操作不是返回、校驗操作,去除最后一個逗號

str=str.substring(0,str.length-2);
          str+=`\n ]\n },\n`;
        }
      }

    str+=` {\n "className":"AWKeyBoardAction"\n }`;

    //如果back不是最后一個操作,則重新開始

if(i!==actions.length-1){

      str+=`,\n`;
      if("back"!==backAction&&"assert"!==backAction){

        //如果下一個操作不是返回,校驗操作,則添加

str+=` {\n "className": "AWAppiumComponentInit",\n "remark": "",\n "elementInfoList": [\n`;
      }
    }
    break;

5、增加元素名稱的輸入框--暫時不需要

     由於ATK腳本中元素是以“app-page-element”的方式定位元素,所以需要用戶輸入page名稱和element名稱,並保存到數據庫中。

5.1、實現方案

      在現有的Tap、Send Keys、Clear操作上增加元素輸入框操作,如圖

5.2、代碼修改

5.2.1、修改onClick方法

 修改Inspector/SelectedElement.js 中tab、Tap、Send Keys、Clear的onClick方法,修改為通過在actions/Inspector.js中新增showSendElementNameModal()方法來控制彈出框, 該方法會把type設置為

SHOW_SEND_ELEMENT_NAME_MODAL, 在reducers/Inspector.js中中新增switch-case的一個分支,來設置sendElementNameModalVisible=true

export function showSendElementNameModal () {
  return (dispatch) => {
    dispatch({type: SHOW_SEND_ELEMENT_NAME_MODAL});
  };
}
case SHOW_SEND_ELEMENT_NAME_MODAL:
  return {
    ...state,
    sendElementNameModalVisible: true

}; 

5.2.2、增加輸入框

 新增輸入element的輸入框,當sendElementNameModalVisible=true時該輸入框顯示,點擊OK時,調用新增的handleSendElementName()方法,進行元素的獲取和這是輸入框隱藏

 

handleSendElementName () {
  const {sendElementName, applyClientMethod, hideSendElementNameModal, selectedElementId: elementId} = this.props;
  applyClientMethod({methodName: 'click', elementId});
  hideSendElementNameModal();---同showSendElementNameModal()方法
}

6、保存元素名稱到數據庫-暫時不需要

      表單提交元素名稱后,需要把元素名稱保存到數據庫中,

6.1、實現方案

       使用react已經引入JQuery的網絡請求方案。通過POST方式把數據提交到數據庫中

6.2、代碼修改

    Framework.js是各個語言錄制腳本(java.js、python.js、ruby.js等)的父類。所以在Framework.js中進行數據庫的統一添加

6.2.1、傳參修改

    Framework.js 的getCodeString()方法 增加sendElementName參數。通過RecordedActions傳遞過來。代碼修改如下

如1.2.3圖

6.2.2、post請求

其中page、element、expectedvalue需要用戶填寫,其它值可以通過代碼獲取。
postJSON() {
   var obj = { "app":"guanjia", "element":'aaaa', "expectedimg":"bbbb","expectedvalue": "cccc","os": "Android","page": "eeee","type": "id","value": "rwa"};--測試數據
  const req = new XMLHttpRequest()
  req.open('POST', 'http://10.247.39.5:7070/wisper/api/v1/atk/appium/elementinfo')
  req.setRequestHeader('Content-Type', 'application/json;charset=UTF-8')
  req.send(JSON.stringify(obj))
}
 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM