4 Star 16 Fork 2

aken / SimpleAPI

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

SimpleAPI

依赖软件

Python3.8以上
Allure
requirements.txt里面的依赖模块

Allure官网地址:https://docs.qameta.io/allure/

导航到 2.1. Installing a commandline

根据截图中的步骤进行操作就能安装成功Allure

image-20220809001202763

当前版本

Base_V0.1

版本说明

Base:非正式版
Release:正式版
Vxxx:版本号

项目简介

SimpleAPI,顾名思义,就是希望让接口测试变得简单

SimpleAPI就是一个自动化测试框架,写这个框架的初衷,是为了给一些想学习自动化,但又无从下手的同学提供一些思路。这个框架我会坚持每周更新,每次更新发生的变化,我都会用“分支”记录下来,供后续每一位想要学习的新同学参考。

SimpleAPI的初始版本是“Base_V0.1”,如果你想学习这个框架,那么,我希望你能从“Base_V0.1”这个版本着手起步。后续的迭代,所有功能都是基于“Base_V0.1”的代码进行优化

特别注意⚠️:Base_V0.1版本的功能还非常简单,目前还不够智能、不够自动化。所以,Base_V0.1版本只是体验、学习为主,不建议直接在生产中使用(通俗点说:不够完善,别造那么多数据先)。到了Base_V0.2版本,我将优化数据的存储方式。Base_V0.2之后,数据格式不再变动,到时候再大量造数据。

项目结构

.								# 项目根目录:SimpleAPI
├── Data						# 用例数据存放目录
│   └── haloLogin				# 用例模块目录
│       └── login.yaml			# 某个接口的用例数据
├── README.md					# 框架说明文档
├── README						# README.md需要的一些图片、文字数据、等
├── Report						# 生成Allure报告数据的存放目录
├── RunInit						# 运行代码前的配置、检测
│   └── createReport.py			# 创建报告目录
├── SystemFile					# 系统依赖文件的存放目录
│   ├── pathEnum.py				# 项目各个目录的绝对路径存放文件
│   ├── readUserConf.py			# 读取YAML文件方法文件
│   └── user.conf.yaml			# 用户配置文档
├── TestCase					# 测试用例存放目录
│   └── test_loginModule.py		# 接口用例
├── Utils						# 工具类存放目录
│   ├── dataUtils				# 数据相关的工具类目录
│   │   ├── setRequestData.py	# 设置请求数据工具类
│   │   └── yamlUtility.py		# YAML文件操作工具类
│   ├── fileUtils				# 文件、目录操作工具类目录
│   │   └── directoryUtils.py	# 目录操作工具类
│   └── requestUtils			# 请求相关的工具类目录
│       └── mergeUrl.py			# 将host和request path合并的方法
├── main.py						# 程序主入口
├── pytest.ini					# pytest配置文件
└── requirements.txt			# 框架依赖的第三方模块

使用说明

用户配置文件

用户配置文件存放位置:SimpleAPI -> SystemFile -> user.conf.yaml

配置文件详细说明

# host配置:在接口测试中,host基本是不改动的,所以可以在这里配置我们的host。发请求前,来这里取对应host数据即可
# evn:环境配置(字段名不能改)
evn:
# host:具体使用哪个环境(字段名不能改,字段值随便改。注意:host的字段值一定要和下面的字段名对应上)
  host: test
# 开发环境(名字、值,都能随便改,上面的host值,和下面4个名,其中一个对上就行了)
  dev: http://175.178.37.196
# 测试环境
  test: http://175.178.37.196
# 预发布环境
  staging: http://175.178.37.196
# 生产环境
  product: http://175.178.37.196

数据构建

注意事项

  • 创造数据前,先创建一个**空文件夹,这个文件夹不要用中文取名,以后这个文件夹的名字还要用的。这个文件夹的作用,主要是用来管理“同一模块”内的所有接口数据。你可以把这个文件夹,当做一个模块看待也行,在我看来,确实就是模块。例如项目结构**中的 Data -> haloLogin,这个文件夹内,主要存放和登录相关的接口数据。
  • 每个接口的数据,都单独拿出来,用一个YAML文件进行管理,切记不要将两个接口的数据都放到同一个文件中。虽然技术上,允许你这么做,但如果你坚持这样做,以后数据将难以维护。
  • 用例文件中,有些字段是必填的。以下是用例字段的说明
    • case_1:用例标记,必填,但名字无所谓 *
    • title:用例标题,可以忽略不写
    • method:请求方法,必填 *
    • path:请求路径,有就填,没有就忽略
    • header:请求头,有就填,没有就忽略
    • params:请求参数,有就填,没有就忽略
    • assert:断言语句,你喜欢,不填也行
  • 创建数据前,请查看 SimpleAPI -> SystemFile -> user.conf.yaml 中的host是否修改。比如你想用**百度**进行测试,那你需要将host改成:https://www.baidu.com

GET请求

# 我们以百度为例子,创建一个百度请求的数据。注意,记得把host改成:https://www.baidu.com
case_1:
  title: 发送个百度请求
  method: get

case_2:
  title: 不存在的路径,请求失败
  method: get
  path: /asdasdad

请求数据解释

case_1:用例的标志,必填
title:用例名称,可以忽略不填
method:请求的方法,必填
path:请求的路径,可以不填

POST请求

请求示例

请求网址: http://175.178.37.196/api/admin/login
请求方法: POST
请求头: Content-Type: application/json
请求体:
	authcode: null
    password: "12345678"
    username: "admin"

请求成功响应示例

{
    "status": 200,
    "message": "OK",
    "devMessage": null,
    "data": {
        "access_token":"67c4442bc8434ea8828b52df03361cac",
        "expired_in":86400,
        "refresh_token":"77e3a390b2444895ba11d837c6b64054"
    }
}

根据以上的示例,我们来设计对应的数据

case_1:
  title: 冒烟用例
  path: /api/admin/login
  method: POST
  header:
    Content-Type: application/json
  params:
    authcode: null
    password: "12345678"
    username: "admin"
  assert:
    - "'OK' == r.json()['message']"
    - 200 == r.status_code

case_2:
  title: 账号不存在,登录失败
  path: /api/admin/login
  method: POST
  header:
    Content-Type: application/json
  params:
    authcode: null
    password: "1234567"
    username: "admin"
  assert: "'用户名或者密码不正确' == r.json()['message']"

case_3:
  title: 密码错误,登录失败
  path: /api/admin/login
  method: POST
  header:
    Content-Type: application/json
  params:
    authcode: null
    password: "12345678"
    username: "admins"
  assert: "'用户名或者密码不正确' == r.json()['message']"

请求数据解释

case_1:用例的标志,必填
title:用例名称,可以忽略不填
method:请求的方法,必填
path:请求的路径,可以不填
header:请求头,可以不填,根据实际情况来就行了
params:请求参数,可以不填,根据实际情况来就行了
assert:断言语句,里面存放Python语法,具体写什么内容,要根据你的用例来

用例编写

from Utils.dataUtils.setRequestData import SetRequestData
from SystemFile.pathEnum import get_path
from requests import request
import logging
import pytest
import allure
import time
import os


# 标记模块名称,最后会在报告中显示
@allure.feature("登录模块")
class TestLogin:
    # 用例文件的路径
    file = os.path.join(os.path.join(get_path("data"), "haloLogin"), "login.yaml")
    # 读取文件中的数据
    case = SetRequestData(file).set_case()

    @allure.story("登录接口测试")  # 用例名称,可以直接写接口名称
    @allure.title("{title}")  # 用例标题
    
    # parametrize是参数化的方法
    @pytest.mark.parametrize("title, url, method, header, paras, assert_str", case)
    
    # 接口用例
    def test_case_1(self, title, url, method, header, paras, assert_str):
        
        # 使用request发送接口请求
        r = request(method=method, url=url, headers=header, json=paras)
        
        # 将请求对象转换成"utf-8"编码
        r.encoding = "utf-8"
        
        # 控制台输出日志
        log = logging.getLogger('响应信息')
        log.setLevel(logging.DEBUG)
        
        # 对响应数据做断言
        if type(assert_str) == type(str()):
            assert eval(assert_str)
            log.info(r.text)
        elif type(assert_str) == type([]):
            for assert_ in assert_str:
                assert eval(assert_)
                log.info(r.text)
                
        time.sleep(5)  # 我这里使用的是测试项目的登录接口,由于不能频繁访问,所以加个等待时间

实践

对于某些Python基础较差的同学来说,可能看完后仍然是一头雾水。不够没关系,学习是需要过程的,没有一天建成的罗马,自然也没有一天就能完全掌握的技术。既然如此,那我们就直接开始实践吧,兄弟们,跟我冲~

我们以CSDN文章搜索接口做个例子

请求示例

请求网址: https://silkroad.csdn.net/api/v2/assemble/list/channel/pc_hot_word?
请求参数:
	user_foormark: 1
    channel_name: pc_hot_word
    size: 20
    platform: pc
    imei: 10_20051326840-1646992611076-531956
请求方法: GET

响应示例

{
    "code": 200,
    "data": {
        "ext": {},
        "size": 10,
        "items": [
            {
                "ext": null,
                "resourceId": "",
                "mediaAssetInfo": null,
                "productId": "python log 青色",
                "reportData": {
                    "eventClick": true,
                    "data": {
                        "mod": "",
                        "extra": "{\"utm_medium\":\"distribute.pc_hot_word.none-task-hot_word-landing-1-python log 青色-null-null.186^v4^control\",\"dist_request_id\":\"1659976388516_95735\"}",
                        "dist_request_id": "1659976388516_95735",
                        "ab_strategy": "default",
                        "index": "1",
                        "strategy": "landing"
                    },
                    "urlParams": {
                        "utm_medium": "distribute.pc_hot_word.none-task-hot_word-landing-1-python log 青色-null-null.186^v4^control",
                        "depth_1-utm_source": "distribute.pc_hot_word.none-task-hot_word-landing-1-python log 青色-null-null.186^v4^control"
                    },
                    "eventView": true
                },
                "recommendType": "ali",
                "index": 1,
                "style": "word_1",
                "strategyId": "landing",
                "productType": "hot_word"
            },
            {
                "ext": null,
                "resourceId": "",
                "mediaAssetInfo": null,
                "productId": "python3 高亮打印",
                "reportData": {
                    "eventClick": true,
                    "data": {
                        "mod": "",
                        "extra": "{\"utm_medium\":\"distribute.pc_hot_word.none-task-hot_word-landing-2-python3 高亮打印-null-null.186^v4^control\",\"dist_request_id\":\"1659976388516_95735\"}",
                        "dist_request_id": "1659976388516_95735",
                        "ab_strategy": "default",
                        "index": "2",
                        "strategy": "landing"
                    },
                    "urlParams": {
                        "utm_medium": "distribute.pc_hot_word.none-task-hot_word-landing-2-python3 高亮打印-null-null.186^v4^control",
                        "depth_1-utm_source": "distribute.pc_hot_word.none-task-hot_word-landing-2-python3 高亮打印-null-null.186^v4^control"
                    },
                    "eventView": true
                },
                "recommendType": "ali",
                "index": 2,
                "style": "word_1",
                "strategyId": "landing",
                "productType": "hot_word"
            },
            {
                "ext": null,
                "resourceId": "",
                "mediaAssetInfo": null,
                "productId": "python print 颜色",
                "reportData": {
                    "eventClick": true,
                    "data": {
                        "mod": "",
                        "extra": "{\"utm_medium\":\"distribute.pc_hot_word.none-task-hot_word-landing-3-python print 颜色-null-null.186^v4^control\",\"dist_request_id\":\"1659976388516_95735\"}",
                        "dist_request_id": "1659976388516_95735",
                        "ab_strategy": "default",
                        "index": "3",
                        "strategy": "landing"
                    },
                    "urlParams": {
                        "utm_medium": "distribute.pc_hot_word.none-task-hot_word-landing-3-python print 颜色-null-null.186^v4^control",
                        "depth_1-utm_source": "distribute.pc_hot_word.none-task-hot_word-landing-3-python print 颜色-null-null.186^v4^control"
                    },
                    "eventView": true
                },
                "recommendType": "ali",
                "index": 3,
                "style": "word_1",
                "strategyId": "landing",
                "productType": "hot_word"
            },
            {
                "ext": null,
                "resourceId": "",
                "mediaAssetInfo": null,
                "productId": "pycharm没有pytest运行",
                "reportData": {
                    "eventClick": true,
                    "data": {
                        "mod": "",
                        "extra": "{\"utm_medium\":\"distribute.pc_hot_word.none-task-hot_word-landing-4-pycharm没有pytest运行-null-null.186^v4^control\",\"dist_request_id\":\"1659976388516_95735\"}",
                        "dist_request_id": "1659976388516_95735",
                        "ab_strategy": "default",
                        "index": "4",
                        "strategy": "landing"
                    },
                    "urlParams": {
                        "utm_medium": "distribute.pc_hot_word.none-task-hot_word-landing-4-pycharm没有pytest运行-null-null.186^v4^control",
                        "depth_1-utm_source": "distribute.pc_hot_word.none-task-hot_word-landing-4-pycharm没有pytest运行-null-null.186^v4^control"
                    },
                    "eventView": true
                },
                "recommendType": "ali",
                "index": 4,
                "style": "word_1",
                "strategyId": "landing",
                "productType": "hot_word"
            },
            {
                "ext": null,
                "resourceId": "",
                "mediaAssetInfo": null,
                "productId": "python assert 失败",
                "reportData": {
                    "eventClick": true,
                    "data": {
                        "mod": "",
                        "extra": "{\"utm_medium\":\"distribute.pc_hot_word.none-task-hot_word-landing-5-python assert 失败-null-null.186^v4^control\",\"dist_request_id\":\"1659976388516_95735\"}",
                        "dist_request_id": "1659976388516_95735",
                        "ab_strategy": "default",
                        "index": "5",
                        "strategy": "landing"
                    },
                    "urlParams": {
                        "utm_medium": "distribute.pc_hot_word.none-task-hot_word-landing-5-python assert 失败-null-null.186^v4^control",
                        "depth_1-utm_source": "distribute.pc_hot_word.none-task-hot_word-landing-5-python assert 失败-null-null.186^v4^control"
                    },
                    "eventView": true
                },
                "recommendType": "ali",
                "index": 5,
                "style": "word_1",
                "strategyId": "landing",
                "productType": "hot_word"
            },
            {
                "ext": null,
                "resourceId": "",
                "mediaAssetInfo": null,
                "productId": "invalid placeholder in string",
                "reportData": {
                    "eventClick": true,
                    "data": {
                        "mod": "",
                        "extra": "{\"utm_medium\":\"distribute.pc_hot_word.none-task-hot_word-landing-6-invalid placeholder in string-null-null.186^v4^control\",\"dist_request_id\":\"1659976388516_95735\"}",
                        "dist_request_id": "1659976388516_95735",
                        "ab_strategy": "default",
                        "index": "6",
                        "strategy": "landing"
                    },
                    "urlParams": {
                        "utm_medium": "distribute.pc_hot_word.none-task-hot_word-landing-6-invalid placeholder in string-null-null.186^v4^control",
                        "depth_1-utm_source": "distribute.pc_hot_word.none-task-hot_word-landing-6-invalid placeholder in string-null-null.186^v4^control"
                    },
                    "eventView": true
                },
                "recommendType": "ali",
                "index": 6,
                "style": "word_1",
                "strategyId": "landing",
                "productType": "hot_word"
            },
            {
                "ext": null,
                "resourceId": "",
                "mediaAssetInfo": null,
                "productId": "python删除目录",
                "reportData": {
                    "eventClick": true,
                    "data": {
                        "mod": "",
                        "extra": "{\"utm_medium\":\"distribute.pc_hot_word.none-task-hot_word-landing-7-python删除目录-null-null.186^v4^control\",\"dist_request_id\":\"1659976388516_95735\"}",
                        "dist_request_id": "1659976388516_95735",
                        "ab_strategy": "default",
                        "index": "7",
                        "strategy": "landing"
                    },
                    "urlParams": {
                        "utm_medium": "distribute.pc_hot_word.none-task-hot_word-landing-7-python删除目录-null-null.186^v4^control",
                        "depth_1-utm_source": "distribute.pc_hot_word.none-task-hot_word-landing-7-python删除目录-null-null.186^v4^control"
                    },
                    "eventView": true
                },
                "recommendType": "ali",
                "index": 7,
                "style": "word_1",
                "strategyId": "landing",
                "productType": "hot_word"
            },
            {
                "ext": null,
                "resourceId": "",
                "mediaAssetInfo": null,
                "productId": "pycharm 创建生成注释",
                "reportData": {
                    "eventClick": true,
                    "data": {
                        "mod": "",
                        "extra": "{\"utm_medium\":\"distribute.pc_hot_word.none-task-hot_word-landing-8-pycharm 创建生成注释-null-null.186^v4^control\",\"dist_request_id\":\"1659976388516_95735\"}",
                        "dist_request_id": "1659976388516_95735",
                        "ab_strategy": "default",
                        "index": "8",
                        "strategy": "landing"
                    },
                    "urlParams": {
                        "utm_medium": "distribute.pc_hot_word.none-task-hot_word-landing-8-pycharm 创建生成注释-null-null.186^v4^control",
                        "depth_1-utm_source": "distribute.pc_hot_word.none-task-hot_word-landing-8-pycharm 创建生成注释-null-null.186^v4^control"
                    },
                    "eventView": true
                },
                "recommendType": "ali",
                "index": 8,
                "style": "word_1",
                "strategyId": "landing",
                "productType": "hot_word"
            },
            {
                "ext": null,
                "resourceId": "",
                "mediaAssetInfo": null,
                "productId": "python递归函数中的静态变量",
                "reportData": {
                    "eventClick": true,
                    "data": {
                        "mod": "",
                        "extra": "{\"utm_medium\":\"distribute.pc_hot_word.none-task-hot_word-landing-9-python递归函数中的静态变量-null-null.186^v4^control\",\"dist_request_id\":\"1659976388516_95735\"}",
                        "dist_request_id": "1659976388516_95735",
                        "ab_strategy": "default",
                        "index": "9",
                        "strategy": "landing"
                    },
                    "urlParams": {
                        "utm_medium": "distribute.pc_hot_word.none-task-hot_word-landing-9-python递归函数中的静态变量-null-null.186^v4^control",
                        "depth_1-utm_source": "distribute.pc_hot_word.none-task-hot_word-landing-9-python递归函数中的静态变量-null-null.186^v4^control"
                    },
                    "eventView": true
                },
                "recommendType": "ali",
                "index": 9,
                "style": "word_1",
                "strategyId": "landing",
                "productType": "hot_word"
            },
            {
                "ext": null,
                "resourceId": "",
                "mediaAssetInfo": null,
                "productId": "python获得一个目录下所有结构",
                "reportData": {
                    "eventClick": true,
                    "data": {
                        "mod": "",
                        "extra": "{\"utm_medium\":\"distribute.pc_hot_word.none-task-hot_word-landing-10-python获得一个目录下所有结构-null-null.186^v4^control\",\"dist_request_id\":\"1659976388516_95735\"}",
                        "dist_request_id": "1659976388516_95735",
                        "ab_strategy": "default",
                        "index": "10",
                        "strategy": "landing"
                    },
                    "urlParams": {
                        "utm_medium": "distribute.pc_hot_word.none-task-hot_word-landing-10-python获得一个目录下所有结构-null-null.186^v4^control",
                        "depth_1-utm_source": "distribute.pc_hot_word.none-task-hot_word-landing-10-python获得一个目录下所有结构-null-null.186^v4^control"
                    },
                    "eventView": true
                },
                "recommendType": "ali",
                "index": 10,
                "style": "word_1",
                "strategyId": "landing",
                "productType": "hot_word"
            }
        ]
    },
    "message": "success"
}

第一步

将SimpleAPI -> SystemFile -> user.conf.yaml的 evn -> test 改为:https://silkroad.csdn.net,其他不用动。修改好之后,应该和底下一样(user.conf.yaml的注释太碍眼的话,可以删掉)

evn:
  host: test
  dev: http://175.178.37.196
  test: https://silkroad.csdn.net
  staging: http://175.178.37.196
  product: http://175.178.37.196

第二步

接下来就要构建我们的接口数据和断言数据了

清空 SimpleAPI -> Data -> haloLogin -> login.yaml 里面的所有内容

把下面的内容,复制到login.yaml 里面

case_1:
  title: 发送个成功的请求
  method: get
  path: /api/v2/assemble/list/channel/pc_hot_word?
  params:
    user_foormark: 1
    channel_name: pc_hot_word
    size: 20
    platform: pc
    imei: 10_20051326840-1646992611076-531956
  assert:
    - 200 == r.json()["code"]
    - 200 == r.status_code

case_2:
  title: size等于0,则没有数据返回
  method: get
  path: /api/v2/assemble/list/channel/pc_hot_word?
  params:
    user_foormark: 1
    channel_name: pc_hot_word
    size: 0
    platform: pc
    imei: 10_20051326840-1646992611076-531956
  assert:
    - 0 == len(r.json()["data"]["items"])
    - 200 == r.status_code

第三步

开始编写我们的用例啦

将 SimpleAPI -> TestCase -> test_loginModule.py 里面的内容清空,替换成下面的内容

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @time: 2022-08-08 09:50:44
# @author: 鹰眼测试


from Utils.dataUtils.setRequestData import SetRequestData
from SystemFile.pathEnum import get_path
from requests import request
import logging
import pytest
import allure
import os


# 标记模块名称,最后会在报告中显示
@allure.feature("CSDN搜索模块")
class TestLogin:
    file = os.path.join(os.path.join(get_path("data"), "haloLogin"), "login.yaml")
    case = SetRequestData(file).set_case()

    @allure.story("搜索接口测试")  # 用例名称,可以直接写接口名称
    @allure.title("{title}")  # 用例标题
    @pytest.mark.parametrize("title, url, method, header, params, assert_str", case)
    def test_case_1(self, title, url, method, header, params, assert_str):
        r = request(method=method, url=url, headers=header, params=params)
        r.encoding = "utf-8"
        log = logging.getLogger('响应信息')
        log.setLevel(logging.DEBUG)
        if type(assert_str) == type(str()):
            assert eval(assert_str)
            log.info(r.text)
        elif type(assert_str) == type([]):
            for assert_ in assert_str:
                assert eval(assert_)
                log.info(r.text)

第四步

运行 SimpleAPI -> main.py 文件即可

最后的结果如截图(看不懂英文的,在左下角有个En,点击一下切换中文就行了)

image-20220809010120880

空文件

简介

最简单、实用的接口自动化框架 展开 收起
Python
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
1
https://gitee.com/kenAyan/SimpleAPI.git
git@gitee.com:kenAyan/SimpleAPI.git
kenAyan
SimpleAPI
SimpleAPI
master

搜索帮助