Metadata-Version: 2.4
Name: mwj-apitest
Version: 1.3.0
Summary: 无需编码的接口测试框架，支持json、yaml、py文件格式的用例，命令行mwj查看帮助。
Project-URL: Homepage, https://github.com/Lvan826199/mwjApiTest
Project-URL: Repository, https://github.com/Lvan826199/mwjApiTest
Author-email: 梦无矶小仔 <Lvan826199@163.com>
License-Expression: MIT
License-File: LICENSE
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.8
Requires-Dist: colorama>=0.4.6
Requires-Dist: colorlog>=6.7.0
Requires-Dist: faker>=18.10.1
Requires-Dist: jinja2>=3.1.2
Requires-Dist: jsonpath>=0.82
Requires-Dist: pymysql>=1.0.2
Requires-Dist: pyyaml>=6.0
Requires-Dist: requests-toolbelt>=1.0.0
Requires-Dist: requests>=2.31.0
Requires-Dist: rsa>=4.7.2
Description-Content-Type: text/markdown

# mwj-apitest

一款无需编码且易用于二次开发的 HTTP 接口测试框架。支持 JSON、YAML、Python 三种用例格式，内置数据驱动、变量提取、断言校验、失败重跑、多线程执行、HTML 报告生成及多渠道通知（邮件/钉钉/企业微信）。

本框架可拆解用于自研接口自动化平台的接口执行引擎。

## 特性

- 数据驱动：支持 JSON / YAML / Python 文件编写用例，零代码即可完成接口测试
- 变量系统：`${{var}}` 引用变量，`F{func()}` 调用内置或自定义函数
- 数据提取：支持 JSONPath 和正则表达式从响应中提取数据
- 断言校验：支持 `eq`（相等）和 `contains`（包含）两种断言方式
- 钩子机制：`setup_hook` / `teardown_hook` / `db_check_hook` 等前后置钩子
- 数据库校验：支持 MySQL 前后置查询及数据校验
- 多线程执行：基于 `ThreadPoolExecutor` 的并发测试执行
- 失败重跑：可配置重试次数和间隔
- HTML 报告：Jinja2 渲染，支持两种报告模板，含历史趋势数据
- 通知推送：邮件（SMTP）、钉钉机器人、企业微信群消息

## 环境要求

- Python >= 3.8
- 推荐使用 [uv](https://docs.astral.sh/uv/) 管理虚拟环境和依赖

## 安装

### 使用 uv（推荐）

```bash
uv pip install mwj-apitest
```

### 使用 pip

```bash
pip install mwj-apitest
```

### 从源码安装（开发模式）

```bash
git clone https://github.com/Lvan826199/mwjApiTest.git
cd mwjApiTest
uv venv
uv pip install -e .
```

## 发布到 PyPI

```bash
# 1. 修改 pyproject.toml 中的 version 字段
# 2. 构建包
uv build

# 3. 发布到 PyPI（需要 PyPI token）
uv publish --token <your-pypi-token>

# 或使用用户名密码方式
uv publish --username __token__ --password <your-pypi-token>
```

## 快速开始

### 1. 创建项目

```bash
mwj create my_project
cd my_project
```

### 2. 运行测试

```bash
mwj run
```

### 3. 指定文件运行

```bash
mwj run --file case_yaml/test_case_demo.yaml
```

## 命令行参数

```
mwj create <project_name>   创建测试项目
mwj run                     运行当前目录下的所有用例
mwj run --file <path>       指定用例文件或目录
mwj run --thread <n>        设置并发线程数
mwj run --rerun <n>         设置失败重跑次数
mwj run --interval <s>      设置重跑间隔（秒）
mwj -V                      查看版本号
```

## 用例编写

### YAML 格式

```yaml
- testSet:
    name: 用户接口测试
    host: http://httpbin.org
    interface: /get
    method: GET
    Cases:
      - title: 测试GET请求
        interface: /get
        method: GET
        verification:
          - [eq, 200, status_code]
```

### JSON 格式

```json
[
  {
    "name": "用户接口测试",
    "host": "http://httpbin.org",
    "interface": "/get",
    "method": "GET",
    "Cases": [
      {
        "title": "测试GET请求",
        "interface": "/get",
        "method": "GET",
        "verification": [["eq", 200, "status_code"]]
      }
    ]
  }
]
```

### Python 格式

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

class TestDemo(HttpCase):
    name = "接口测试示例"
    host = "http://httpbin.org"
    interface = "/get"
    method = "GET"
    Cases = [
        {
            "title": "测试GET请求",
            "interface": "/get",
            "method": "GET",
            "verification": [["eq", 200, "status_code"]]
        }
    ]
```

## 配置文件 (settings.py)

```python
# 调试模式
DEBUG = True

# 日志文件路径
LOG_FILE_PATH = "./logs"

# 全局变量
ENV = {
    "host": "http://httpbin.org"
}

# 并发线程数
THREAD = 1

# 失败重跑次数
RERUN = 0

# 重跑间隔（秒）
INTERVAL = 2

# 测试报告配置
TEST_RESULT = {
    "filename": "report.html",
    "report_dir": "./reports",
    "title": "接口测试报告",
    "tester": "测试员",
    "desc": "接口自动化测试报告",
    "templates": 2,
}

# 数据库配置（可选）
DB = [
    {
        "name": "db1",
        "type": "mysql",
        "config": {
            "host": "127.0.0.1",
            "port": 3306,
            "user": "root",
            "password": "123456",
            "database": "test_db"
        }
    }
]

# 邮件通知（可选）
EMAIL = {
    "host": "smtp.qq.com",
    "port": 465,
    "email_account": "your_email@qq.com",
    "password": "smtp授权码",
    "to_addrs": ["receiver@example.com"],
}

# 钉钉通知（可选）
DINGTALK = {
    "webhook": "https://oapi.dingtalk.com/robot/send?access_token=xxx",
    "key": "关键字",
}

# 企业微信通知（可选）
WECHAT = {
    "chatid": "群ID",
    "access_token": "access_token",
}
```

## 变量与函数

### 变量引用

使用 `${{变量名}}` 引用环境变量：

```yaml
headers:
  Authorization: "Bearer ${{token}}"
```

### 内置函数

使用 `F{函数名(参数)}` 调用内置数据生成函数：

| 函数 | 说明 |
|------|------|
| `F{random_mobile()}` | 随机手机号 |
| `F{random_name()}` | 随机中文姓名 |
| `F{random_ssn()}` | 随机身份证号 |
| `F{random_email()}` | 随机邮箱 |
| `F{random_addr()}` | 随机地址 |
| `F{random_city()}` | 随机城市 |
| `F{get_timestamp()}` | 当前时间戳 |
| `F{base64_encode("text")}` | Base64 编码 |
| `F{md5_encrypt("text")}` | MD5 加密 |
| `F{rsa_encrypt("msg","pubkey")}` | RSA 加密 |

## 数据提取

从响应中提取数据并存储到变量中：

```yaml
extract:
  token: [ENV, jsonpath, "$.data.token"]
  user_id: [env, re, '"id":\s*(\d+)']
```

- 第一个参数：变量作用域（`ENV` 全局 / `env` 局部）
- 第二个参数：提取方式（`jsonpath` / `re`）
- 第三个参数：提取表达式

## 断言

```yaml
verification:
  - [eq, 200, status_code]
  - [eq, "success", "V{{$.msg}}"]
  - [contains, "token", "V{{$.data}}"]
```

- 第一个参数：断言方式（`eq` 相等 / `contains` 包含）
- 第二个参数：预期值
- 第三个参数：实际值（`status_code` 或 `V{{jsonpath表达式}}`）

## 许可证

MIT License
