接口测试 浅谈一下自己的接口自动化落地与实现,顺便希望各位提出意见进行完善

姜衍 · 2022年06月18日 · 最后由 姜衍 回复于 2022年06月28日 · 4743 次阅读

由于刚来到咱们社区 第一次发帖,而且文笔不好,编程技术也烂的要死,直接讲述我的框架设计思路

使用的是 Pytest+Requests+Allure 框架
然后使用的 pytest 的参数化来进行运行接口测试数据

目前的项目目录:

common:公共方法封装 (yaml 操作,Requests 封装,assert 封装)
config:环境配置信息以及账号 token 等
data:接口测试数据
logs:pytest 配置后自动生成的日志
reports 和 temps:allure 测试报告
testcases:测试用例存

request 封装:

config 配置的环境数据以及接口地址,账号 token,请求头,请求体等等需要使用的东西

data:
接口测试数据存放,一个 yaml 对应一个接口,一个 list 对应一条测试用例
格式可自己设定,我目前是存储 Url,用例信息,schema 库的响应结果格式校验,和预期结果

logs 配置:
在 pytest.in

输出来的格式
INFO     root:test_mimu.py:37 模块名称: 物品收藏,测试目的: 物品收藏成功 ,响应状态码: 200,响应结果: {"msg":"成功","code":0,"data":true}

testcases:

conftest: 存储公共接口 (关联),如登录,等
然后就是测试用例

@allure.epic("移动端-接口测试")
class TestMain:
    def setup_class(self):
        self.req = RequestHandler()
        self.logger = logging

    @user2ize('args', yaml_case_data())
    def test_mimu_api(self, args):
        if args['case_name'] is not None:
            # 动态生成标题
            allure.dynamic.title(args['case_name'])
        # 动态获取级别信息
        if args['severity'] is not None:
            allure.dynamic.severity(args['severity'])
        # 动态获取模块名称
        if args['feature'] is not None:
            allure.dynamic.feature(args['feature'])
        # 动态获取用例功能名称
        if args['story'] is not None:
            allure.dynamic.story(args['story'])

        url = get_url(args['url'])
        payload = args['body']
        token = read_yaml('config/config.yaml')['token']
        headers = request_header(payload, token)
        with allure.step("接口请求"):
            response = self.req.visit("POST", url, headers=headers, json=payload)
        response_json = response.text
        self.logger.info('模块名称: {},测试目的: {} ,响应结果: {}'.format(args['story'], args['case_name'], response_json))
        response_body_check(args, response)
        return response_json

    def teardown_class(self):
        self.logger.info("测试用例执行完毕")

思路:
调用封装的 yaml 方法,循环读取 data 目录下的所有 yaml 文件,然后将所有 yaml 文件内的数据读取出来,存入一个 List 内,然后使用参数化方法进行循环执行与断言校验。如果报错就用例执行失败并在日志和 allure 测试报告内详细展示报错原因

各位多多担待,第一次写,技术菜,文本菜😋

共收到 20 条回复 时间 点赞

config 配置的一些公共接口,比如登录
配置里面存放公共接口?这个点从概念上就是有点问题,要么把登录接口作为前置步骤,放到测试用例的前置;要么把固定 token 作为预设变量存储在全局变量池。

  1. 断言方面可以更精准一点,比如某个字段的某个值的校验(这里推荐使用 jsonpath) 2.可以调研下,是否能够模板化生成测试用例代码,因为多数测试步骤是统一的,唯一变的是一些参数化的数据 自己对自动化测试用例的一些浅显认知,欢迎互相交流

可以分层再细一点,底层 加一些日志,也可以加一个 API 层,因为通常接口和用例都是一对多的关系,接口参数相互关联。比如上一个接口的响应,下一个接口要做为参数。接口参数要做参数化。

这项目的 token。。。好像是固定的?!

dongfanger 回复

抱歉说错了 公共接口存放在 testcases/conftest 内😂

AllisonLiu 回复

这方面已经在做了,我们公司使用的 APIfox 来维护的接口测试文档,然后该应用有 web 版,思路是每次启动项目时抓包获取 apifox 项目内的所有接口文档,进行比对校验,如有未编写的接口测试数据,就获取生成 yaml 自动存放在 data 内,自动化运行的时候会自动便利所有 data 下的 yaml 接口😁

dongfanger 回复

然后 token 的话,是每次运行自动更新的

AllisonLiu 回复

断言的话目前是先判断接口的网络状态码,然后是接口响应的业务状态码和 msg 的内容信息,最后是整体响应格式,像你说的这种方法我也考虑过,但是综合来讲还是得根据测试目的进行设计断言,然后项目如果稳定迭代的话,基本只需要验证一下接口的正向用例即可,一般异常通常是校验一些新加的接口,这些可以单独拉出来进行一组测试。

小叮当 回复

不是 每次运行都会生成新的 token 供其使用

姜衍 #10 · 2022年06月20日 Author
Kevin.zhao 回复

目前不用分层 因为有参数关联的接口,统一放进 conftest 内进行执行存储到 config 内供接口调用读取进行请求了

是不是每个 yaml 用例文件都需要一份与之对应的 testcases 脚本
如果是 get 的下面就需要变动一下

with allure.step("接口请求"):
response = self.req.visit("POST", url, headers=headers, json=payload)

姜衍 #12 · 2022年06月20日 Author
王中 回复

因为我目前项目皆是 post 所以未对请求进行参数化,如果你有很多种接口方式的测试数据时
可在 yaml 文件内增加个字段 为请求方式 然后
with allure.step("接口请求"):
response = self.req.visit(请求方式, url, headers=headers, json=payload)

姜衍 #13 · 2022年06月20日 Author
王中 回复

不需要 因为我目前设计,是循环读取 data 文件内所有 yaml 数据,然后参数化请求接口,如果我需要编写新的接口测试用例的话,直接创建一个 yaml 文件,写几个接口 list 数据即可

14楼 已删除

我也是新手,提几个意见哈哈哈哈。首先是需要新建一个 api 层,毕竟一个接口需要多个地方调用,不能每次都重新写接口吧。然后是 yml 测试用例不要搞这么多,可以一个模块用一份 yml,不然文件太乱了想找都找不到。最后就是之前有人说的,需要一个 log 模块来打印日志~

姜衍 #16 · 2022年06月20日 Author
Yasashii 回复

我已经更新了一下帖子内容 可以看 data 图
就是按照模块进行划分 然后 api 层目前没必要 你也可以看我评论回复别人的 一个接口需要多个地方调用的我都会放入 conftest 内 或者封装成公共方法
我目前就是因为请求头有特殊校验 然后就讲获取特殊校验的接口封装到请求方法内 每次请求任何接口都会调用一下

姜衍 #17 · 2022年06月20日 Author

如果一个 yaml 对应一个模块 你想过如果一个模块可能有十几个接口呢 然后每个接口可能有七八组测试数据 你维护不麻烦吗 而且如果有些接口改动或者弃用 你删除或者维护数据不麻烦吗

姜衍 #18 · 2022年06月20日 Author
Yasashii 回复

老哥是不是没有认真看我的图和帖子内容呀 log 有的

然后发出来的代码 也有 log 代码呀 而且都会记录到单独的文件 以及 allure 测试报告内

姜衍 回复

那如果是 get 请求的话 是不是需要改动下 json=payload 用 param=

user2ize 装饰器怎么实现的呢

姜衍 #21 · 2022年06月28日 Author
大帅 回复

封装个读取目录下所有 yaml 文件的方法, 循环出来后将所有 yaml 内容读取出来,然后使用装饰器运行就行了

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册