pytest+yaml+allure+钉钉接口自动化测试,无需代码能力,小白也可使用

文章目录

  • 使用pytest+yaml+allure的接口自动化测试框架
      • 前置条件
      • 一.一个yaml文件一个接口
      • 二.用到的pytest插件:
      • 三.markers的使用
      • 四.执行顺序
      • 五.前后置执行
      • 六.allure报告的用例的严重程度,可以加类或者方法上
      • 七、allure报告如何在本地访问。
      • 八、接口自动化测试框架规则
          • 1.必须有五个一级关键字:name、base_url、request、validate、assert_sql
          • 2.在request一级关键字下必须包含两个二级关键字:method、url
          • 3.传参方式:在request一级关键字下,二级关键字传参
          • 4.如果需要做接口关联的话,那一级关键字中必须要有:extract,目前支持正则匹配和jsonpath匹配,比如:
          • 5.热加载,当yaml中需要动态参数的时候,可以在debug_talk.py中写方法调用,
          • 6.此框架支持四种接口响应断言方式
          • 7.csv数据驱动使用一级关键字parameters,二级关键字中各变量名使用“-”分隔,使用$csv{}调用
          • 8.日志监控和异常处理以及基础路径的设置
          • 9.allure报告定制
          • 10. 数据库断言
          • 11.自动生成代码的yaml文件编写规范
          • 12.智能等待时间的使用
          • 13.测试用例跳过的使用
          • 14.钉钉推送配置
          • 15.前置和后置操作
      • 八.config.yaml文件介绍
      • 九.如何使用
          • 1.data里面放测试用例
          • 2.自动生成测试代码的使用
          • 3.conftest.py的使用
          • 4.执行脚本
          • 5.报告地址
      • 十.实现功能
      • 十一.后续优化

使用pytest+yaml+allure的接口自动化测试框架

项目地址:https://gitee.com/BanZhuanKeOrz/pytest-apitest?_from=gitee_search

前置条件

Windows:

1.安装python,python版本推荐小于3.10,安装requirements.txt 的库,pycharm会提示,然后安装即可,也可以通过pip安装,版本最好一致,不同版本可能不兼容

2.配置allure,建议使用框架中的2.17.3版本,将“allure-2.17.3\bin”配置为环境变量,配置后cmd控制台使用“allure --version”验证是否安装成功

3.支持pytest.ini中文需要修改“F:\ShunYunAutoTest\venv\lib\site-packages\iniconfig\init.py”里面52的为:

# f = open(self.path)
f = open(self.path, encoding="utf-8")
  1. jdk安装,建议1.8版本

Linux:

参考文件:centos7.6+python3+allure+selenium+jdk1.8安装配置.md

网页版:https://blog.csdn.net/weixin_45292690/article/details/130508470?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22130508470%22%2C%22source%22%3A%22weixin_45292690%22%7D

或者网上查下

  1. 安装python,python版本推荐小于3.10,安装requirements.txt 的库,python教程参考

  2. 配置allure,建议使用框架中的2.17.3tgz版本,将“allure-2.17.3\bin”配置为环境变量,安装参考

  3. jdk安装,建议1.8版本,安装参考

一.一个yaml文件一个接口

二.用到的pytest插件:

​ pytest-html 生成简易报告
​ pytest-xdist 多线程
​ pytest-orderding 控制测试用例的执行顺序
​ pytest-rerunfailures 失败用例重跑
​ pytest-base-url 基础路径的配置
​ allure-pytest 生成allure报告

三.markers的使用

​ 在用例上面加上:

    @pytest.mark.smoke
    @pytest.mark.usermanage
    addopts = -v -s -m=smoke -p  no:warnings --alluredir=./temps --clean-alluredir

​ 在执行时需要在ini配置文件中加上:
​ -m 分组名 or 分组名

​ 在执行时需要使用:
​ -m 分组名 or 分组名

四.执行顺序

 @pytest.mark.run(order=1)

五.前后置执行

在所有类,所有用例之前或之后

def setup_class(self):
    print("在类之前的操作")

def teardown_class(self):
    print("在类之后的操作")
    
def setup(self):
    print("在所有用例之前的前置操作")
    
def teardown(self):
    print("在所有用例之后的后置操作")

希望在部分用例之前或之后执行。使用Fixture
Fixture装饰器完整结构如下:

@pytest.fixture(scope="作用域",autouser="自动执行",params="数据驱动",ids="参数别名",name="fixture别名")
@pytest.fixture(scope="function",params=return_list())
def mysql_test(request):
    """
    这个就放着,当参考例子的
    这里的params用于传输数据(list,tuple,字典列表,字典元祖),需要在夹
    具里面通过request(固定写法)接收,然后通过request.param(固定写法)
    获取数据,然后再通过yield把数据返回到测试用例中,然后使用。
    :param request:
    """
    print(request.param)
    print("连接数据库")
    yield request.param
    print("关闭数据库连接")

应用:
1.scope:标记fixture的作用域
function:函数级别(可以手动,也可以自动)
class:类级别(一般是自动)
module:模块级别(一般是自动)
package/session:会话级别(一般是自动)

应用:
1.scope:标记fixture的作用域
function:函数级别(可以手动,也可以自动)
class:类级别(一般是自动)
module:模块级别(一般是自动)
package/session:会话级别(一般是自动)

六.allure报告的用例的严重程度,可以加类或者方法上

例子:

@allure.severity(allure.severity_level.BLOCKER)

blocker:中断缺陷:致命bug:内存泄漏,用户数据丢失,系统奔溃。
critical:临界缺陷:严重bug:功能未实现,功能错误,重复提交
normal:一般缺陷,一般bug,条件查询有误,大数据了无响应等
minor级别:次要缺陷:提示bug,颜色搭配不好,字体排列不整齐,错别字。
trivial级别:轻微缺陷:轻微bug,没有使用专业术语,必填项无提示。建议。

七、allure报告如何在本地访问。

因为pycharm自带容器。tomcat,Nginx,weblogic
1.在本地搭建本地服务器。
2.通过启动服务打开allure报告。
allure open ./reports/allures

八、接口自动化测试框架规则

1.必须有五个一级关键字:name、base_url、request、validate、assert_sql
2.在request一级关键字下必须包含两个二级关键字:method、url
3.传参方式:在request一级关键字下,二级关键字传参

​ 如果是get请求,通过params传参
​ 如果是post请求
​ 传json格式:通过json关键字传参
​ 传表单格式:通过data关键字传参
​ 传文件格式:通过files关键词传参,路径需要"\"进行转义,如:
​ files:
​ file_path: “D:\test.jpg”

  request:
    method: post
    url: /api/system/enterprise
    headers: {"Content-Type": "application/json;charset=utf-8","Authorization": "${get_extract_data(cs_token)}"}
    json:
      userName: $csv{userName}
      leader: "测试"
      phone: $csv{phone}
      password: "admin123"
      passwordConfirm: "admin123"
      enterpriseName: $csv{enterpriseName}
      regionName: "华南"
      address: "广东省中山市专治跌打损伤"
      logo: null
      nickName: "测试"
      phonenumber: $csv{phone}
      lat: 22.267916
      lon: 113.485942
      region: "2"
      method: "post"
      sysUser:
        nickName: "测试"
        phonenumber: $csv{phone}
        userName: $csv{userName}
        password: ""
        passwordConfirm: "admin123"
  request:
    method: post
    url: /adminManage/list
    headers: {"Content-Type": "application/json;charset=utf-8","Authorization": "${get_extract_data(login_token)}"}
    json: {"name":"","account":"","groupName":"","pageNo":1,"pageSize":15}
4.如果需要做接口关联的话,那一级关键字中必须要有:extract,目前支持正则匹配和jsonpath匹配,比如:
    extract:
    	user_Id795: '"userId":(.*?),'
    	user_Id796: $..userId
{
"code": 0,
"message": "success",
"data": {
    "name": "超级管理员",
    "account": "ceshi1",
    "type": 0,
    "company": "绍兴处置中心",
    "mobile": "133333",
    "code": "ABCDEF",
    "token": "hkk-F4fkghsN",
    "groupId": "1,5,2,6,9,10,11,7,3,4,8",
    "jurisdiction": {
        "name": "超级管理员",
        "id": 1
                    },
    "areaCode": 330600,
    "longitude": "120.65391",
    "latitude": "30.21213"
    }
}

提取变量到extract.yaml文件中:
jsonpath提取比如:

    extract:
        login_message: $.message
        login_data_name: $..name

正则提取比如:

    extract:
        login_token: '"token":"(.*?)"'

​ 一起用:

    extract:
        login_message: $.message
        login_data_name: $..name
        login_token: '"token":"(.*?)"'

从extract.yaml 文件中取值变量

如:

login_token: "${get_extract_data(login_token)}"
5.热加载,当yaml中需要动态参数的时候,可以在debug_talk.py中写方法调用,

注意:定义的方法必须有参数;传参的时候,需要什么类型的时候,需要进行强转。int(min_number), int(max_number)
如:

##获取随机数

def get_random_number(self, min_number, max_number):
    return random.randint(int(min_number), int(max_number))

yaml中调用的写法:

password: ${get_random_number(100000,999999)}
6.此框架支持四种接口响应断言方式

分别为:contains、equals、time、jsonpath,除了jsonpath方式,其他的当值为纯数字的时候需要加英文状态的引号。

contains:用于包含情况断言

equals:完全相等情况断言。且其中包含响应状态码断言,使用方式为:{status_code: 200}

time: 响应时间断言,填入时间即可,单位为ms,无需加单引号

jsonpath:1.path为提取实际响应内容的值 2.type为in的时候是期望值在实际值中,type为"=="的时候是期望值完全等于实际值 3.value 为期望值;jsonpath 已经支持热加载,可以直接调用方法

​ 如:

    validate:
    - equals: {status_code: 200}	# 状态码断言
    - equals: {message: success}	# 响应内容完成相等的断言
    - equals: {code: 0}	# 响应内容完成相等的断言
    - contains: token	# 包含断言
    - contains: "'code': 500"	# 包含断言
    - contains: '500'
    - time: 500	#大于500ms,断言失败
    - jsonpath:
    	path: $.data.user.providerId	#提取实际响应内容的值
    	type: in	#断言方式,包含
    	type: ==	#断言方式,完全相等
    	value: 59	#期望值
        value: "${get_api_info(provider_id)}" # 热加载
7.csv数据驱动使用一级关键字parameters,二级关键字中各变量名使用“-”分隔,使用$csv{}调用

​ 如:
​ yaml文件中:

    parameters:
        name-account-password-assert_str: /handle/login/login.csv  parameters:
    name: $csv{name}
    json:
        account: $csv{account}
        password: $csv{password}

​ csv文件中:

    name,account,password,assert_str
    处置平台输入正确的账号密码登录,ceshi1,123456,token
    account必填项检查,"",123456,账号不能为空
    password必填项检查,ceshi1,"",密码不能为空
    测试登录输入错误密码,ceshi1,cuowudemima,账号或密码错误

注意事项:
csv文件中写入规范:当测试输入空的时候使用两个英文状态的双引号,请勿使用中文状态的,中文的算作输入了双引号的值了
断言只能使用contains断言,可以多个的

8.日志监控和异常处理以及基础路径的设置
9.allure报告定制
@allure.epic("项目名称:云服务接口自动化测试项目")
@allure.feature("模块名称:个人信息相关模块")
class TestEmployeeManagement:
    @allure.story("接口名称:获取个人信息信息")
    @pytest.mark.parametrize("args", YamlUtil.read_testcase_yaml("/cs_imotorlinx/mine/test_employee_management/get_employee_info.yaml"))
    def test_get_employee_info(self, args):
        allure.dynamic.title("测试用例标题:{}".format(args['name']))
        RequestUtil().analysis_yaml(args)
10. 数据库断言

assert_sql 关键字不管是否使用都需要在的

sql_statement:放sql语句,因为是用于断言的,所以只支持查询的,返回的内容为,格式为字符串:

[{'user_id': 342, 'enterprise_id': 170, 'provider_id': None, 'dept_id': None, 'user_name': 'siyueqiye', 'nick_name': 'siyueqiye', 'user_type': 2, 'email': None, 'phonenumber': '177*******', 'sex': '0', 'avatar': None, 'password': '$2a$10$jVJurAhzWibCY4pEEUMDvOKjn6VJwiVpJ46nk.bIm4WngTCA93fvm', 'salt': None, 'status': '0', 'del_flag': '0', 'del_version': 0, 'login_ip': None, 'login_date': None, 'manager_id': None, 'create_by': 'admin', 'create_time': datetime.datetime(2022, 5, 6, 11, 5, 15), 'update_by': None, 'update_time': datetime.datetime(2022, 5, 17, 10, 35, 36), 'remark': None}]

yaml文件的写法如下

assert_sql:
  - sql_statement: SELECT * FROM `imotor`.`sys_user` WHERE `phonenumber` LIKE '%177*******%' LIMIT 0, 1000
  - sql_assert: "'user_id': 342, 'enterprise_id': 170"
  - sql_reserve: "'user_id': 342, 'enterprise_id': 170"
  - state: all
  - switch: True
  

sql_assert 中是预期结果是否在实际结果里面,目前的写法格式必须为:“‘字段1’:‘字段value’”

sql_reserve 中是预期结果是否不在实际结果,一般用于硬删除的时候,目前的写法格式必须为:“‘字段1’:‘字段value’”

注意:

​ 输入都需要英文状态的

​ 非数字需要用单引号、数字的时候不要单引号、sql里面的内容必须是连着的

​ 数据库某一个字段的内容为“null”的时候,python返回的时候是“None”,填写预期结果需注意

​ 当查询出的内容没有内容的时候,python返回的是“()”,所以预期结果就填写“()”

​ state字段不存在的时候或者state的值为“all”的时候查询全部的数据,其他情况都是查询单条

​ switch 为 True 执行数据库判断,False表示不进行数据库断言

11.自动生成代码的yaml文件编写规范
- name: 云服务获取个人信息
  case_common:
    allureEpic: 云服务平台接口
    allureFeature: 个人信息模块
    allureStory: 获取个人信息接口
  base_url: ${get_base_url(url_cs_imotorlinx)}
  request:
    method: get
    url: /api/system/user/list?pageNum=1&pageSize=1000
    headers: {"Content-Type": "application/json;charset=utf-8","Authorization": "${get_extract_data(cs_token)}"}
  validate:
    - contains: 操作成功
  assert_sql :
    - sql_statement: SELECT * FROM `imotor`.`sys_user` WHERE `phonenumber` LIKE '%177*******%' LIMIT 0, 1000
    - sql: "'user_id': 342"



- name: 云服务获取个人信息,错误的url
  base_url: ${get_base_url(url_cs_imotorlinx)}
  request:
    method: get
    url: /api/system/user/list1?pageNum=1&pageSize=1000
    headers: {"Content-Type": "application/json;charset=utf-8","Authorization": "${get_extract_data(cs_token)}"}
  validate:
    - contains: "500"
  assert_sql:
    - sql_statement: SELECT * FROM `imotor`.`sys_user` WHERE `phonenumber` LIKE '%177*******%' LIMIT 0, 1000
    - sql: "'user_id': 342"
    - sql: "'enterprise_id': 17"
    - state: one

加上case_common(必填),当一个yaml有多个文件的时候,在第一个用例中填写:

case_common:
	# 测试项目名称
    allureEpic: 云服务平台接口
    # 接口相关模块
    allureFeature: 个人信息模块
    # 接口名称
    allureStory: 获取个人信息接口
12.智能等待时间的使用

在用例文件中增加一级关键字"wait_time",会在断言之前增加等待时间(单位:秒),防止响应过慢接口导致接口失败,使用方法如下:

- name: 测试用例名称001
  wait_time: 1
13.测试用例跳过的使用

在用例文件增加一级关键字“is_run”,当值为“False”的时候,跳过该用例,没该关键字或其他值的时候,跳过该测试用例

- name: 获取24小时高报设备台数(/imotor/device/apumStatisticsTwentyFour)--用例编号812
  #是否跳过测试用例
  is_run:
  is_run: False
14.钉钉推送配置

钉钉机器人配置:

  1. 新建群聊–添加机器人–选择自定义机器人–“安全设置"选择"自定义关键词”–输入"测试"–完成机器人添加,得到webhook
  2. 将webhook的值,填入框架的"config.yaml"的"webhook" 中
15.前置和后置操作

前置操作:用于当前测试用例执行之前的操作,比如通过sql将需要的值写入extract.yaml文件中,或者一些其他的前置操作,需要关键字“setup”,然后去调debug_talk.py中的方法

后置操作:用于当前测试用例执行之前的操作,比如对用例新增、编辑的操作进行还原删除操作,需要关键字“teardown”,然后去调debug_talk.py中的方法

  # 后置操作
  setup:
    sql_extract: ${extract_sql(SELECT id FROM `imotor`.`m_report_rule` WHERE rule_name like '%接口自动化测试%'ORDER BY id DESC LIMIT 1,sql_id_1038)}
  # 后置操作
  teardown:
    sql_teardown: ${extract_sql(SELECT id FROM `imotor`.`m_report_rule` WHERE rule_name like '%接口自动化测试%'ORDER BY id DESC LIMIT 1,sql_id_end_1038)}

八.config.yaml文件介绍

project:
  name: PytestApi
  author: 搬砖客
url:
  url_big_background: http://8.1:8888
  url_iot_platform: http://39.:8080
  url_imotor_ev: http://rdc-dx.com
  url_imotor_prod: https://im.cn
  url_imotor_dev: https://w.cn
  url_imotor: https://web-px.cn
  nginx_url: /imotor-api
  # ding_Webhook:钉钉机器人的webhook
  ding_Webhook: https://oapi.dingtalk.com/robot/send?
# conftest中的账号密码配置
login:
  username: provin
  password: eL0hvAfgEIHDGJWw==
  password_selenium: 2
# 日志配置
log:
  user_name: xzk
  file_name: test.log
  when: S
  interval: 1
  backup: 10
  console_level: INFO
  file_level: DEBUG
#  pattern: '%(module)s - %(funcName)s - %(lineno)d - %(asctime)s - %(name)s - %(levelname)s - %(message)s'
  pattern: '%(levelname)s %(asctime)s  [%(name)s] [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s'
# 数据库配置
mysql:
  host: 8.4.233
  user: root
  password: Imotor@2022
  database: imotor
  port: 3306
# 配置jenkins的ip
host:
  localhost: 127.0.0.1
  jenkins_host: 121.210
# 配置jenkins的port
port:
  jenkins_port: 8080
  localhost: 8080
# sql和dingTalk的值为True的时候表示开启数据库断言和开启钉钉通知
switch:
  sql: True
  dingTalk: False
  # 实时更新用例内容,False时,已生成的代码不会在做变更
  # 设置为True的时候,修改yaml文件的用例,代码中的内容会实时更新
  real_time_update_test_cases: True
# enable为True表示生成测试报告,type为“local”表示本地windows跑,jenkins表示jenkins跑
report:
  enable: True
  type: local

九.如何使用

1.data里面放测试用例
2.自动生成测试代码的使用

​ 文件路径:common/readFileUtils/caseAutomaticControl.py

​ 执行该py文件即可,前提是data中有相应的代码

3.conftest.py的使用

​ 把需要登录的操作,提取全局token的时候写在这边,不要去使用yaml文件

​ conftest.py理解为一个专门存放fixture的配置文件。

conftest.py的优势
​ 当多个test.py同时需要使用一个前置条件,比如登录功能,此时,登录功能不能存放在某一个py中。

​ conftest.py可以完美解决上面问题,能够单独对fixture进行管理。

conftest.py配置文件的注意事项:
​ conftest.py命名是固定的,不可改变。
​ pytest会默认执行conftest.py中的fixture。
​ conftest.py只对同个目录下的py生效。
​ 每个目录都可以有自己的conftest.py文件,一个项目中可以拥有多个conftest.py文件。
​ 执行测试用例时,conftest.py不用手动导入。

4.执行脚本

run_main.py 按照文件中的注释使用即可,后续会优化

5.报告地址

window本地:report/index.html

jenkins:allure-report/index.html

十.实现功能

  • 测试数据隔离, 实现数据驱动
  • 支持多接口数据依赖: 提取返回内容,用于其他用例
  • 数据库断言: 直接在测试用例中写入查询的sql即可断言,无需编写代码
  • 动态多断言: 如接口需要同时校验响应数据和sql校验,支持多场景断言
  • 自动生成用例代码: 测试人员在yaml文件中填写好测试用例, 程序可以直接生成用例代码,纯小白也能使用
  • 返回接口的运行时长
  • 支持单个测试用例的前置和后置操作
  • 日志模块: 打印每个接口用例的日志信息
  • 通知: 目前支持钉钉通知
  • 自定义拓展字段: 如用例中需要生成的随机数据,可直接调用
  • 兼容linux和windows

十一.后续优化

1.数据库断言(已完成,可优化)

2.代码自动生成,已完成

3.钉钉或者邮件发送,已经加了钉钉通知

4.jenkins集成,在linux跑的时候这个有点问题,找找问题还得-优先级4–已完成

5.增加提取数据库返回内容到extract文件中的功能–待完成-优先级3

6.数据库断言需要支持热加载(已完成)

7.接口断言、提取增加或改为jsonpath(已完成,加了热加载)

8.录制脚本–待完成(使用mitmproxy)-优先级4

9.数据库断言改为jsonpath-优先级2

10.代码注释、编写规范 完善–进行中

11.日志优化–待完成-优先级3

12.支持swagger接口文档转成yaml用例–待完成-优先级4

13.老的接口响应断言加上热加载-优先级1

14.多线程执行(待完成,可以使用 pytest-xdist)-优先级2

15.批量修改yaml文件内容(待完成),完成后将"assert_sql" 改为"assert_sql",相关代码适配-优先级2

16.多数据库连接。思路:在每个项目中建conftest文件,进行各自的数据库连接和断开 2.各平台的接口必须写在相应的文件夹内,因为根据用例来连接数据库和断开,容易被封ip

17.自动生成代码,后面也要加开关(在run_main.py中读取配置文件)-优先级3

18.extract提取需要支持jsonpath格式—已完成

你可能感兴趣的:(pytest,python)