小程序UI自动化之Python

UI自动化作为测试来说也是很必要的技术,在一个公司要不要展开自动化是需要考虑自动化投入和产出是否成正比。当然针对个人发展来说技多不压身,今天的这篇文章是借鉴他人的代码自己整理出的一些逻辑,希望在以后的日子里可以深入研究

前置条件

  1. 安装Python
  2. 安装Pycharm
  3. 安装类库:Unittest;request;appium;selenium;HMLTestRunner等
  4. 安装Adb
  5. 安装Node.js
  6. 使用命令行安装[npm淘宝镜像]sudo npm install -g cnpm –registry=https://registry.npm.taobao.org –verbose
  7. 安装appium desktop

1.配置环境

1.1 Adb确定连接

  • 首先手机需要打开开发者选项,然后使用电脑通过数据线连接手机,在命令行中输入以下命令就可查看手机和电脑是否连接成功
    1
    2
    1. adb   没有提示错误信息则显示adb安装成功
    2. adb devices 出现设备信息则显示电脑和手机连接成功

Vaj6zj.png

1.2 Appium desktop配置

  • 打开appium desktop中设置host为127.0.0.1,post为默认。点击Start Server v1.10.0按钮
    VXnTUS.png

  • 点击连接后打开右上角的🔍按钮
    VXnxbV.png

  • 在配置 Desired Capabilities标签下输入机型版本设备名称启动app的包地址app的活动名称每次不重置等,在右下角可点击保存另存为根据上述配置开始执行
    VXu95F.png

  • Saved Capability Sets标签下可以看到刚刚配置的信息

    1
    2
    3
    4
    5
    6
    7
    8
    {
    "platformName": "Android",
    "platformVersion": "5.0.2",
    "deviceName": "79ZTWK9599999999",
    "appPackage": "com.tencent.mm",
    "appActivity": "com.tencent.mm.ui.LauncherUI",
    "noReset": true
    }

VXKTpQ.png

  • 连接手机后,在配置好的页面点击Start Session按钮,可以在页面定位到element定位,获取到点击的元素各个属性以及该元素的xpath定位
    VXKH6s.png

ok,如果以上的都完成了,恭喜你所有的配置环境都Done!

2.代码实现逻辑

  • 在编写代码前一定要设计好整个框架及框架的的结构,编写UI小程序自动化引用的是Appium框架,主要编写的代码分为几个大类设备基础类,业务流程类, Elements类, 公共方法类
    ZS6NjS.png

2.1 Elements类

  • xpath类其实在之前也说过,主要是用于定位元素的公共类,任何页面的点击都会触发定位元素,方便元素更好的定位。Appium在定位中使用的元素方式有很多种常用的有:例如XpathidnameClassNameAccessibilityId、等方式。在AllPageElements中下对不同的页面创建不同的.py文件,主要是通过Xpath方法定位。例如主页定位
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    class HomePage():
    elementList = {
    #在首页点击第一个商品
    'firstGoods' : '/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.FrameLayout[1]/android.widget.RelativeLayout/android.widget.FrameLayout[2]/android.widget.FrameLayout/android.widget.FrameLayout[1]/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout/android.widget.FrameLayout[1]/android.webkit.WebView/android.view.View/android.view.View[5]/android.view.View[1]/android.view.View/android.view.View[1]/android.view.View[1]/android.view.View[2]/android.widget.Image',

    #右上角的"···"
    'more' : '//android.widget.ImageButton[@content-desc=\"更多\"]',

    #点击完右上角的"···"后,出现的蒙层页。点击分享。
    'moreShare' : '/hierarchy/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout/android.widget.LinearLayout/android.support.v7.widget.RecyclerView/android.widget.LinearLayout[1]/android.widget.LinearLayout/android.widget.TextView',

    #选择分享对象
    'shareForward' : '//android.widget.FrameLayout[@content-desc=\"当前所在页面,选择\"]/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[1]/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.ListView/android.widget.RelativeLayout[2]/android.widget.LinearLayout/android.widget.LinearLayout/android.widget.LinearLayout',

    #点击发送
    'shareSend' : '/hierarchy/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.LinearLayout/android.widget.LinearLayout[2]/android.widget.LinearLayout/android.widget.Button[2]',

    #我的
    'my' : '/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.FrameLayout[2]/android.widget.LinearLayout/android.widget.RelativeLayout[3]/android.widget.LinearLayout/android.widget.ImageView',

    #首页
    'homePage' : '/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.FrameLayout[2]/android.widget.LinearLayout/android.widget.RelativeLayout[1]/android.widget.LinearLayout/android.widget.TextView',

    #退出小程序
    'exit' : '//android.widget.ImageButton[@content-desc="关闭"]',

    #从微信进入小程序(QA:拼拼到家)
    'miniProEnter' : '//android.widget.FrameLayout[@content-desc="当前所在页面,与的聊天"]/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[1]/android.widget.FrameLayout/android.widget.FrameLayout/com.tencent.mm.ui.mogic.WxViewPager/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.ListView/android.widget.FrameLayout/android.support.v7.widget.RecyclerView/android.widget.RelativeLayout[1]/android.widget.FrameLayout/android.widget.ImageView[1]',

    #社区名称
    'communityName' : '/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.FrameLayout[1]/android.widget.RelativeLayout/android.widget.FrameLayout[2]/android.widget.FrameLayout/android.widget.FrameLayout[1]/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout/android.widget.FrameLayout[1]/android.webkit.WebView/android.view.View/android.view.View[1]/android.view.View[2]',



    }

2.2 公共方法类

  • 公共方法类直白的说就是定位元素的公共类,不同的定位元素可能会有相同的定位方式,只是索引不同。故此创建了公共方法类避免每次调用都要创建,其实这也是方便Elements类,使的每次调用相同的定位方法可直接从公共方法类中获取就行。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    class Find_Element():


    '''
    摘要:以xpath定位元素
    参数介绍:
    driver:appium驱动对象
    xpath:需要查询元素的条件
    msg:需要打印的信息,成功失败不用写(必须打印)
    index:默认为0,值为得到list中的序数
    send_keys:默认为1,不传值,当send_keys为其他值时,则传值
    keys:当需要传值时,传的值是多少
    '''
    def by_xpath(self,driver,xpath,msg,index=0,send_keys=1,keys=''):
    el = driver.find_elements_by_xpath(xpath)
    #print(msg)
    #print(driver.page_source)
    #send_keys为1时,则认为不需要传值
    self.judgeAndPrint(el, msg, index, send_keys, keys)

2.3 设备基础类

  • 从开始准备环境中已经准备环境变量,包括安装软件,配置Appium,定位元素及adb 使用等,这些前提条件准备好后就能写代码实现UI自动化的编程逻辑。设备基础类是整个实现代码的基础,是代码连接设备的桥梁。主要包括设备名称、设备版本、设备操作系统、设备键盘、设备安装包等。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    class devices():

    # @staticmethod
    def setUp(self):
    desired_caps={}
    desired_caps['platformName'] = 'Android'
    desired_caps['platformVersion'] = '8.0.0' #安卓版本
    # desired_caps['platformVersion'] = '5.0.2' #安卓版本
    desired_caps['deviceName'] = '37KRX18A15018322' #设备名称 华为荣耀9i青春版--田野
    # desired_caps['deviceName'] = '79ZTWK9599999999' # 设备名称 三星S8--云霞
    desired_caps['noReset'] = True #键盘是不是要开启
    desired_caps['appPackage'] = 'com.tencent.mm' #安装的包地址
    desired_caps['appActivity'] = 'com.tencent.mm.ui.LauncherUI'
    driver=webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
    #driver.find_elements_by_class_name()
    #el_test=driver.find_element_by_xpath('asdfasdfasf')
    #el_test.
    return driver
    #webdriver.webdriver.WebDriver.get_window_size()

2.4 业务流程类

  • 业务流程类主要是按照正常的业务场景梳理的业务流程,当然这也可以分不同的场景,主流程或者单个流程。本次本人介绍的是按照业务主流程进行分析,从用户的启动小程序到用户的选择商品再到加入购物车的全过程。代码如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    from com.MiniProgram.Main.AllPagesElements.GoodsDetail import GoodsDetail
    #from com.MiniProgram.Main.devices.Devices import devices
    from com.MiniProgram.Main.AllPagesElements.HomePage import HomePage
    from com.MiniProgram.Main.CommonFunction.Find_Element import Find_Element
    from com.MiniProgram.Main.devices.Devices import devices
    from com.MiniProgram.Main.CommonFunction.Swipe import Swipe
    from com.MiniProgram.Main.AllPagesElements.OrderConfirm import OrderConfirm
    from com.MiniProgram.Main.AllPagesElements.Pay import Pay
    from com.MiniProgram.Main.AllPagesElements.ShopCar import ShopCar
    from com.MiniProgram.Main.CommonFunction.TimeWait import TimeWait

    import time
    class MiniPro_buyMainFlow():
    # login=login()
    # 启动自动化测试,获取driver

    #driver = login().login_autoTest()

    # 初始化并获取driver
    driver = devices().setUp()
    time.sleep(8)
    Swipe().swipe(driver,0.5,0.5,0.3,0.8,1000)
    time.sleep(1)

    Find_Element().by_xpath(driver,HomePage().elementList['miniProEnter'],'QA小程序登陆')
    TimeWait().ExplicitWait(driver,HomePage.elementList['firstGoods'],30)

    # 进入详情页
    Find_Element().by_xpath(driver,HomePage.elementList['firstGoods'],'点击第一个商品')
    time.sleep(5)

    # 点击加入购物车
    Find_Element().by_xpath(driver,GoodsDetail().elementList['addToShopCar'],'点击加入购物车')
    time.sleep(3)

    # 将默认sku数量+1
    Find_Element().by_xpath(driver, GoodsDetail().elementList['plus'], '点击+')
    time.sleep(3)

    # 改完数量后,点击加入购物车
    Find_Element().by_xpath(driver, GoodsDetail().elementList['toShopCarTrue'], '点击加入购物车')
    time.sleep(5)

以上是按照UI自动化的框架进行的逻辑分析,在自动化框架中其实有很多种适用于自己业务的框架,适合的才是好的。UI自动化主要是界面的操作,适用于小程序、web、app等各种界面能操作的程序。