# 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文件
## 执行测试及结果通知
### 执行测试
- 本地执行:在编辑器的终端中执行命令即可实现本地执行,如执行:python run.py testCases;
- 服务端构建执行:通过配置DevOps实现自动构建并执行;
- 定时执行:请联系产品支持和质控中心团队,在服务端设置执行测试的定时任务。
### 企业微信配置群机器人
UI自动化测试用例代码提交至gitlab,流水线构建完毕后,测试服务器每日定时执行UI自动化测试,采用企业微信机器人通知模式,群机器人配置方法可参考如下:
### 配置config.py文件
- max_fail:当达到最大失败数时,自动停止继续执行其余用例;
- notice_status:是否开启企业微信通知,开启企业微信通知时,设置为TRUE;否则,则不开启企业微信通知,用例运行完毕后不会发送企业微信进行通知;
- chatbot_url:配置企业微信群机器人的Webhook地址;
- product_name:执行UI自动化测试的产品名称(建议命名方式:产品名称+版本号,如:低代码开发平台V21.10版本);
- project_name:项目名称(gitlab中代码仓库名称);
- server_address:测试服务器地址(测试服务器ip地址+webserver端口号)。
### 启动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")))
```
## 常见问题及解决办法
### 浏览器驱动未安装或版本不正确
问题描述:若浏览器驱动未安装或版本不正确时,执行脚本时会报以下错误:
解决办法:使用上文提到的命令,下载正确版本的浏览器驱动。
### 页面未加载完全,导致断言中获取元素内容失败
问题描述:运行用例时,由于操作过快,页面未加载完全,获取的断言不正确,导致脚本运行失败。
解决办法:引入sleep方法,在对应的操作步骤或断言前添加等待时间(等待时间以秒为单位)。
```shell
#引入sleep方法块
from time import sleep
#对应的操作步骤或断言前添加等待时间
sleep(2)
```