# jc-uitest **Repository Path**: jiachengnet/jc-uitest ## Basic Information - **Project Name**: jc-uitest - **Description**: 嘉诚UI自动化测试框架集成了playwright和pytest,提供简单、快捷、可视化的用例录制手段,以及结果统计、报告生成、持续构建等特性,实现UI自动化测试的全链路解决方案。 - **Primary Language**: Python - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 40 - **Forks**: 16 - **Created**: 2021-12-24 - **Last Updated**: 2026-01-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 嘉诚UI自动化测试框架 ## 框架介绍 嘉诚ui自动化测试框架集成了playwright和pytest,提供简单、快捷、可视化的用例录制手段,以及结果统计、报告生成、持续构建等特性,实现UI自动化测试的全链路解决方案。 ## 安装部署 ### 依赖环境 | 软件 | 版本 | 备注 | | :-----| :---- | :---- | | 操作系统 | win7及以上; centos7及以上 | centos系统要求:CLIBC版本为2.18+,字符集为zn_CN.UTF8 | | python | v3.7+ | | | pip/pip3 | v22.0.3+ | | PS:可使用命令:python -m pip install --upgrade pip,升级pip/pip3版本。 ### 代码下载 将UI自动化框架代码下载到本地,gitee地址:https://gitee.com/jiachengnet/jc-uitest。 ### 本地部署 - 用VSCode或Pycharm打开本地项目代码,根目录下的requirements.txt文件中有UI自动化测试所用的所有依赖包,终端中执行命令即可安装: ```shell $ pip install -r requirements.txt ``` - 安装浏览器驱动 ```shell python -m playwright install ``` 说明:以上步骤操作完毕后,可在本地运行测试框架自带的测试用例,检验环境是否安装成功。 ## 框架介绍 ### 框架文件结构 ``` jc-uitest # UI自动化测试工程 ├── logs # 脚本执行日志 ├── testCases # 测试用例存放路径 │ ├── login # 功能模块名 │ └── test_login.py # UI测试用例-登录系统 │ ├── test_baidu.py # UI测试用例-访问百度 │ └ ──data.json # 存放参数化的数据(若不使用参数化,此文件可忽略) ├── tools # 存放公共方法的目录 ├── report # 每次运行均可在此目录下生成测试报告,包含:错误日志时的屏幕截图、html格式的报告 ├── requirements.txt # 所有UI自动化测试实施时所需的依赖环境 ├── config.py # UI自动化测试框架的配置文件,可配置浏览器驱动类型等 ├── conftest.py # UI自动化测试框架的自带的底层方法 ├── webserver.py # 启动后可通过点击企业微信通知中报告地址查看测试报告内容 └── run.py # 批量运行全部/部分用例 ``` ### 工程配置项说明 | 配置名称 | 说明 | 默认值 | | | :------- | :------------- | :----------------------------------------------------------- | ------------------------------------------------------------ | | 1 | browser | 浏览器驱动类型,支持chromium, firefox, webkit | browser = "chromium" | | 2 | mode | 用例运行模式,包括headless和headedheadless:无头模式,运行用例时不弹出浏览器;headed:有头模式,运行用例时,弹出浏览器 | mode = "headless" | | 3 | rerun | 失败重跑次数 | rerun = "0" | | 4 | fail | 当达到最大失败数,停止执行 | max_fail = "5" | | 5 | notice_status | 是否开启企业微信消息通知。开启企业微信通知时,设置为TRUE;否则,则不开启企业微信通知 | notice_status=True | | 6 | chatbot_url | 企业微信机器人地址 | | | 7 | product_name | 产品名称及版本号 | product_name="嘉城中台v21.10版本" | | 8 | project_name | 项目名称(gitlab项目名称) | project_name = "jcmp_uitest" | | 9 | server_address | 测试报告地址(测试服务器ip地址+webserver端口号) | server_address = "[http://172.31.6.10:8000](http://172.31.6.10:8000/)" | ### 测试用例介绍 ``` """ 编写人 编写时间 """ #引入脚本所用的模块 import os import sys import time from playwright.sync_api import Page import pytest from os.path import dirname, abspath from tools.get_log import GetLog from tools.read_json import get_data #指定参数化文件路径 logincommon_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) sys.path.insert(0, logincommon_path) logger = GetLog.get_log() #添加装饰器,实现测试用例参数化 @pytest.mark.parametrize( "url,loginname,password", get_data(logincommon_path + "/data.json","login") ) #定义测试用例中使用的方法,引用参数化文件中的参数 def test_login(page: Page, url,loginname, password): """ 用例名称:用户中心登录; 用例步骤: 1)输入用户中心地址,访问用户中心; 2)输入用户名、密码。点击登录按钮; 3)登录成功后,判断系统名称是否为“嘉城开发平台”; 4)点击退出登录 """ #获取当前正在执行的测试用例名称,以日志形式打印出来 casename = os.path.splitext(os.path.basename(__file__))[0] logger.info("正在执行用例:{}".format(casename)) #以下为测试用例中具体的操作步骤 # Go to http://test-env.jcinfo.com/jcdp/ page.goto(url) # Click [placeholder="请输入账号"] page.click("[placeholder=\"请输入账号\"]") # Fill [placeholder="请输入账号"] page.fill("[placeholder=\"请输入账号\"]", loginname) # Click [placeholder="请输入密码"] page.click("[placeholder=\"请输入密码\"]") # Fill [placeholder="请输入密码"] page.fill("[placeholder=\"请输入密码\"]", password) # Click input[type="submit"] # with page.expect_navigation(url="http://test-env.jcinfo.com/jcmms/#/404"): with page.expect_navigation(): page.click("input[type=\"submit\"]") # 添加断言:系统登录成功后,获取并判断浏览器标题是否为“嘉诚开发平台”,如果不是,则抛出异常 try: assert "嘉诚开发平台" == page.text_content(".avue-logo_title") logger.info("用例{}的断言结果为{}".format(casename, "嘉诚开发平台" == page.text_content(".avue-logo_title"))) except Exception as e: logger.error("用例{}的断言结果为{},错误信息是:{}".format(casename, "嘉诚开发平台" == page.text_content(".avue-logo_title"), e)) raise # Click span[role="button"] page.click("span[role=\"button\"]") # Click text=退出登录 page.click("text=退出登录") # Click [aria-label="提示"] button:has-text("确定") with page.expect_navigation(): page.click("[aria-label=\"提示\"] button:has-text(\"确定\")") # Close page page.close() ``` ## 开发测试用例 #### 录制用例 - 在cmd或编辑器的终端中,进入到UI自动化测试工程的testCases目录; - 执行录制命令,如:浏览器输入地址为http://test-env.jcinfo.com/jcdp,将录制生成的文件名称指定为test_userCenter_login.py,可输入以下命令 ``` python -m playwright codegen -o test_userCenter_login.py http://test-env.jcinfo.com/jcdp ``` - 录制完毕后关闭浏览器,录制内容可自动保存至文件中,内容如下: ``` from playwright.sync_api import Playwright, sync_playwright def run(playwright: Playwright) -> None: browser = playwright.chromium.launch(headless=False) context = browser.new_context() # Open new page page = context.new_page() # Go to http://test-env.jcinfo.com/jcdp/ page.goto("http://test-env.jcinfo.com/jcdp/") # Click [placeholder="请输入账号"] page.click("[placeholder=\"请输入账号\"]") ..... # Close page page.close() # --------------------- context.close() browser.close() with sync_playwright() as playwright: run(playwright) ``` - 双击录制生成的脚本文件可以回放整个录制过程,检查是录制内容是否正确。 **说明:UI自动化测试用例文件名称需以“test_”开头,否则工程中将不会执行此用例。** ### 编辑用例 ##### 引入工程包 使用pycharm或VSCode打开UI自动化测试工程,在录制好的脚本最上方,添加引入工程包的语句(不需要修改,直接复制即可) ``` import os import sys import time import pytest from playwright.sync_api import Page from os.path import dirname, abspath from tools.get_log import GetLog from tools.read_json import get_data ``` ##### 参数化 测试用例中经常使用的变量(如:网址、用户名、密码等),可放在testCases目录下得data.json文件中,每个测试用例均可引用此变量作为方法的参数使用。若用例需要更换用户名及密码进行登录,则不需要修改用例本身,可直接修改data.json文件中的参数值即可。 如:将登录时使用的网址、用户名、密码配置在testCases\data.json文件中 ``` { "login": [ { "url":"http://test-env.jcinfo.com/jcdp/", "loginname": "super", "password": "admin12345" } ] } ``` 在测试用例文件中,定义方法上方增加指定参数化文件路径及参数注入的语句(不需要修改,直接复制即可): ``` logincommon_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) sys.path.insert(0, logincommon_path) logger = GetLog.get_log() @pytest.mark.parametrize( "url,loginname,password", get_data(logincommon_path + "/data.json","login") ) ``` 在测试用例文件中,定义方法时传入并使用用户名参数、密码参数(定义方法后,在注释中说明测试用例名称及步骤): ``` def test_login(page: Page,url, loginname, password): """ 用例名称:按照登录账户查询用户; 用例步骤: 1)登录系统; 2)进入用户中心-系统管理-用户管理页面; 3)登录账户查询条件中输入“super”,点击查询; 4)点击退出登录 """ # Go to http://test-env.jcinfo.com/jcdp/ page.goto(url) # Click [placeholder="请输入账号"] page.click("[placeholder=\"请输入账号\"]") # Fill [placeholder="请输入账号"] page.fill("[placeholder=\"请输入账号\"]", loginname) # Click [placeholder="请输入密码"] page.click("[placeholder=\"请输入密码\"]") # Fill [placeholder="请输入密码"] page.fill("[placeholder=\"请输入密码\"]", password) # Click input[type="submit"] with page.expect_navigation(): page.click("input[type=\"submit\"]") ``` 说明: 测试用例文件若不使用参数化方式对变量进行设置,则变量值发生变化时直接在测试用例文件中修改即可。 ##### 添加断言 在录制生成的脚本中,需要根据用例添加对应的断言 ``` #系统登录成功后,获取并判断浏览器标题是否为“嘉诚开发平台”,如果不是,则抛出异常 assert "嘉诚开发平台" == page.text_content(".avue-logo_title") ``` ##### 注释或删除无用代码 录制生成的脚本中,需要将以下代码注释或删除,脚本才可运行成功。 ``` # browser = playwright.chromium.launch(headless=False) # context = browser.newContext() # page = context.newPage() # context.close() # browser.close() # with sync_playwright() as playwright: # run(playwright) ``` ### 本地调试用例 * 运行所有用例,可在终端中执行 ```shell $ python run.py testCase ``` * 运行某个功能模块中的所有用例,可在终端中执行 ```shell $ python run.py 功能模块名称 ``` * 运行单个脚本,需要进入到此用例所在目录 ```shell $ python run.py 功能模块名称\用例文件名称 ``` 说明: 1. 控制台中可输出脚本执行成功及失败情况,具体失败原因可查看log文件或report; 2. 执行脚本时,可在命令行中指定运行模式(headed/headless)、测试服务器地址、是否开启企业微信通知,若不指定,则按照config.py文件中默认配置执行。如:python run.py testCases mode:headed server_address:[http://uitest.jcinfo.com](http://uitest.jcinfo.com/) notice_status:True。 ## 部署测试工程 UI自动化测试工程中,根据测试工程在测试服务器中的路径,修改gitlab-ci.yml文件 gitlab-ci ## 执行测试及结果通知 ### 执行测试 - 本地执行:在编辑器的终端中执行命令即可实现本地执行,如执行:python run.py testCases; - 服务端构建执行:通过配置DevOps实现自动构建并执行; - 定时执行:请联系产品支持和质控中心团队,在服务端设置执行测试的定时任务。 ### 企业微信配置群机器人 UI自动化测试用例代码提交至gitlab,流水线构建完毕后,测试服务器每日定时执行UI自动化测试,采用企业微信机器人通知模式,群机器人配置方法可参考如下: bot01 bot02 bot03 ### 配置config.py文件 - max_fail:当达到最大失败数时,自动停止继续执行其余用例; - notice_status:是否开启企业微信通知,开启企业微信通知时,设置为TRUE;否则,则不开启企业微信通知,用例运行完毕后不会发送企业微信进行通知; - chatbot_url:配置企业微信群机器人的Webhook地址; - product_name:执行UI自动化测试的产品名称(建议命名方式:产品名称+版本号,如:低代码开发平台V21.10版本); - project_name:项目名称(gitlab中代码仓库名称); - server_address:测试服务器地址(测试服务器ip地址+webserver端口号)。 modifyConfig ### 启动webserver服务 - 若本地调试代码时,可不启动webserver服务,执行结果直接在report文件夹中查看; - 若需独立部署整个自动化测试环境,可启动webserver服务,消息通知中的报告地址可根据部署情况,在conftest.py中的“企业微信消息通知方法”中配置。 启动webserver服务方法:确认webserver使用的端口号(默认为8000,可根据情况修改)没有被占用后,进入webserver.py文件所在目录,执行以下命令: ``` #windows系统服务器上执行此命令 python webserver.py #linux系统服务器上执行此命令(断开连接时,webserver不会中断) nohup python3 webserver.py & ``` ### 通知结果展示 按照以上方式配置完成后,在服务器或本地运行脚本,企业微信中将收到群机器人发送的UI自动化测试结果通知的消息,点击报告地址可查看本次测试报告的详细情况。 ## 常用方法 ### 常用断言 - page.text_content("nav:first-child"):获取文本内容; - page.get_attribute("input", "alt"):获取属性值; - page.is_checked("input"):获取checkbox状态; - page.is_visible("input"):是否可见; - page.is_enabled("input"):是否可不输入。 更多断言方法可参考:https://playwright.dev/python/docs/assertions。 ### 元素定位 - path方式定位:page.click("xpath=//h2")或page.click("//h2") - 文本方式定位:page.click("text=退出登录")或page.click("'退出登录"') - CSS方式定位:page.click("css=h2")或page.click("h2") 更多元素定位方法可参考:https://playwright.dev/python/docs/selectors。 ### 输出日志 - 在定义方法上方添加以下语句(不需要修改,直接复制即可) ``` logger = GetLog.get_log() ``` - 在定义方法后,获取当前用例名称,输出显示在日志中; - 断言中也需要输出日志,描述失败原因,如: ```python #获取当前用例名称,打印在日志中 casename = os.path.splitext(os.path.basename(__file__))[0] logger.info("正在执行用例:{}".format(casename)) #断言中输出日志,描述失败原因 logger.info("用例{}的断言结果为{}".format(casename, "嘉诚开发平台" == page.text_content(".avue-logo_title"))) ``` ## 常见问题及解决办法 ### 浏览器驱动未安装或版本不正确 问题描述:若浏览器驱动未安装或版本不正确时,执行脚本时会报以下错误: problem01 解决办法:使用上文提到的命令,下载正确版本的浏览器驱动。 ### 页面未加载完全,导致断言中获取元素内容失败 问题描述:运行用例时,由于操作过快,页面未加载完全,获取的断言不正确,导致脚本运行失败。 解决办法:引入sleep方法,在对应的操作步骤或断言前添加等待时间(等待时间以秒为单位)。 ```shell #引入sleep方法块 from time import sleep #对应的操作步骤或断言前添加等待时间 sleep(2) ```