Metadata-Version: 2.1
Name: apin
Version: 0.1
Summary: apin 一个不用写代码的接口自动化测试框架
Home-page: https://github.com/musen123/apin
Author: MuSen
Author-email: musen_nmb@qq.com
License: UNKNOWN
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.6
Description-Content-Type: text/markdown
Requires-Dist: Jinja2 (==2.10.1)
Requires-Dist: PyYAML (==5.3.1)
Requires-Dist: requests (==2.24.0)
Requires-Dist: rsa (==4.7.2)
Requires-Dist: jsonpath (==0.82)
Requires-Dist: pyasn1 (==0.4.8)
Requires-Dist: colorama (==0.4.4)

# apin(0.1)使用文档

# 一、apin介绍及安装

#### 1、什么是apin

​	apin是一个无需写代码，就可以完成接口自动化测试的框架，只需要通过json或yaml文件编写非常简洁的用例数据，即可完成接口自动化测试，并生成自动化测试报告。

​	apin是柠檬班—木森老师根据多年的自动化工作经验而开发出来的，旨在帮助更多不会写代码的小伙伴掌握接口自动化测试的能力。框架使用起来非常简单，易上手，只需要几个小时就能掌握！	

#### 2、安装apin

apin是基于python3.6开发的，安装前请确认你的python版本>3.6

- #### 安装命令

    ```
    pip install apin
    ```



# 二、快速入门

## 1、项目创建

- #### 创建命令

    ```
     apin create 项目名
    ```

安装好apin之后，打开命令终端输入创建命令，即可在当前路径下创建项目。

cd 切换到项目之中，即可看到如下的项目结构

![1615961932491](C:\课件\images\1615961932491.png) 

- #### 项目文件说明

    - ###### document: apin使用文档

    - ###### casedata: 存放yaml和json格式编写的用例文件

    - ###### testcases:py：存放py编写的用例目录

    - ###### func_tools.py：自定义的函数工具文件

    - ###### setting.py：整个项目的全局配置文件

    - ###### run.py：项目运行入口文件





## 2、用例编写

apin用例编写支持yaml文件，json文件，py文件三种方式，下面通过一个接口的用例demo来快速了解一下

#### 1、接口demo：

- ###### 接口地址：http://httpbin.org/post

- ###### 请求方法：post

- ###### 请求参数类型：application/json

- ###### 请求参数:

    | 参数名 | 类型 | 说明 |
    | ------ | ---- | ---- |
    | user   | str  | 账号 |
    | pwd    | str  | 密码 |

#### 2、json编写用例

在项目的casedata目录下，定义一个以test开头的json文件，按照【apin用例编写规范-json】编写用例即可

- ##### 案例

    ```json
    {
      "host": "http://api.XXX.com/futureloan/",
      "Cases": [
        {
          "title": "普通用户注册",
          "interface": "member/register",
          "method": "post",
          "json":{"mobile_phone":"133010121224","pwd":"lemonban"},
          "verification": []

        }
      ]
    }
    ```

#### 3、yaml编写用例

在项目的casedata目录下，定义一个以test开头的yaml文件，按照【apin用例编写规范-yaml】编写用例即可

- ##### 案例

    ```
    # 域名
    host: http://api.XXX.com/futureloan/
    # 用例数据
    Cases:
      - title: 普通用户注册
        interface: member/register
        method: post
        json:
          mobile_phone: ${{user_mobile}}
          pwd: lemonban
    ```



#### 4、py文件编写用例

​	在testcases目录中定义一个以test开头的py文件，定义一个以Test开头的类，并且继承于apin.core.httptest.HttpCase类，按照【apin用例编写规范-py】编写用例即可

- ##### 案例

    ```python
    from apin.core.httptest import HttpCase

    class TestStreamV3(HttpCase):
        host = "http://api.XXX.com/futureloan/"
        Cases = [
            # 用例1：普通用户注册
            {
                'title': "普通用户注册",
                'interface': "member/register",
                "method": "post",
                'json': {"mobile_phone": "${{user_mobile}}", "pwd": "lemonban"},
            },
        ]
    ```

## 3、用例运行

- ##### 方式1：

    ###### 终端项目路径下输入命令

    ```python
    apin run
    ```

- ##### 方式2

    ###### 直接使用python运行项目的run.py文件



## 4、测试报告和日志

- ##### 日志：项目运行完，会自动在项目路径下生成详细的运行日志

    ![1615984513176](C:\课件\images\1615984513176.png)

- ##### 测试报告：apin的测试报告是基第三方库unittestreport生成的

    ###### 运行完会在项目目录的reports目录中，自动生成详细的html测试报告。

![1615966527547](C:\课件\images\1615966527547.png) 



# 三、用例编写规范

## 1、概念介绍：

- ##### 用例集：apin中创建的每一个test开头的用例文件(py,json,yaml)，被称之为一个用例集。一个用例集下面可以定义多条测试用例。

- ##### 测试用例： 用例集中Cases字段中的一条数据就是一个测试用例



## 2、用例集的主要字段介绍

- ##### host：用例接口的host地址(接口的域名) 

    - ###### 类型：字符串

    - ###### 例：

        ```python
        host = "http://api.lemonban.com/futureloan/"
        ```



- ##### headers：指定用例使用的请求头

    - ###### 类型：字典

    - ###### 例

        ```python
        headers = {"User-Agent": "apin/musen"}
        ```

- ##### method：指定用例接口的请求方法

    - ###### 类型：字符串

    - ###### 例：post,get

- ##### interface：指定用例接口地址（接口url域名后面的部分）

    - ###### 类型：字符串

- ##### env： 设置用例集运行环境的局部变量

    - ###### 类型：字典

    - ###### 例:

        ```python
         env = {
                "user_mobile": '13109099878',
                "pwd": 'lemonban'
            }
        ```



- ##### extract：指定用例请求完要提取的变量（详细介绍见：【四、变量提取和引用】）

- ##### verification：指定用例的断言（详细介绍见：【五、用例断言】）

- ##### Cases:设置该测试集下的用例（详细介绍见：下一节【用例字段介绍】）

## 3、用例字段介绍

### 1、主要字段：

- ##### 用例集中除env字段之外的字段

    - ###### 1、用例集中除env和Cases字段之外，上述用例集中的字段，均支持在用例中自定义。

    - ###### 2、如果用例中定义了用例集中的字段，就使用自己定义的，没定义则引用 用例集中的。

- ##### title：用例的描述字段（必传字段）

    测试报告和日志信息中用例的描述

- ##### json: 用来传递json类型的请求参数

    请求参数类型为：content-type:application/json，使用该字段来传递请求参数

- ##### data：用来传递表单类型的请求参数

    请求参数类型为：content-type: application/x-www-form-urlencoded，使用该字段来传递请求参数

- ##### params: 用来查询字符串参数

    请求参数，以？key=value的形式 拼接在url后面的参数

### 2、其他字段

除了上述主要字段之外，python中的requests库中的requests.request方法所有的请求参数，均支持在用例中定义字段，

这些字段在大多数情况下都用不到，如果有用到

- ##### files:接口用于文件上传

    请求参数类型为：content-type:application/from-data，使用该字段来传递请求参数,常用语文件上传

- ##### cookies：请求的cookie信息（apin中同一个用例集会自动化传递cookie,一遍情况下，不需要使用该字段来传递cookie）

- ##### auth: 用于Basic/Digest/Custom HTTP认证

- ##### timeout：设置http请求超时时间

- ##### allow_redirects：是否运行请求重定向

- ##### proxies：代理请求的

- ##### stream：是否立即下载响应内容

- ##### verify：是否进行证书校验（如果要忽略HTTPS请求的证书校验，则将此参数设置为False）

- ##### cert：指定校验证书的路径

## 4、用例编写

### 1、python编写用例

- ##### 步骤一、在testcases目录中定义一个以test开头的py文件，

- ##### 步骤二、在文件中定义一个以Test开头的类，并且继承于apin.core.httptest.HttpCase类

- ##### 步骤三、在类中，编写测试集的字段值

    - ##### 字段名 = 字段值

    ```python
    from apin.core.httptest import HttpCase
    class TestDomeV3(HttpCase):
        host = "http://api.lemonban.com/futureloan/"
        headers = {"X-Lemonban-Media-Type": "lemonban.v2"}
        # 定义测试前置方法
        setup_hook = {"timestamp": 'F{get_timestamp()}'}
        # 预设变量
        env = {
            "user_mobile": 'F{rand_phone("155")}',
            "admin_mobile": 'F{rand_phone("133")}'
        }
        # 结果校验
        verification = {"method": "eq",
                        "expected": {'code': 0, "msg": "OK"},
                        "actual": {'code': 'V{{$..code}}', "msg": "V{{$..msg}}"}}
    ```

- ##### 步骤四、在Cases字段中编写用例数据

    ```python
    from apin.core.httptest import HttpCase
    class TestDomeV3(HttpCase):
        host = "http://api.XXXX.com/futureloan/"
        headers = {"X-Lemonban-Media-Type": "lemonban.v2"}
        # 定义测试前置方法
        setup_hook = {"timestamp": 'F{get_timestamp()}'}
        # 预设变量
        env = {
            "user_mobile": 'F{rand_phone("155")}',
            "admin_mobile": 'F{rand_phone("133")}'
        }
        # 结果校验
        verification = {"method": "eq",
                        "expected": {'code': 0, "msg": "OK"},
                        "actual": {'code': 'V{{$..code}}', "msg": "V{{$..msg}}"}}
    	Cases = [
            # 用例1：普通用户注册
            {
                'title': "普通用户注册",
                'interface': "member/register",
                "method": "post",
                'json': {"mobile_phone": "${{user_mobile}}", "pwd": "lemonban"},

            },
            # 用例2：管理员注册
            {
                'title': "管理员注册",
                'interface': "member/register",
                "method": "post",
                'json': {"mobile_phone": "${{admin_mobile}}", "pwd": "lemonban", "type": 0}
            },
       ]
    ```

### 3、yaml编写用例

​	使用yaml编写用例前 建议先去学习一下yaml的语法

- ##### 步骤一：在casedata中定义一个test开头的yaml文件

- ##### 步骤二：在yaml文件中定义测试集的字段值

    ```yaml
    # 域名
    host: http://api.xxxxx.com/futureloan/
    # 请求头
    headers:
      X-Lemonban-Media-Type: lemonban.v2
    # 用例前置钩子函数
    setup_hook:
      timestamp: F{get_timestamp()}
    # 预设运行变量
    env:
      user_mobile: F{rand_phone("155")}
      admin_mobile: F{rand_phone("133")}
    # 结果校验字段
    verification:
      method: eq
      expected:
        code: 0
        msg: OK
      actual:
        code: 'V{{$..code}}'
        msg: 'V{{$..msg}}'
    ```

- ##### 步骤三：在Cases字段中编写测试用例

    ```yaml
    # 用例数据
    Cases:
      - title: 普通用户注册
        interface: member/register
        method: post
        json:
          mobile_phone: ${{user_mobile}}
          pwd: lemonban
      - title: 管理员注册
        interface: member/register
        method: post
        json:
          mobile_phone: ${{admin_mobile}}
          pwd: lemonban
          type: 0
    ```

### 4、json编写用例

使用yaml编写用例前 建议先去学习一下json的语法，json文件中字段名都需要使用双引号

- ##### 步骤一：在casedata中定义一个test开头的json文件

- ##### 步骤二：在json文件中定义测试集的字段值

- ##### 步骤三：在json文件中定义测试集的字段值

    ```json
    {
      "host": "http://api.XXXXX.com/futureloan/",
      "headers": {"X-Lemonban-Media-Type": "lemonban.v2"},
      "setup_hook": {"timestamp": "F{get_timestamp()}"},
      "env": {
        "user_mobile": "F{rand_phone('155')}",
        "admin_mobile": "F{rand_phone('133')}"
      },
      "verification": {"method": "eq",
                       "expected": {"code": 0,"msg": "OK"},
                       "actual": {"code": "V{{$..code}}","msg": "V{{$..msg}}"}
      },
      "Cases": [
        {
          "title": "普通用户注册",
          "interface": "member/register",
          "method": "post",
          "json": {
            "mobile_phone": "${{user_mobile}}",
            "pwd": "lemonban"
          }
        },
        {
          "title": "管理员注册",
          "interface": "member/register",
          "method": "post",
          "json": {
            "mobile_phone": "${{admin_mobile}}",
            "pwd": "lemonban",
            "type": 0
          }
        }
      ]
    }
    ```



# 四、变量提取和引用

变量提取和引用主要是为了解决接口之间的参数依赖问题

使用场景：接口A的参数中需要使用接口B返回的某个数据，那么就要在请求B接口之后，提取数据保存，给请求A接口时使用。

## 1、变量提取

在用例集或用例数据中，通过extract字段指定要提取的变量。

- ##### 语法

    ```python
    "extract": {
       "变量名": ("变量保存的级别", "提取方式", "提取表达式"),
    }
    ```

    - ##### 变量名：保存数据的变量名

    - ##### 变量保存的级别：

        - ###### EVN: 全局变量，settings文件中的EVN

        - ###### env : 为局部变量(只对当前用例集有效)：用例集的env字段

    - ##### 提取方式

        - ###### re: 正则表达式提取

        - ###### jsonpath： 通过jsonpath提取

- ##### 案例

    ```python
    "extract": {
        # 通过jsonpath提取
       "token": ("env", "jsonpath", "$..token"),
        # 通过正则表达式提取
       'member_id': ("env", "re", r'"id":(.+?),')
    }
    ```



## 2、变量引用

- ##### 变量引用表达式：${{变量名}}

- ##### 引用优先级

    优先引用该用例的局部变量(用例的env中的变量)，如果局部变量不存在，则会引用全局变量(setting.py中ENV中保存的变量)。



# 五、用例断言

关于测试用例预期结果和实际结果的比对的,apin中封装了一个verification字段，只需要在verification中定义预期结果，实际结果提取表达式，和断言的方法，即可实现用例的断言！

### 1、基本语法

```python
verification = [
        [断言方式, 预期结果, 实际结果]
    ] 
```

### 2、断言方式

apin中目前支持两种断言方式：

- ###### 1、断言相等 ：eq

    预期结果和实际结果相等

    ```
    verification = [
            ['eq', 预期结果, 实际结果]
        ] 
    ```

- ###### 2、断言包含：contians

    实际结果中包含预期结果的内容

    ```
    verification = [
            ['contians', 预期结果, 实际结果]
        ] 
    ```

### 3、实际结果获取

​	关于断言的实际结果提取，需要使用`V{{表达式}}`来进行提取，表达式支持jsonpath和正则表达式两种提取方式方式。

- ##### 1、正则表达式提取

    ```python
    # 通过正则表达式来提取实际结果中的msg字段。
    verification = [
            ['contians', {'msg':"OK"}, {"msg": "V{{msg:'(.+?)'}}"}]
        ] 

    ```

- ##### 2、通过jsonpath提取

    ```python
    # 通过jsonpath来提取实际结果中的msg字段。
    verification = [
            ['contians', {'msg':"OK"}, {"msg": 'V{{$..msg}}']
        ] 

    ```

### 4、HTTP状态码的断言

​	上述两种方式，以可提取结果返回的数据，那如果要断言接口http请求的状态码呢？apin中也提供了一个内置的字段名，来表示http状态码

```python
# 断言接口请求的http状态码是否等于200
verification = [
        ['eq', 200, 'status_code']
    ] 
```



# 六、函数工具的使用

apin支持在测试用例中调用自定义的函数来处理数据，如对数据进行加密处理、随机生成数据等等。

#### 1、自定义函数

apin创建的项目中有一个funcTools.py，在该文件中可以自己定义函数，然后在用例中通过F{xxx()}来调用。

- ##### 案例：funcTools.py文件

```python
import hashlib,random

def md5_encrypt(msg):
    """md5加密"""
    md5 = hashlib.md5()  
    md5.update(msg.encode("utf8"))  
    return md5.hexdigest()

def rand_phone():
	"""随机生成手机号的函数"""
    import random
    for i in range(8):
        phone += str(random.randint(0, 9))
    return str(phone)


def get_timestamp():
    """获取时间戳"""
    return time.time()

```

- ##### 注意点：函数处理完的数据需要return返回哦

### 2、用例中引用函数

- ###### 引用表达式：F{函数名()}

- ##### demo1:用例数据中的user，引用前面定义的rand_phone函数

```python
{
	'title': "普通用户注册",
	'interface': "member/register",
	"method": "post",
	'json': {"user": "F{rand_phone()}", "pwd": "lemon123"},
}
```

- ##### demo2:用例数据中的pwd，引用前面定义的md5_encrypt函数对密码进行md加密

    - 注意点：引用的函数，传递的参数如果是变量，则不需要在变量应用表达式外加引号

```python
{
	'title': "普通用户登录",
	'interface': "member/login",
	"method": "post",
	'json': {"user": "13109877890", "pwd": "F{md5_encrypt('lemon123')}"},
}

# 引用函数，变量作为参数传递
{
	'title': "普通用户登录",
	'interface': "member/login",
	"method": "post",
	'json': {"user": "${{user}}", "pwd": "F{md5_encrypt(${{pwd}})}"},
}
```



# 七、项目全局配置

项目中的setting.py文件，是整个项目的配置文件，接下来相信介绍一下项目的配置选项。

### 1、debug模式运行

项目创建之后，默认运行是开启了debug模式，运行过程中会输出详细的debug级别日志。如果不像看运行日志，则将settings中的DEBUG设置为Flase即可。

```
# 是否开启debug模式：True为debug模式，False为关闭debug模式
DEBUG = False
```



### 2、ENV全局的变量

将settings.py中的ENV可以设置项目全局配置，

- #### 全局的域名

    推荐在ENV中设置全局的host,不建议在每一个测试用例中去设置host,切换测试环境切换也更方便(如果用例数据中没有自己定义host，会自动引用全局的host地址)

    ```python
    ENV = {
        "host":"http://WWW.XXX.com/",
    }
    ```



- #### 全局的请求头

    如果项目接口有必传的请求头数据，也可以直接在ENV中设置(如果用例数据中没有定义时，也会自动引用全局的headers)。

    ```python
    ENV = {
        "host":"http://WWW.XXX.com/",
        "headers": {"UserAgent": "apin-test01"}
    }
    ```

- #### 全局的测试数据

    如果用例中需要引用事先准备好的一些测试数据，如测试账号、密码之类的

    如：定义一个测试账号、测试密码、用户id

    ```python
    ENV = {
        "host":"http://WWW.XXX.com/",
        "headers": {"UserAgent": "apin-test01"},
        "user":"musen@qq.com",
        "pwd":"lemon123",
        "user_id":111
    }
    ```

    测试用例中直接使用${{}}即可引用，

    ```python
    # 引用user和pwd
    {
     'title': "登录",
     'interface': "member/register",
     "method": "post",
     'json': {"mobile_phone": "${{user}}", "pwd": "${{pwd}}"},
    }
    ```

    - ##### 注意点：如果局部环境和全局变量重名，优先引用局部变量。



### 3、测试报告

​	通过setting中的TEST_RESULT，可以配置测试报告的输出信息。

```python
TEST_RESULT = {
    # 测试报告文件名
    "filename": "report.html",
    # 测试人员
    "tester": "测试员",
    # 报告标题
    "title": "测试报告",
    # 报告样式 ：有1，2，三个样式
    "templates": 1,
    # 报告描述信息
    "desc": "XX项目测试生成的报告"
}
```



### 4、邮件推送测试结果

如果要将测试结果发送到指定的邮箱中，则在settings.py添加EMAIL配置即可

```python
EMAIL = {
    # smtp服务器地址
    "host": 'smtp.qq.com',
    # smtp服务器端口
    "port": 465,
    # 邮箱账号
    "user": "xxxx@qq.com",
    # smtps授权码
    "password": "xxxx",
    # 收件人列表
    "to_addrs": ['xxx@qq.com','xxx@qq.com'],
    # 是否发送附件
    "is_file": True
}
```



### 5、测试结果推送到钉钉群

如果要将测试结果推送到钉钉群，则在settings.py添加DINGTALK配置即可。

```python
DINGTALK = {
    #  钉钉机器人的Webhook地址
    "url": "",
    # 如果钉钉机器人安全设置了关键字，则需要传入对应的关键字
    "key": None,
    # 如果钉钉机器人安全设置了签名，则需要传入对应的密钥
    "secret": None,
    # 钉钉群中要@人的手机号列表，如：[137xxx,188xxx]
    "atMobiles": [],
    # 是否@所有人
    "isatall": False
}
```



### 6、测试结果推送企业微信群

如果要将测试结果推送到企业微信群，则在settings.py添加WECHAT配置即可。

```python
WECHAT = {
    # 企业微信群ID
    "chatid": "",
    # 调用企业微信API接口的凭证
    "access_token": ""
}
```



# 八、用例前后置执行

关于测试用例执行的前后置，apin中提供了四个字段来指定用例前后置执行的函数。

#### 1、setup_hook 

- ###### 指定用例  的前置执行函数

    ```python
    # 设置一个用例级别的前置函数，将前置函数的返回值，保存到局部变量的timestamp
    setup_hook = {"timestamp": 'F{get_timestamp()}'}
    ```



#### 2、setup_class_hook

- ###### 指定用例集  的前置执行函数

    ```python
    # 设置一个测试集级别的前置函数，将前置函数的返回值，保存到局部变量的timestamp
    setup_class_hook = {"timestamp": 'F{get_timestamp()}'}
    ```

####  3、teardown_hook

- ###### 指定用例 的后置执行函数

    ```python
    # 设置一个用例级别的后置
    teardown_hook = {"teardowm": 'F{data_clear()}'}
    ```

####  4、teardown_class_hook

- ###### 指定用例集的后置执行函数

    ```python
    # 设置一个测试集级别的后置方法
    teardown_hook = {"teardowm": 'F{data_clear()}'}
    ```



1

