基于PO多设备并发用例框架python+pytest+appium+allure

文章介绍了PyAppium框架,它支持自动启动/关闭AppiumServer,获取设备信息,安装/卸载APP,自动化测试用例执行,失败截图与日志收集,以及在多台手机上并行测试以提高效率。框架还包含了详细的使用说明和关键代码示例。
摘要由CSDN通过智能技术生成

框架目录说明

pyAppium		# 项目根目录
├─app			# 测试APP存放目录
├─common		# 公共模块目录
├─config		# 配置文件目录
├─data			# 测试数据目录
├─outputs		# 测试输出目录
│  ├─logs		# 日志目录
│  ├─picture	# 截图存放目录
│  └─reports	# 测试报告存放目录
├─pageViwe		# PO模式页面封装模块
└─testcase		# 测试用例目录

主要功能


1.自动启动appium server和杀掉appium server
2.自动获取电脑连接设备信息,如设备版本、设备udid
3.自动检测端口是否可用、释放占用端口
4.自动获取测试APP应用相关信息,如:appPackage、launchable_activity
5.自动安装APP和卸载APP
6.测试用例无需配置,自动获取用例执行,测试人员只需编写相关case
7.用例执行失败自动截图、收集错误日志信息,自动加到测试报告对应case下面
8.启动一次APP,执行所有测试用例,缩短测试用例执行间隔,提高测试执行效率
9.多进程方式在多台手机上同时执行测试,大幅提高测试效率

测试环境

  • win10 64 pycharm2019
  • python 3.7.0 及以上
  • node v12.16.3
  • appium1.20.2
  • java version “1.8.0_181”
  • Android SDK 百度云分享地址 密码:6666

下载框架源码


1.仓库地址:https://gitee.com/King15800/pyAppium.git
2.下载源码:git clone https://gitee.com/King15800/pyAppium.git
3.使用pycharm 打开源码项目
4.安装项目依赖包:pip install -r requirements.txt

使用说明


启动项目正常运行前提:
有手机正常已经连接电脑
修改 test_login.py文件输入账号信息,本demo基于学科网APP编写
已下载APP,放到项目目录App下
启动项目:直接运行main.py文件即可。

关键代码说明
启动入口说明 main.py

def run_parallel(device_info) 定义一个pytest 启动入口,根据设备进行启动,一个设备启动一个

def run_parallel(device_info):
    pytest.main([f"--cmdopt={device_info}",
                 "--alluredir", "outputs/reports/data"])
    os.system("allure generate outputs/reports/data -o outputs/reports/html --clean")


根据设备数量,使用进程池创建进程进行测试

    device_lists = get_device_infos() # 获取连接设备信息
    uninstall_app(device_lists)  # 卸载APP
    with Pool(len(device_lists)) as pool:
        pool.map(run_parallel, device_lists)
        pool.close()
        pool.join()


完整代码

# _*_coding:utf-8 _*_
# @Time  :2021/6/21 22:33
# @Author  : king
# @File    :main.py
# @Software  :PyCharm
from multiprocessing import Pool

import os
import pytest
from common.app_info import get_device_infos, uninstall_app
from common.appium_auto_server import close_appium


def run_parallel(device_info):
    pytest.main([f"--cmdopt={device_info}",
                 "--alluredir", "outputs/reports/data"])
    os.system("allure generate outputs/reports/data -o outputs/reports/html --clean")


if __name__ == "__main__":
    device_lists = get_device_infos()
    uninstall_app(device_lists)
    with Pool(len(device_lists)) as pool:
        pool.map(run_parallel, device_lists)
        pool.close()
        pool.join()


driver实现 base_driver.py

class BaseDriver:

    def __init__(self, device_info):
        self.device_info = device_info
        cmd = "start /b appium -a 127.0.0.1 -p {0} -bp {1}".format(self.device_info["server_port"],
                                                                   self.device_info["server_port"] + 1)
        open_appium(cmd, self.device_info["server_port"])

    def base_driver(self, automationName="appium"):
        fp = open(f"{configPath}//caps.yml", encoding='utf-8')
        # 超时时间、是否重置
        desired_caps = yaml.load(fp, Loader=yaml.FullLoader)

        # 设备名称
        desired_caps["deviceName"] = self.device_info['device']

        # 版本信息
        desired_caps["platform_version"] = get_devices_version(desired_caps["deviceName"])

        app_path = os.path.join(appPath, get_app_name(appPath))
        desired_caps['app'] = app_path

        desired_caps['appPackage'] = get_app_package_name()

        desired_caps['appActivity'] = get_app_launchable_activity()

        # udid
        desired_caps["udid"] = self.device_info['device']
        # 系统端口号
        desired_caps["systemPort"] = self.device_info["system_port"]

        desired_caps["automationName"] = automationName

        driver = webdriver.Remote(f"http://127.0.0.1:{self.device_info['server_port']}/wd/hub",
                                  desired_capabilities=desired_caps)
        return driver


核心conftest文件 conftest.py

from common.base_driver import BaseDriver
import pytest
import random

from pageViwe.loginPage import LoginPage

driver = None


def pytest_addoption(parser):
    parser.addoption("--cmdopt", action="store", default="device_info", help=None)


@pytest.fixture(scope='session')
def cmdopt(pytestconfig):
    return pytestconfig.getoption("--cmdopt")


# 定义公共的fixture,根据需要进行修改
@pytest.fixture(scope='session')
def common_driver(cmdopt):
    global driver
    base_driver = BaseDriver(eval(cmdopt))
    driver = base_driver.base_driver()
    lg = LoginPage(driver)
    yield lg
    driver.close_app()
    driver.quit()


@pytest.fixture
def device(cmdopt):
    yield eval(cmdopt)

# 报告中区分多设备执行结果
def pytest_itemcollected(item):
    item._nodeid = str(random.randint(1, 1000)) + '_' + item . _nodeid


执行结果

============================= test session starts =============================
platform win32 -- Python 3.8.4, pytest-7.4.0, pluggy-1.2.0
============================= test session starts =============================
platform win32 -- Python 3.8.4, pytest-7.4.0, pluggy-1.2.0
rootdir: C:\study\pythonT\pyAppium-master
configfile: pytest.ini
testpaths: testcase/
plugins: allure-pytest-2.13.2, excel-1.5.2, html-3.2.0, metadata-3.0.0, ordering-0.6, rerunfailures-12.0, xdist-3.3.1
rootdir: C:\study\pythonT\pyAppium-master
configfile: pytest.ini
testpaths: testcase/
plugins: allure-pytest-2.13.2, excel-1.5.2, html-3.2.0, metadata-3.0.0, ordering-0.6, rerunfailures-12.0, xdist-3.3.1
collected 2 items
collected 2 items


35_testcase\test_login.py 575_testcase\test_login.py .                                              [ 50%]
239_testcase\test_login.py .                                             [ 50%]
885_testcase\test_login.py F                                             [100%]


执行日志

测试报告

我同时连接的是一台模拟机,一台真机,控制台显示也是两台同时运行,但是实际结果是设备一台台运行的,并不是两台设备同时运行操作。(连接两台真机时,可以并行)


case 标题动态生成,可以自行修改,目前是功能名称+设备udid

注意点

由于使用pytest的自带日志模块,修改pytest 自带loging文件的写入模式,保证记录完整日志信息,文件路径C:\python3.8\Lib\site-packages\_pytest\logging.py 需要根据自己环境地址进入
将mode='w' 改成 mode='a' 在文件505行左右(不同版本有所不同,有的在646行左右)
       

if log_file:
    self.log_file_handler = logging.FileHandler(
        log_file, mode="a", encoding="UTF-8"
    )

未来规划
集成到Jenkins
不同机器能够采用不同数据
可以对于无线连接手机进行测试
appium server远程分布式调用执行
————————————————

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值