• 4.测试案例实现代码库与测试用例V2.0


    测试案例实现代码库与测试用例V2.0

    接口分析

    • 1、接口认证机制--cookies
      • 存储在请求头中
    • 2、接口风格---restful
      • 数据格式为json
      • 请求方法
        • 查询:GET
        • 增加:POST
        • 修改:PUT
        • 删除:DELETE

    面临的问题

    • 接口众多如何快速开发?
    • API之前相同,且有规律

    APIObject设计模式

    • rest风格的接口特点
      • 增加--POST
      • 修改--PUT
      • 删除--DELETE
      • 查询--GET

    按照面向对象的思路,把接口进行重新设计一遍

    • BaseAPI的设计
      • 统一增删改查API
      • 接口参数模板化
      • 接口数据与测试脚本分离

    图 48

    在common中新增一个类

    class BaseAPI:
        path="???"
        payload="???"
        #增加
        def add(self):
            pass
        #修改
        def edit(self):
            pass
        #删除
        def delete(self):
            pass
        #查询
        def list_all(self):
            pass
        #删除所有
        def delete_all(self):
            pass
    

    但是path和payload怎么处理,每个接口都不一样,新增一个配置文件,通过读取配置文件来获取

    配置文件

    api_conf.yml

    OrganizAPI:
      path: /api/v4/organizations
      add:
        {
          "name": "utuytut",
          "parent": "qpG8DsWSaY8FAwWxN",
          "sort_no": 100,
          "hidden": false,
          "space": "NhnKCEchFReJbgqZM"
        }
    
      edit:
        {
          "name": "testccc",
          "parent": "qpG8DsWSaY8FAwWxN",
          "sort_no": 100,
          "hidden": false,
          "space": "NhnKCEchFReJbgqZM"
        }
    

    修改的请求体不一样,多了一层$set

    {
    "$set": {
     "name": "testccc",
     "parent": "qpG8DsWSaY8FAwWxN",
     "sort_no": 100,
     "hidden": false,
     "space": "NhnKCEchFReJbgqZM"
    }
    }
    

    配置文件,只放set对应的value,跟上面的add保持一致,后面传参的时候再把$set加进去
    现在配置文件有了,那我们需要把它读取出来

    读取配置文件

    在pylib下面配置一个通用的文件夹,utils,再在此文件夹下面新增一个config.py文件
    然后定义一个读取yml文件的方法:def read_yml(path):

    import yaml
    def read_yml(path):
        with open(path,encoding='utf-8') as f :
            content=f.read()
            data=yaml.safe_load(content)
            return data 
    
    

    测试下能不能正常读取到内容

    if __name__ == '__main__':
        print(read_yml('../../conf/api_conf.yml'))
    
    输出:
    {'OrganizAPI': {'path': '/api/v4/organizations', 'add': {'name': 'utuytut', 'parent': 'qpG8DsWSaY8FAwWxN', 'sort_no': 100, 'hidden': False, 'space': 'NhnKCEchFReJbgqZM'}, 'edit': {'name': 'testccc', 'parent': 'qpG8DsWSaY8FAwWxN', 'sort_no': 100, 'hidden': False, 'space': 'NhnKCEchFReJbgqZM'}}}
    

    分析发现每个接口的增删改查接口的path都是一样,那么只需要在实例化的时候读取出来就可以了

    • 注意,以后测试用例都是从根目录开始,现在需要变换相对路径,要从项目根目录开始

    BaseAPI

    class BaseAPI:
        def __init__(self):
            self.api_conf=read_yml('conf/api_conf.yml')['OrganizAPI']
    

    写死OrganizAPI,这样有一个问题,目前只能读取到OrganizAPI,如果是其他api就读取不到数据

    观察发现,刚才读取的数据,这个key跟类名相同
    如何取当前类名

        def __init__(self):
            currrent_name=self.__class__.__name__
            self.api_conf=read_yml('conf/api_conf.yml')[currrent_name]
    

    可以在business里面初始化一个OrganizAPI,ContractsAPI分别测试下获取的类名是否正确

    接下来直接实现baseapi的增删改查
    def add(self,name='lily',age=11):

    不确定入参是多少个的时候,且入参是关键字参数,可与采用字典形式传参
    def add(self,**kwargs):
    下面是要处理哪些数据是动态替换的,哪些数据是可以写死的

    space从登录返回的cookie里面获取cookies['X-Space-Id']

    <RequestsCookieJar[<Cookie X-Access-Token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7InRva2VuIjoiMTdjOGE0NjVkNDRlNGUzNzBmNTE5OWUzNmYxNjFhN2NiN2I1NDI4MTQ4MDNiOWYwNzg4YTk2MDY4ZDg0YmIwOGI2ZDFkODgyMzMzZjg4ODY2OTA1MDgiLCJpc0ltcGVyc29uYXRlZCI6ZmFsc2UsInVzZXJJZCI6IjVmZDg3NDM0YjQyODAzMDAxMmYyNjFiZiJ9LCJpYXQiOjE2Mjc4MjI3ODYsImV4cCI6MTYzNTU5ODc4Nn0.NYJ-z5iA30i5Vd3xq4QnJ3X1a-pzUUmgEnRlguXRHSQ for 120.27.146.185/>, <Cookie X-Auth-Token=17c8a465d44e4e370f5199e36f161a7cb7b542814803b9f0788a96068d84bb08b6d1d882333f8886690508 for 120.27.146.185/>, <Cookie X-Space-Id=tY4wsv85gTFhk6B5N for 120.27.146.185/>, <Cookie X-Space-Token=tY4wsv85gTFhk6B5N,17c8a465d44e4e370f5199e36f161a7cb7b542814803b9f0788a96068d84bb08b6d1d882333f8886690508 for 120.27.146.185/>, <Cookie X-User-Id=5fd87434b428030012f261bf for 120.27.146.185/>]>

    tY4wsv85gTFhk6B5N

    class BaseAPI:
        def __init__(self,cookies):
            currrent_name=self.__class__.__name__
            self.api_conf=read_yml('conf/api_conf.yml')[currrent_name]
            self.path=self.api_conf['path']
            self.cookies=cookies
            self.space =cookies['X-Space-Id']#跟随管理员用户
        #增加
        def add(self,**kwargs):
            url=f'{host}{self.path}'
            payload=self.api_conf['add']#通过模板取数据
            payload.update(kwargs)#处理动态替换数据,dict = {'Name': 'Zara', 'Age': 7},dict2 = {'Sex': 'female' },dict.update(dict2)
            payload['space']=self.space
            res =requests.post(url,json=payload,cookies=self.cookies)
            return res.json()['value'][0]#返回数据在value的唯一一个元素中
    

    完整代码

    class BaseAPI:
        def __init__(self,cookies):
            #取当前类名
            current_name=self.__class__.__name__
            #通过类名获取api的配置信息
            self.api_conf=read_yml('conf/api_conf.yml')[current_name]
            self.path=self.api_conf['path']#获取URL的path
            self.cookies=cookies#初始化的时候传递cookies信息
            self.space =cookies['X-Space-Id']#跟随管理员用户,空间ID
        #增加
        def add(self,**kwargs):
            url=f'{host}{self.path}'
            payload=self.api_conf['add']#通过模板取数据
            payload.update(kwargs)#处理动态替换数据,dict = {'Name': 'Zara', 'Age': 7},dict2 = {'Sex': 'female' },dict.update(dict2)
            payload['space']=self.space
            res =requests.post(url,json=payload,cookies=self.cookies)
            return res.json()['value'][0]#所有新增接口返回数据在value的唯一一个元素中
        #修改
        def edit(self,_id,**kwargs):
            url=f'{host}{self.path}/{_id}'
            payload=self.api_conf['edit']
            payload.update(kwargs)
            payload['space']=self.space
            data={}
            data['$set'] =payload
            res =requests.put(url,json=data,cookies=self.cookies)
    
        #删除
        def delete(self,_id):
            url =f'{host}{self.path}/{_id}'
            res =requests.delete(url,cookies=self.cookies)
            return res.json()
    
        #查询所有
        def list_all(self):
            url=f'{host}{self.path}'
            res =requests.get(url,cookies=self.cookies)
            return res.json()['value']
    
        #删除所有
        def delete_all(self):
            lists=self.list_all()
            for list in lists:
                self.delete(list['_id'])
    
  • 相关阅读:
    分布式锁实战,分布式锁方案选择
    数据库索引调优技巧
    GraphQL
    PDF添加水印
    word添加水印,.NET执行宏
    『OpenCV』在Cmake中设置指定的OpenCV路径
    『论文笔记』ArcFace: Additive Angular Margin Loss for Deep Face Recognition
    Dapr微服务应用开发系列3:服务调用构件块
    ClearLinux安装教程
    tail命令学习实例
  • 原文地址:https://www.cnblogs.com/xiehuangzhijia/p/15087842.html
Copyright © 2020-2023  润新知