使用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:\Program\Jenkins\workspace\APP_AutoTest\appium_AutoTest\Caps\Caps.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"]),要想真正做到多台手机同时运行,就要用到多线程

appium+pytest+allure+jenkins 如何实现多台手机连接的更多相关文章

  1. pytest + allure + jenkins 生成漂亮的测试报告

    pytest我在上一篇文章初始pytest中已有介绍,是一个很理想的Python测试框架.Allure是一款非常轻量级并且非常灵活的开源测试报告生成框架. 它支持绝大多数测试框架, 例如TestNG. ...

  2. Pytest单元测试框架——Pytest+Allure+Jenkins的应用

    一.简介 pytest+allure+jenkins进行接口测试.生成测试报告.结合jenkins进行集成. pytest是python的一种单元测试框架,与python自带的unittest测试框架 ...

  3. pytest使用笔记(三)——pytest+allure+jenkins配置使用

    按照pytest使用笔记(二)把pytest+allure配置好后,现在在jenkins配置好,先实现手动构建(立个小目标) 一,安装jenkins插件 首页->系统管理->插件管理,从“ ...

  4. python(pytest)+allure+jenkins 实现接口自动化的思路

    效果图镇楼: 上述各模块作用: python(pytest): 1:用于读测试用例(本次用例写在csv文件中) 2:环境配置相关 3:提取1中的测试数据,组成请求体 4:发送请求 5:获取结果 6:断 ...

  5. pytest系列(四)- pytest+allure+jenkins - 持续集成平台生成allure报告

    pytest是什么 pytest是python的一款测试框架,拥有unittest的功能并比它更丰富. allure是什么 有非常多的优秀的测试框架,但却是有非常少优秀的报告工具可以展示非常清楚的用例 ...

  6. Pytest+allure+jenkins生成测试报告

    allure集成jenkins下载地址.下载相关版本的allure包 http://updates.jenkins-ci.org/download/plugins/allure-jenkins-plu ...

  7. pytest+allure+jenkins +python2.7

    pip install lxml==3.8.0 pip install pytest-allure-adaptor

  8. Python+Pytest+Allure+Git+Jenkins接口自动化框架

    Python+Pytest+Allure+Git+Jenkins接口自动化框架 一.接口基础 接口测试是对系统和组件之间的接口进行测试,主要是效验数据的交换,传递和控制管理过程,以及相互逻辑依赖关系. ...

  9. pytest+allure(allure-pytest基于这个插件)设计定制化报告

    一:环境准备 1.python3.6 2.windows环境 3.pycharm 4.allure-pytest 5.allure2.8.0 6.java1.8 allure-pytest快速安装 在 ...

随机推荐

  1. TA-Lib函数对照

    Overlap Studies 重叠研究指标 BBANDS Bollinger Bands 布林带 DEMA Double Exponential Moving Average 双指数移动平均线 EM ...

  2. BBS - 预备知识

    一.中介模型 四个项目: 苑昊 博客(BBS) (7-8) CRM 1.权限组件 (3) 2.start组件 -- admin (5) 1.使用 2.源码 django 源码 (面向对象) 以源码为导 ...

  3. python控制台输出颜色

    python_控制台输出带颜色的文字方法在开发项目过程中,为了方便调试代码,经常会向stdout中输出一些日志,默认的这些日志就直接显示在了终端中.而一般的应用服务器,第三方库,甚至服务器的一些通告也 ...

  4. 0702-spring cloud config-git仓库配置、用户授权

    一.概述 参看地址:https://cloud.spring.io/spring-cloud-static/Edgware.SR3/single/spring-cloud.html#_environm ...

  5. controller中两个方法之间共享一个变量LinkedHashMap

    1:引用传递,创建一个变量,给两个线程都传递进去. 2:静态修饰 static  通过该修饰符说明,该变量只有一份,  所有线程共用一份. 例如下面的htmlidMap通过static变量修饰, up ...

  6. #ifdef和#if defined的差别

    注意两者都有个define的作用,区别在于使用方式上.前者的通常用法是:#ifdef  XXX .... #else .... #endif 只能在两者中选择是否有定义.对于后者,常用法是: #if ...

  7. redhat 5的中文包安装

    中文包文件名.在iso文件的/server/文件夹下fonts-chinese-3.02-9.6.el5.noarch.rpmfonts-ISO8859-2-75dpi-1.0-17.1.noarch ...

  8. 3.7 Templates -- Links

    一.The {{link-to}} Helper 1. 使用{{link-to}}创建一个指向route的链接: app/router.js Router.map(function() { this. ...

  9. 怎样使用CSS设置文字与文字间距距离?

    [文字与文字间距距离,字与字距离间距CSS如何设置?]如果你也遇到W3Cschool用户唐婷大小姐类似的问题不妨也到W3Cschool编程问答进行提问. 对于使用CSS解决字间距的方法W3Cschoo ...

  10. c#将十进制转64进制

    //由于用于文件命名,所以将64位中的+转换为=,/转换为_     static char[] digits = {          '0' , '1' , '2' , '3' , '4' , ' ...