zoukankan      html  css  js  c++  java
  • appium+pytest+allure+jenkins 如何实现多台手机连接

    使用appium可以实现app自动化测试,我们之前是连接一台手机去运行,如何同时连接多台手机呢?很多人可能想到的是多线程(threading)。今天分享一种比多线程更简单的方法,虽然不是多台手机同时运行,但可以连接多台手机依次运行,大致的运行方式是:001号测试用例:A手机,B手机...,002号测试用例:A手机,B手机...

    环境准备

    • appium的安装:adt,nodejs,appium的python库,appium server
    • pytest的安装:pytest
    • allure的安装:allure的python库pytest-allure-adaptor
      jenkins上插件的安装-传送门
    • jenkins的安装:windows上的安装-传送门
    • 手机/模拟器:华为荣耀畅玩5C,夜神模拟器

    框架改造

    1. 配置改写

    以上课所写的前程贷的自动化框架为主,框架的分层如下(框架分享 - 传送门:提取码: zvry):

    在上述框架中,我们的配置信息存在Caps目录下的Caps.yaml中,譬如这样

    -
      platformName: Android
      platformVersion: 5.1.1
      deviceName: JTG6T16307007427
      appPackage: com.xxzb.fenwoo
      appActivity: .activity.addition.WelcomeActivity
      noReset: True
    
    -
      server_ip: 127.0.0.1
      server_port: 4723
    

    这只是一台手机的设备信息和连接信息,如果我们需要两台甚至多台,就需要把它们的信息都写入yaml文件,每个手机的信息用一个列表描述

    -
      deviceDesc: Honor_5C
      server_url: 127.0.0.1
      server_port: 4723
      desired_caps:
        platformName: Android
        platformVersion: 5.1.1
        deviceName: JTG6T16307007427
        udid: JTG6T16307007427
        appPackage: com.xxzb.fenwoo
        appActivity: .activity.addition.WelcomeActivity
        noReset: True
    
    -
      deviceDesc: YeShen
      server_url: 127.0.0.1
      server_port: 4726
      desired_caps:
        platformName: Android
        platformVersion: 5.1.1
        deviceName: 127.0.0.1:62025
        udid: 127.0.0.1:62025
        appPackage: com.xxzb.fenwoo
        appActivity: .activity.addition.WelcomeActivity
        noReset: True
    

    注意:

    1. 上述yaml文件中多了deviceDesc和udid,前者是我们用来区分不同的手机,后者是appium用来区分不同的手机  2) 给不同的手机设置不同的端口,荣耀畅玩5C使用的是4723,夜神模拟器使用的是4726

    2. BaseDriver的改写

    BaseDriver是公共的driver类,通过读取yaml配置信息,生成并返回driver对象,其基本的传递路径是:Caps.yaml-->BaseDriver.py-->conftest:设置不同的fixture,返回driver,因此它是沟通配置信息和conftest的桥梁,既然配置信息变了,相应的BaseDriver的读取也要改变
    改写前的BaseDriver.py,具体代码如下:

    import yaml
    import os
    from Common.dir_config import caps_dir
    from appium import webdriver
    
    class BaseDriver:
    
        def base_driver(self, automationName="appium", noRest=True):
            fs = open(os.path.join(caps_dir, "caps.yaml"))
            datas = yaml.load(fs)
            #通过判断automationName,来决定是否添加uiautomator2
            if automationName != "appium":
                datas[0]["automationName"] = automationName
            if noRest == False:
                datas[0]["noReset"] = False
            #连接appium server,并告诉其要操作的对象
            server = 'http://{0}:{1}/wd/hub'.format(datas[1]["server_ip"], datas[1]["server_port"])
            driver = webdriver.Remote(server, datas[0])
            return driver
    

    由于是多台手机,每个手机的通过配置信息里的deviceDesc来区分,BaseDriver类中的base_driver函数需要设置一个变量device来区别不同的手机,这个device是我们传入的,如果我们传入的是device="YeShen",还是用之前的代码的话,得到将是全部的信息。有必要通过if判断筛选下,只取对应device的配置信息

    import yaml
    from appium import webdriver
    
    class BaseDriver:
    
    
        def base_driver(self, device, automationName="appium", noReset=True):
            fs = open(r"D:ProgramJenkinsworkspaceAPP_AutoTestappium_AutoTestCapsCaps.yaml", encoding="utf-8")
            datas = yaml.load(fs)
            for i in datas:
                if device == i["deviceDesc"]:
                    if automationName != "appium":
                        i["desired_caps"]["automationName"] = automationName
                    if noReset == False:
                        i["desired_caps"]["noReset"] = False
                    desired_caps = i["desired_caps"]
                    driver = webdriver.Remote("http://{0}:{1}/wd/hub".format(i["server_url"], i["server_port"]), desired_caps)
                    return driver
    

    3. conftest的改写

    conftest是比较关键的一部,因为它会调用BaseDriver()类中的base_driver()方法,以往我们的conftest是这样定义的:

    #登录:无弹出框,不重置(保留状态)
    @pytest.fixture
    def default_login_driver():
        driver = BaseDriver().basedriver()
        is_welcome(driver)
        yield driver
        driver.close_app()
        driver.quit()
    

    但是现在不同了,这个basedriver()函数中必须传入一个device的实参,这个实参是从哪里获得的?pytest的fixture为我们提供了一种参数化的操作,fixture可以带入参数params,依赖于这个fixture的一套测试会根据参数的不同运行多次,而被装饰函数中通过特殊的request对象来访问每个参数:request.param访问的是列表中的每个元素

    params=["Honor_5C", "YeShen"]
    
    #登录:无toast弹框,不重置
    @pytest.fixture(params=params)
    def login_common_driver(request):
        driver = BaseDriver().base_driver(device=request.param)
        is_welcome(driver)
        yield driver
        driver.close_app()
        driver.quit()
    

    4. allure的使用

    allure可以设置不同的特性:allure.feature(功能点)、allure.story(子功能点)、with allure.step(步骤):、allure.attach(附件)等,结合pytest,一个收集测试用例,一个生成测试报告。现在通过allure在测试用例中给测试报告增加一些特性

    class TestLogin:
    
        #登录成功——手机号、密码正确
        @allure.feature("登录模块")
        @allure.story("登录成功")
        @pytest.mark.usefixtures("login_common_driver")
        def test_login_success(self, login_common_driver):
            with allure.step("正常登录"):
                IndexPage(login_common_driver).click_login()
                LoginPage(login_common_driver).input_phoneNumber(login_success_data["phoneNumber"])
                LoginPage(login_common_driver).input_passwd(login_success_data["passwd"])
                IndexPage(login_common_driver).click_later()
            with allure.step("获取昵称"):
                IndexPage(login_common_driver).click_me()
                nickName = UserInfoPage(login_common_driver).get_nickName()
            with allure.step("比对昵称"):
                assert login_success_data["check"] == nickName
    

    启动多个appium-server

    之前有想过python代码执行appium命令的形式去自动启动appium服务,但通过npm或cnpm安装appium命令行都有报错,只能手动启动。很简单,打开两个appium客户端,一个设置端口为4723,一个4726,启动即可

    配置jenkins任务

    这方面的内容不做过多介绍,只看下构建和构建后的操作,其中allure-results是pytest运行测试用例生成的xml报告所在的目录,jenkins上的Allure Commandline插件会自动解析xml,生成对应的html报告


    allure测试报告

    十分美观吧,右上角的TREND显示的是多次运行结果的趋势,第7次到第19次都是5个fail,第20次6个fail

    除此之外,allure报告的Behaviors功能中可以看到每个测试用例对应的测试步骤、功能、子功能等,测试报告还会标记出同一个测试用例是哪台手机执行的,如下图,TestLogin.test_login_errorPasswd[Honor_5C]代表的执行机是荣耀畅玩5C

    jenkins面板也展示了多次运行结果的趋势

    结语

    pytest中fixture的参数化虽然能够实现多台手机同时连接,但是运行并不是同时的,因为request.param读取参数列表是遍历读取的,所以造成了一个测试用例,手机A先执行,手机B后执行(假设params=["手机A", "手机B"]),要想真正做到多台手机同时运行,就要用到多线程

  • 相关阅读:
    Kettle使用kettle.properties
    kettle 获取文件名
    连接池的补充设置,应用到上面所有数据源中
    kettle 获取某个目录下所有的文件
    不小心删库了怎么办,用binlog可以恢复
    江北的KETTLE学习日志
    Python3 中,bytes 和 str
    kettle入门(四) 之kettle取昨天时间&设置任意时间变量案例
    30-Day Leetcoding Challenge Day17(构造并查集)
    30-Day Leetcoding Challenge Day16
  • 原文地址:https://www.cnblogs.com/my_captain/p/10152125.html
Copyright © 2011-2022 走看看