企业微信实战练习

霍格沃兹测试开发学社

ceshiren.com

目录

  • 学习价值
  • 知识点梳理
  • 成果展示
  • 实战思路

学习价值

  • 接口测试
  • 接口自动化测试

接口自动化测试常见问题

  1. 写接口自动化测试用例时,你使用了 requests 库,那大概使用到了 requests 的哪里内容?
  2. 接口自动化实现思路?
  3. 其他接口都需要登录接口的信息,怎么去让这个登录的接口只在其他接口调用一次?
  4. 接口产生的垃圾数据如何清理?
  5. 接口响应值嵌套较深,获取不方便怎么办?
  6. 接口的返回字段特别多,结构特别复杂时,如何做断言?

知识点梳理

详见思维导图

成果展示


├── api
│   ├── __init__.py
│   ├── tag.py
│   ├── user.py
│   └── wework_api.py
├── config
│   ├── __init__.py
│   ├── dev.yaml
│   ├── test.yaml
│   └── wework_config.py
├── testcase
│   ├── __init__.py
│   ├── schema.json
│   ├── test_tag.py
│   ├── test_tag_user.py
│   ├── test_tag_user_flow.py
│   └── test_user.py
└── utils
    ├── __init__.py
    ├── log_utils.py
    └── schema_utils.py
    └── jsonpath_utils.py

企业微信实战练习

  • 被测产品介绍
  • 测试需求
  • 实战思路

被测产品

  • 接口设计规范。
  • 接口文档详细。
  • 属于名企产品。

企业微信是腾讯微信团队打造的企业通讯与办公工具,具有与微信一致的沟通体验,丰富的 OA 应用,和连接微信生态的能力,可帮助企业连接内部、连接生态伙伴、连接消费者。专业协作、安全管理、人即服务。

环境准备

  1. 企业微信注册(有手机号即可)。
  2. 企业微信白名单配置: https://ceshiren.com/t/topic/22768

测试需求

  • 针对于企业微信的标签功能完成接口自动化测试的架构优化

优化前的代码

"""
__author__ = '霍格沃兹测试开发学社'
__desc__ = '更多测试开发技术探讨,请访问:https://ceshiren.com/t/topic/15860'
"""
import jsonpath
import requests

from wework_interface_test.utils.log_utils import log


class TestWework:

    def setup_class(self):
        app_id = "ww93348658d7c66ef4"
        secret = "T0TFrXmGYel167lnkzEydsjl6bcDDeXVmkUnEYugKIw"
        token_url = f"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={app_id}&corpsecret={secret}"
        r = requests.get(token_url)
        self.token = r.json()["access_token"]

    def test_create_tag(self):
        """
        1. 创建
        2. 查询
        3. 删除(数据清理)
        :return:
        """
        tag_body = {"tagname": "AD测试2", }
        url = f"https://qyapi.weixin.qq.com/cgi-bin/tag/create?access_token={self.token}"
        r = requests.post(url, json=tag_body)
        tag_id = r.json().get("tagid")
        create_tag_result = r.json().get("errcode")
        log.info(f"创建标签的标签为{tag_id}")
        list_url = f"https://qyapi.weixin.qq.com/cgi-bin/tag/list?access_token={self.token}"
        r2 = requests.get(list_url)
        log.info("查询标签")
        list_resutl = jsonpath.jsonpath(r2.json(), f"$..taglist[?(@.tagid=={tag_id})]")
        delete_url = f"https://qyapi.weixin.qq.com/cgi-bin/tag/delete?access_token={self.token}"
        r3 = requests.get(delete_url, params={"tagid": tag_id})
        log.info(f"删除的标签为{r3.json()}")
        # 断言创建接口响应信息为正确
        assert create_tag_result == 0
        # 断言通过id获取的tag信息不为空
        assert list_resutl



    def test_update_tag(self):
        # 1. 查询tag
        # 2. 更新
        # 3. 查询
        log.info("查询标签")
        list_url = f"https://qyapi.weixin.qq.com/cgi-bin/tag/list?access_token={self.token}"
        r2 = requests.get(list_url)
        tag_id_list_resutl = jsonpath.jsonpath(r2.json(), f"$..tagid]")
        update_tag_id = tag_id_list_resutl[0]
        log.info(f"要更新的标签为{update_tag_id}")
        update_url = f"https://qyapi.weixin.qq.com/cgi-bin/tag/update?access_token={self.token}"
        update_data = {"tagid": update_tag_id, "tagname": "ADD2"}
        r3 = requests.post(update_url, json= update_data)
        update_tag_errcode = r3.json().get("errcode")
        log.info(f"查询id为{update_tag_id}的标签名称")
        list_url = f"https://qyapi.weixin.qq.com/cgi-bin/tag/list?access_token={self.token}"
        r4 = requests.get(list_url)
        list_result = jsonpath.jsonpath(r4.json(), f"$..taglist[?(@.tagid=={update_tag_id})].tagname")
        # 断言创建接口响应信息为正确
        assert update_tag_errcode == 0
        # 断言更新的tag名称为正确的
        assert list_result[0] == "ADD2"
    def test_list_tag(self):
        # 1. 展示tag
        # 2. 断言展示信息
        ...

    def test_delete_tag(self):
        # 1. 创建tag
        # 2. 删除tag
        # 3. 查询tag
        ...

    def test_addtagusers(self):
        # 1. 添加标签成员
        # 2. 获取标签成员
        # 3. 删除标签成员
        ...

    def test_tag_flow(self):
        # 1. 创建标签
        # 2. 更新标签
        # 3. 添加标签成员
        # 4. 获取标签成员
        # 5. 删除标签
        ...

    def test_tag_flow_fail(self):
        # 1. 创建标签
        # 2. 删除标签
        # 3. 添加标签成员失败
        ...

实战思路

相关知识点

  1. 代码架构优化。
  2. token 复用。
  3. 多环境切换。
  4. 复杂结构响应断言

优化代码架构

token 复用

在获取token 请求之前,先判断token 是否存在。

  • 如果不存在,则获取。
  • 如果存在,则跳过。

练习

将代码进行优化,要求:

  1. 日志打印。
  2. 接口和业务(用例)分离。
  3. 添加token的过程不要体现在接口中。
  4. 针对于嵌套层级较深的响应,优化提取方式。

进阶练习1:多环境切换场景优化

  • 结合录播:
    • 《多套被测环境》

进阶练习2:整体结构响应断言

# 整体结构响应断言
class SchemaUtils:
    @classmethod
    def schema_validate_by_file(cls, obj,file_path):
        schema_data = json.load(open(file_path))
        return cls.schema_validate(obj, schema_data)
    @classmethod
    def schema_validate(cls, obj, schema):
        '''
        对比 python 对象与生成的 json schame 的结构是否一致
        '''
        try:
            validate(instance=obj, schema=schema)
            return True
        except Exception as e:
            log.error(f"schema 校验异常 =======> {e}")
            return False
  • 结合录播:
  • 《整体结构响应断言》

进阶练习3:多层嵌套响应断言

jsonpath.jsonpath(r2, f"$..taglist[?(@.tagid=={tag_id})]")
  • 结合录播:
  • 《多层嵌套响应断言》

接口自动化测试常见问题(一)

  1. 写接口自动化测试用例时,你使用了 requests 库,那大概使用到了 requests 的哪里内容?
    • 知识点梳理。
  2. 接口自动化实现思路?
    • 练习思路。
  3. 其他接口都需要登录接口的信息,怎么去让这个登录的接口只在其他接口调用一次?
    • 获取token的之前添加判断,如果存在则不获取。

接口自动化测试常见问题(二)

  1. 接口产生的垃圾数据如何清理?
    • 方式一:专门准备一个自动化测试环境,测完直接做数据回滚
    • 方式二:每次创建完数据,都调用delete接口删除
    • 注意:尽量不要用数据库直接删除,容易引起bug
  2. 接口响应值嵌套较深,获取不方便怎么办?
    • JsonPath 表达式提取。
  3. 接口的返回字段特别多,结构特别复杂时,如何做断言?
    • JsonSchema 做结构断言。

知识点总结

我们今天学习的内容:

  1. 知识点梳理。
  2. 企业微信实战练习。
  3. 接口自动化测试常见问题的梳理。