python + appium 自动化测试可配置方案

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Mr_shashadudu/article/details/82018167

该方案将具体的操作代码抽离,并通过json文件的形式,使需要传入的特定参数可自由配置,而无需重复书写操作代码。同时将与appium服务器连接所需的参数、操作步骤、界面控件分开,将整个自动化测试过程分成不同模块,并根据具体需求自由组合,也方便多成员共同维护。


1、启动py时传入平台和应用版本信息

parser = argparse.ArgumentParser(description='APP自动化测试方案')
parser.add_argument('--p', metavar='<project path>', help='平台,ios/android')
parser.add_argument('--v', metavar='<project path>', help='测试的应用版本号')

2、将appium运行所需要的配置信息,以及操作和element对应信息,通过json形式分别描述,可以根据版本和平台信息加载相应的配置文件,也可以根据需要加载操作和element对应信息的配置文件。

配置文件目录

与appium创建连接的配置文件
{
  "platformName": "Android",
  "platformVersion": "5.1.1",
  "deviceName": "632340c3",
  "appPackage": "包名",
  "appActivity": "启动页面activity"
}
操作步骤配置文件
[
  {
    "type": "action",
    "elements_id": "nav_bar",
    "action_type": "recycler_click",
    "page": "family_home",
    "recycler_index":0,
    "delay": 2
  },
  {
    "type": "action",
    "action_type": "click",
    "page": "family_home",
    "elements_id": "btn_add_dev",
    "delay": 2
  }
]
界面控件配置文件
{
  "device_type_config_choose": {
    "page_tag_name": "此界面的activity",
    "elements": [
      {
        "elements_id": "btn_back",
        "type": "android.widget.ImageButton"
      },
      {
        "elements_id": "btn_qrcode",
        "path": "//android.widget.TextView[@content-desc='扫一扫']"
      },
      {
        "elements_id": "btn_zigbee_dev",
        "path": "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.ScrollView/android.widget.RelativeLayout/android.widget.LinearLayout/android.widget.LinearLayout[1]/android.widget.ImageView"
      },
      {
        "elements_id": "btn_ble_dev",
        "path": "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.ScrollView/android.widget.RelativeLayout/android.widget.LinearLayout/android.widget.LinearLayout[2]/android.widget.ImageView"
      },
      {
        "elements_id": "btn_all_dev",
        "path": "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.ScrollView/android.widget.RelativeLayout/android.widget.LinearLayout/android.widget.LinearLayout[3]/android.widget.ImageView"
      }
    ]
  }
}

3、加载需要的界面配置信息,解析json放进字典中,使用时,根据操作文件中传入的page和element_id信息,到界面配置信息中定位到指定元素,获取对应的path、id、class等可抓去元素的方式信息。

根据文件路径解析json并添加到字典中
def init(paths):
    global configData
    for path in paths:
        dicts = sys_fun.load_config_json(path)
        configData.update(dicts)
解析json文件
def load_config_json(path):
    print 'load config json ' + path
    with open(path, 'r') as f:
        a = f.read()
    try:
        return json.loads(a)
    except Exception, e:
        return None
根据操作配置文件中传入的page和element_id在界面控件配置文件中定位到指定的element
def get_element(page, element_id):
    page = configData.get(page, None)
    if page is None:
        return None
    else:
        des_item = None
        for item in page[AUTO_CONST.ACTION_ELEMENT]:
            if item.get(AUTO_CONST.ACTION_ELEMENT_ID) == element_id:
                des_item = item
                break
        return des_item

4、读取与appium建立连接所需的配置文件,解析json,并传入,与appium服务器建立连接,并返回driver对象。

def connect_server(config_path):
    desired_caps = load_config_json(config_path)
    desired_caps['unicodeKeyboard'] = True
    desired_caps['resetKeyboard'] = True
    driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
    driver.implicitly_wait(5)
    return driver

5、读取操作配置界面,解析json,逐个执行操作。

for page_item in action_config:
    case_config = load_config_json('./config/case/' + page_item + '.json')
    for step in case_config:
        print step
        cur_parser = generate_parser(step, platform)
        if cur_parser is not None:
            cur_parser.execute(driver)
        else:
            print 'cur_parser is none!!'
根据操作配置界面中传入的“action”,判断是action还是assert行为,并进行相对应的操作。
def generate_parser(case_item, platform):
    case_item_type = case_item.get(AUTO_CONST.CASE_TYPE)
    if AUTO_CONST.CASE_TYPE_ACTION == case_item_type:
        return ActionParser(case_item, platform)
    elif AUTO_CONST.CASE_TYPE_ASSERT == case_item_type:
        return AssertParser(case_item, platform)
    else:
        return None

猜你喜欢

转载自blog.csdn.net/Mr_shashadudu/article/details/82018167
今日推荐