Python + pytest + yaml + allure + mysql + redis + 钉钉/企业微信通知,接口自动化框架V2.0,支持多业务处理,仅需维护yaml用例,无需要编写代码

Posted 七月的小尾巴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python + pytest + yaml + allure + mysql + redis + 钉钉/企业微信通知,接口自动化框架V2.0,支持多业务处理,仅需维护yaml用例,无需要编写代码相关的知识,希望对你有一定的参考价值。

python + pytest + allure + yaml + mysql + redis + 企业微信通知

开源接口自动化框架相关操作文档

前言

公司突然要求你做自动化,但是没有代码基础不知道怎么做?或者有自动化基础,但是不知道如何系统性的做自动化,放在yaml文件中维护,不知道如何处理多业务依赖的逻辑?

那么这里 Gitte 中开源的自动化框架,将为你解决这些问题。框架主要使用 python 语言编写,结合 pytest 进行二次开发,用户仅需要在 yaml 文件中编写测试用例,编写成功之后,会自动生成 pytest 的代码,零基础代码小白,也可以操作。

框架中同时支持 mysql 数据库断言和 接口响应断言,并且用例直接在yaml文件中维护,无需编写业务代码,接口pytest框架生成allure报告,并且发送 企业微信通知/ 钉钉通知/ 邮箱通知/ 飞书通知,灵活配置。

实现功能

  • 测试数据隔离, 实现数据驱动
  • 支持多接口数据依赖: 如A接口需要同时依赖B、C接口的响应数据作为参数
  • 数据库断言: 直接在测试用例中写入查询的sql即可断言,无需编写代码
  • 动态多断言: 如接口需要同事校验响应数据和sql校验,支持多场景断言
  • 自动生成用例代码: 测试人员在yaml文件中填写好测试用例, 程序可以直接生成用例代码,纯小白也能使用
  • 统计接口的运行时长: 拓展功能,订制开关,可以决定是否需要使用
  • 日志模块: 打印每个接口的日志信息,同样订制了开关,可以决定是否需要打印日志
  • 钉钉、企业微信通知: 支持多种通知场景,执行成功之后,可选择发送钉钉、或者企业微信、邮箱通知、飞书通知
  • 自定义拓展字段: 如用例中需要生成的随机数据,可直接调用

Gitte地址

接口自动化框架地址: 点我查看.

用例中相关字段的介绍

上方截图,就是一个用例中需要维护的相关字段,下面我会对每个字段的作用,做出解释。

  • case_common: 这个公共参数的维护,方便后期如有需要新增的字段,可以添加在公共参数中,目前只有三个:allureEpicallureFeatureallureStory,这三个都是allure报告需要用到的装饰器内容,后续自动生成 pytest 中 test_case 会用到这三个参数值。

  • spuApplyDetails_01: 用例ID,唯一

  • host: 接口的域名: 填写规则如下 $host,执行脚本时,会去读取conf.yaml 文件中配置域名

  • url: 接口路径

  • header: 请求头

  • requestType: 请求参数类型,有json、file、params、data四种类型

  • is_run: 是否执行,为空、或者 True 都会执行

  • data: 请求参数,所有的请求参数,全部放在 data 下方

  • dependence_case:判断该条用力,是否有依赖业务,如为空或者 false 则表示没有

  • dependence_case_data:依赖用例中需要的相关数据
    1)case_id: 填写该条用用例需要依赖的 case_id
    2)dependent_data:
    1、dependent_type: 支持从依赖的用例中提取该用例响应、请求、或者sql中的数据,目前支持的类型有 responserequestsql三种
    2、jsonpath: 通过jsonpath方法,提取到该条用例中的值
    3、replace_key: 拿到依赖的数据之后,则通过jsonpath方式替换成我们需要的内容。

  • assert: 断言,支持判断sql、或者接口响应内容。

  • type: 可判断 是否相等 ==、不相等 !=、是否包含 IN、不包含 NOTIN

  • value: 期望的值

  • AssertType: 目前自动化支持两种断言类型,接口响应断言和数据库断言。如果是接口响应断言,则AssertType的值可不填,如果值为"SQL"的话,则走数据库断言。为sql的时候,sql查询出来的数据类型是字典类型,因此value值会从sql查询出来的字段中使用jsonpath的形式读取sql查询出来的数据

  • sql:sql 是以 LIST 的类型存储的,可以将我们这个接口需要依赖的sql语句全部放在这里,程序中会循环查询出sql中的所有语句,并且返回数据库中的值,从而与接口响应的值做匹配。(这里也是对于sql多表联查不太会的朋友的福音。如果不会多表联查的话,可以编写单表sql,程序中会将所有单表的数据内容全部查询出来)

如何发送get请求

上方了解了用例的数据结构之后,下面我们开始编写第一个get请求方式的接口。
首先,开始编写项目之后,我们在 conf.yaml 中配置项目的域名

域名配置好之后,我们来编写测试用例,在 data 文件下面,创建一个名称为
spu_appy_list.yaml 的用例文件,内容如下

# 公共参数
case_common:
  allureEpic: 电商平台端
  allureFeature: 审核中心
  allureStory: 商品审核列表


spu_apply_list_01:
  host: $host
  url: /api/v1/work/spu/approval/spuList
  method: GET
  detail: 查看商品审核列表
  headers:
    Content-Type: application/json;charset=UTF-8
    token: work_login_init
  # 请求的数据,是 params 还是 json、或者file
  requestType: params
  # 是否执行,空或者 true 都会执行
  is_run: False
  data:
    spuType: 1
    pageNum: 1
    pageSize: 10
    # 是否有依赖业务,为空或者false则表示没有
  dependence_case:
  # 依赖的数据
  dependence_case_data:
  assert:
    code:
      jsonpath: $.code
      type: ==
      value: 200
      AssertType:
  sql:

get请求我们 requestType 写的是params,这样发送请求时,我们会将请求参数拼接中url中,最终像服务端发送请求的地址格式会为:

$host/api/v1/work/spu/approval/spuList?supType=1&pageNum=1&pageSize=10

如何发送post请求

# 公共参数
case_common:
  allureEpic: 盲盒APP
  allureFeature: 登录模块
  allureStory: 获取登录验证码

send_sms_code_01:
    host: $host
    url: /mobile/sendSmsCode
    method: POST
    detail: 正常获取登录验证码
    headers:
      appId: '23132'
      masterAppId: masterAppId
      Content-Type: application/json;charset=UTF-8
    # 请求的数据,是 params 还是 json、或者file
    requestType: json
    # 是否执行,空或者 true 都会执行
    is_run:
    data:
      phoneNumber: "180xxxx9278"
      # 是否有依赖业务,为空或者false则表示没有
    dependence_case: False
        # 依赖的数据
    dependence_case_data:
    assert:
      code:
        jsonpath: $.code
        type: ==
        value: '00000'
        AssertType:
      success:
        jsonpath: $.success
        type: ==
        value: true
        AssertType:

    sql:

这里post请求,我们需要请求的数据格式是json格式的,那么requestType 则填写为json格式。包括 PUT/DELETE/HEAD 请求的数据格式都是一样的,唯一不同的就是需要配置 reuqestType,如果需要请求的参数是json格式,则requestType我们就填写json,如果是url拼接的形式,我们就填写 params

如何测试上传文件接口

首先,我们将所有需要测试的文件,全部都放在 files 文件夹中

在yaml文件中,我们需要注意两个地方,查看如下示例:

  • requestType: 上传文件,我们需要更改成 file
  • filename 参数名称: 上传文件,我们只需要填写files文件夹下的文件名称即可,程序在发送请求时,会去识别文件
    requestType: file
    # 是否执行,空或者 true 都会执行
    is_run:
    data:
      filename: 排入水体名.png
   
      # 是否有依赖业务,为空或者false则表示没有
    dependence_case: False

多业务逻辑,如何编写测试用例

多业务这一块,我们拿个简单的例子举例,比如登录场景,在登陆之前,我们需要先获取到验证码。


首先,我们先创建一个 get_send_sms_code.yaml 的文件,编写一条发送验证码的用例

# 公共参数
case_common:
  allureEpic: 盲盒APP
  allureFeature: 登录模块
  allureStory: 获取登录验证码

send_sms_code_01:
    host: $host
    url: /mobile/sendSmsCode
    method: POST
    detail: 正常获取登录验证码
    headers:
      appId: '23132'
      masterAppId: masterAppId
      Content-Type: application/json;charset=UTF-8
    # 请求的数据,是 params 还是 json、或者file
    requestType: json
    # 是否执行,空或者 true 都会执行
    is_run:
    data:
      phoneNumber: "180****9278"
      # 是否有依赖业务,为空或者false则表示没有
    dependence_case: False
        # 依赖的数据
    dependence_case_data:
    assert:
      code:
        jsonpath: $.code
        type: ==
        value: '00000'
        AssertType:
      success:
        jsonpath: $.success
        type: ==
        value: true
        AssertType:

    sql:

编写好之后,我们在创建一个 login.yaml 文件

# 公共参数
case_common:
  allureEpic: 盲盒APP
  allureFeature: 登录模块
  allureStory: 登录

login_02:
    host: $host
    url: /login/phone
    method: POST
    detail: 登录输入错误的验证码
    headers:
      appId: '23132'
      masterAppId: masterAppId
      Content-Type: application/json;charset=UTF-8
    # 请求的数据,是 params 还是 json、或者file
    requestType: json
    # 是否执行,空或者 true 都会执行
    is_run:
    data:
      phoneNumber: 18014909278
      code:
      # 是否有依赖业务,为空或者false则表示没有
    dependence_case: True
        # 依赖的数据
    dependence_case_data:
      - case_id: send_sms_code_02
        dependent_data:
          - dependent_type: response
            jsonpath: $.code
            replace_key: $.data.code

    assert:
      code:
        jsonpath: $.code
        type: ==
        value: '00000'
        AssertType:
    sql:

其中处理多业务的核心区域,主要在这里

   dependence_case: True
        # 依赖的数据
    dependence_case_data:
      - case_id: send_sms_code_02
        dependent_data:
          - dependent_type: response
            jsonpath: $.code
            replace_key: $.data.code

首先,我们 dependence_case 需要设置成 True,并且在下面的 dependence_case_data 中设计相关依赖的数据。

  • case_id:上方场景中,我们登录需要先获取验证码,因此依赖的case_id 就是发送短信验证码的 case_id :send_sms_code_02
  • dependent_type:我们依赖的是获取短信验证码接口中的响应内容,因此这次填写的是 response
  • jsonpath: 通过jsonpath 提取方式,提取到短信验证码中的验证码内容
  • replace_key:拿到验证码之后,我们将本条用例中的 登录验证码替换,如下图所示,相当于将我们提取到的响应内容,替换请求参数中的内容

多业务逻辑,需要依赖同一个接口中的多个数据

如果说,我们多业务逻辑,需要依赖同一个接口中的多个数据。
还是拿上方登录距离,假设我们登录时,需要同时或者接口中的 codeaccessToken,那么编写规则如下:

login_02:
    host: $host
    url: /login/phone
    method: POST
    detail: 登录输入错误的验证码
    headers:
      appId: '23132'
      masterAppId: masterAppId
      Content-Type: application/json;charset=UTF-8
      accessToken:
    # 请求的数据,是 params 还是 json、或者file
    requestType: json
    # 是否执行,空或者 true 都会执行
    is_run:
    data:
      phoneNumber: 18014909278
      code:
      # 是否有依赖业务,为空或者false则表示没有
    dependence_case: True
        # 依赖的数据
    dependence_case_data:
      - case_id: send_sms_code_02
        dependent_data:
          # 提取接口响应的code码
          - dependent_type: response
            jsonpath: $.code
            replace_key: $.data.code
          # 提取接口响应的accessToken
          - dependent_type: response
            jsonpath: $.data.accessToken
            # 替换请求头中的accessToken
            replace_key: $.headers.accessToken    

    assert:
      code:
        jsonpath: $.code
        type: ==
        value: 'D0001'
        AssertType:
    sql:

多业务逻辑,需要依赖不同接口的数据

假设我们需要获取 send_sms_code_01get_code_01两个接口中的数据,用例格式如下

    dependence_case: True
        # 依赖的数据
    dependence_case_data:
      - case_id: send_sms_code_01
        dependent_data:
          # 提取接口响应的code码
          - dependent_type: response
            jsonpath: $.code
            replace_key: $.data.code
      - case_id: get_code_01
        dependent_data:
          # 提取接口响应的code码
          - dependent_type: response
            jsonpath: $.code
            replace_key: $.data.code            

用例中需要依赖登录的token,如何设计

首先,为了防止重复请求调用登录接口,pytest中的 conftest.py 提供了热加载机制,看上方截图中的代码,我们需要在 conftest.py 提前编写好登录的代码。

@pytest.fixture(scope="session", autouse=True)
def work_login_init():
    """
    获取平台端的token信息
    :return:
    """
    login_yaml = CaseData(ConfigHandler.data_path + 'Login/login.yaml').case_process()[0]
    res = RequestControl().http_request(login_yaml)
    # 将token写入缓存中
    if res[0] is not False:
        token = res[0]['data']['token']
        Cache('work_login_init').set_caches(token)
        return token
    else:
        WARNING.logger.warning("登录用例设置的是不执行,无法获取到token信息")

如上方代码所示,我们会先去读取login.yaml文件中的用例,然后执行获取到响应中的token,然后 编写 Cache('work_login_init').set_caches(token),将token写入缓存中,其中 work_login_init 是缓存名称。


编写好之后,我们会在 requestControl.py 文件中,读取缓存中的token,如果该条用例需要依赖token,则直接进行内容替换。


这里在编写用例的时候,token 填写我们所编写的缓存名称即可。

用例中如何生成随机数据

比如我们有些特殊的场景,可能会涉及到一些定制化的数据,每次执行数据,需要按照指定规则随机生成。


如上图所示,我们用例中的 reason 审核原因后方,需要展示审核的当前时间。那么我们首先需要封装一个获取当前时间的方法


那么我们就在 regularControl.py 文件中,编写 get_time 的方法。编写好之后,在用例中编写规则如下:

reason: 审核时间$get_time

使用 $函数名称的方法,程序调用时,会生成当前时间。在regularControl.py 文件中,我还封装了一些常用的随机数,如随机生成男生姓名、女生姓名、身份证、邮箱、手机号码之类的,方便大家使用。 如,随机生成邮箱,我们在用例中编写的格式为 $get_email

其他所需随机生成的数据,可在文件中自行添加。

用例中如何进行接口断言和数据库断言

假设现在我需要测试一个报表统计的数据,该接口返回了任务的处理时长 和 处理数量。功能如下截图所示:

假设下方是我们拿到接口响应的数据内容:

"code": 200, "times": 155.91, "counts": 9

这个时候,我们需要判断该接口返回的数据是否正确,就需要编写sql,对响应内容进行校验。


因此我们编写了如上sql,查出对应的数据,那么用例中编写规则如下,下方我们分别断言了两个内容,一个是对接口的响应code码进行断言,一个是断言数据库中的数据。

  assert:
    code:
      jsonpath: $.code
      type: ==
      value: 200
      # 断言接口响应时,可以为空
      AssertType:
   do_time:
   	 # jsonpath 拿到接口响应的数据
      jsonpath: $.times
      type: ==
      # sql 查出来的数据,是字典类型的,因此这里是从字段中提取查看出来的字段
      value: $.do_time
      # 断言sql的时候,AssertType 的值需要填写成 SQL
      AssertType: SQL
   question_counts:
      jsonpath: $.counts
      type: ==
      # 
      value: $.question_counts
      # 断言sql的时候,AssertType 的值需要填写成 SQL
      AssertType: SQL 
  sql:
    - select * from test_goods where shop_id = 515

我们分别对用例的数据进行讲解,首先是响应断言, 编写规则如下

    code:
      # 通过jsonpath获取接口响应中的code "code": 200, "times": 155.91, "counts": 9
      jsonpath: $.code
      type: ==
      value: 200
      # 断言接口响应时,可以为空
      AssertType:

下面是对sql进行断言

   question_counts:
   	  # 断言接口响应的问题上报数量counts "code": 200, "times": 155.91, "counts": 9
      jsonpath: $.counts
      type: ==
      # 查询sql,我们数据库查到的数据是一个字段,数据是这样的:question_counts: 13, do_time: 1482.70, 这里我们通过 jsonpath获取question_counts
      value: $.question_counts
      # 断言sql的时候,AssertType 的值需要填写成 SQL
      AssertType: SQL 
  sql:
    - SELECT round( sum(( UNIX_TIMESTAMP( filing_time )- UNIX_TIMESTAMP( report_time )) / 60 ) / 60, 2 ) AS do_time, count( id ) AS question_counts FROM fl_report_info WHERE state IN ( 1, 3 )

有些细心的小伙伴会发现,我们的sql,是列表类型的。这样就意味这,我们的sql可以同时编写多条,这样会对不会编写多表联查的小伙伴比较友好,可以进行单表查询,获取我们需要的数据。

sql:
  - select * from users;
  - select * from goods;

自动生成test_case层代码

小伙伴们在编写好 yaml 用例之后,可以直接执行 caseAutomaticControl.py ,会跟你设计的测试用例,生成对应的代码。

发送钉钉通知通知

1、首先第一步,我们需要创建一个钉钉群,然后添加机器人

2、点击添加机器人

3、选择自定义机器人


4、选择加签模式,复制密钥


5、选择复制webhook

钉钉通知展示内容如下:

7、通知类型改成1,钉钉通知

配置邮箱通知

发送邮箱通知,邮箱通知是自动化中配置比较常见的,大家讲发送人、收件人、以及邮箱stamp_key改成自己对应的就行。

这里提供了如何配置QQ邮箱的授权码,不知道的同学,可自行查看。链接: 点我查看.

企业微信通知


1、上方是企业微信通知的模板,首先我们需要创建一个企业微信群,右键点击群,会出现如下弹窗,点击添加群机器人

2、点击新创建一个机器人


3、设置机器人名称

4、最后会出现这个webhook地址


5、下面,我们在conf.yaml文件中,找到企业微信配置,更改成对应的内容即可。

日志打印装饰器

在requestControl.py中,我单独封装了一个日志装饰器,需要的小伙伴可以不用改动代码,直接使用,如果不需要,直接注释,或者改成False。控制台将不会有日志输出

统计用例运行时长


同样,这里封装了一个统计用例运行时长的装饰器,使用改装饰器前,需要先进行导包

from utils.logUtils.runTimeDecoratorl import execution_duration

导入之后,调用改装饰器,装饰器中填写的用例执行时长,以毫秒为单位,如这里设置的2000ms,那么如果该用例执行大于2000ms,则会输出一条告警日志。

@execution_duration(2000)

生成allure报告


我们直接运行主程序,运行完成之后,就可以生成漂亮的allure报告啦~

以上是关于Python + pytest + yaml + allure + mysql + redis + 钉钉/企业微信通知,接口自动化框架V2.0,支持多业务处理,仅需维护yaml用例,无需要编写代码的主要内容,如果未能解决你的问题,请参考以下文章

Python + pytest + yaml + allure + mysql + redis + 钉钉/企业微信通知,接口自动化框架V2.0,支持多业务处理,仅需维护yaml用例,无需要编写代码

Python + pytest + yaml + allure + mysql + redis + 钉钉/企业微信通知,接口自动化框架V2.0,支持多业务处理,仅需维护yaml用例,无需要编写代码

pytest文档72- 使用 template 替换 yaml 文件的变量

python+requests+pytest+yaml/json+Allure+jenkins+docker接口自动化框架保姆级教学

pytest + yaml 框架 -5.调用内置方法和自定义函数

pytest + yaml 框架 -18.sleep 和skip/skipif 功能实现