文章目录
- 一、项目目标
- 二、项目效果图
- 三、项目目录结构
- 四、安装依赖
- 五、先写一个本地登录接口服务
- 六、启动接口服务
- 七、写配置文件
- [八、写 YAML 读取工具](#八、写 YAML 读取工具)
- 九、写请求工具类
- 十、编写登录测试数据
- [十一、配置 pytest](#十一、配置 pytest)
- [十二、写 conftest.py](#十二、写 conftest.py)
- 十三、写测试用例
- 十四、这个测试文件你要重点看懂什么
- 十五、整个执行流程图
- 十六、怎么运行项目
- 十七、这个项目你学到了什么
- 十八、你现在可以继续升级的方向
- 十九、我建议你马上做的练习
我们直接做一个能跑起来的 pytest + YAML + requests 登录接口小项目 。
这次你不是只学知识点,而是把这些点串成一套完整流程:
requests负责发接口请求YAML负责存测试数据pytest负责执行测试fixture负责公共前置parametrize负责数据驱动
我会按"初学者能照着敲出来"的方式带你做。
一、项目目标
我们先做一个最小可运行的登录接口自动化项目。
功能很简单:
- 启动一个本地登录接口服务
- 用
requests.post()调用登录接口 - 从
YAML读取多组测试数据 - 用
pytest.mark.parametrize执行多组测试 - 用断言校验接口返回结果
二、项目效果图
整个流程你先脑子里有个图:
plantuml
@startuml
start
:读取 YAML 测试数据;
:pytest 收集测试用例;
repeat
:取出一组登录数据;
:requests 发送 POST 请求;
:服务端返回响应 JSON;
:断言 code / msg / token;
repeat while (还有测试数据?)
stop
@enduml
三、项目目录结构
先建这个目录:
text
login_test_project/
├─ app.py
├─ pytest.ini
├─ requirements.txt
├─ config/
│ └─ config.yml
├─ common/
│ ├─ yaml_util.py
│ └─ request_util.py
├─ data/
│ └─ login.yml
└─ tests/
├─ conftest.py
└─ test_login.py
四、安装依赖
先进入项目目录,然后安装:
bash
pip install pytest requests pyyaml flask
你也可以先写一个 requirements.txt:
txt
pytest
requests
pyyaml
flask
然后执行:
bash
pip install -r requirements.txt
五、先写一个本地登录接口服务
为了让你能完整练习 requests,我们自己写一个本地接口。
文件:app.py
python
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route("/api/login", methods=["POST"])
def login():
data = request.get_json()
username = data.get("username", "")
password = data.get("password", "")
if not username:
return jsonify({
"code": 400,
"msg": "用户名不能为空",
"token": None
})
if not password:
return jsonify({
"code": 400,
"msg": "密码不能为空",
"token": None
})
if username == "admin" and password == "123456":
return jsonify({
"code": 200,
"msg": "登录成功",
"token": "token_admin_123"
})
return jsonify({
"code": 401,
"msg": "用户名或密码错误",
"token": None
})
if __name__ == "__main__":
app.run(host="127.0.0.1", port=5000, debug=True)
六、启动接口服务
打开终端,进入项目目录,运行:
bash
python app.py
启动后你会看到本地服务跑在:
text
http://127.0.0.1:5000
登录接口地址就是:
text
http://127.0.0.1:5000/api/login
七、写配置文件
文件:config/config.yml
yaml
base_url: "http://127.0.0.1:5000"
login_path: "/api/login"
timeout: 5
这个配置文件的意义是:
- 基础地址统一管理
- 接口路径统一管理
- 超时时间统一管理
以后做真实项目时,测试环境、预发布环境、生产环境都能这样切换。
八、写 YAML 读取工具
文件:common/yaml_util.py
python
import yaml
def read_yaml(path):
with open(path, "r", encoding="utf-8") as f:
return yaml.safe_load(f)
这里要记住:
优先用 safe_load(),不要一上来就用 load()。
九、写请求工具类
文件:common/request_util.py
python
import requests
def send_post(url, json_data=None, timeout=5):
response = requests.post(url=url, json=json_data, timeout=timeout)
return response
现在先写最简版。
后面做项目时,我们再往里面加:
- 日志
- 异常处理
- 请求头
- token 管理
- 统一断言封装
十、编写登录测试数据
文件:data/login.yml
yaml
login_cases:
- title: "正确登录"
request:
username: "admin"
password: "123456"
expect:
code: 200
msg: "登录成功"
token_not_null: true
- title: "密码错误"
request:
username: "admin"
password: "111111"
expect:
code: 401
msg: "用户名或密码错误"
token_not_null: false
- title: "用户名为空"
request:
username: ""
password: "123456"
expect:
code: 400
msg: "用户名不能为空"
token_not_null: false
- title: "密码为空"
request:
username: "admin"
password: ""
expect:
code: 400
msg: "密码不能为空"
token_not_null: false
这里你一定要学会这种结构:
title:用例标题request:请求参数expect:期望结果
这是接口自动化里非常常见的组织方式。
十一、配置 pytest
文件:pytest.ini
ini
[pytest]
testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*
addopts = -vs
含义:
testpaths = tests:测试目录在testspython_files = test_*.py:测试文件命名规则addopts = -vs:运行时显示详细输出
十二、写 conftest.py
这里开始把你前面学过的 fixture 用进来。
文件:tests/conftest.py
python
import pytest
from common.yaml_util import read_yaml
@pytest.fixture(scope="session")
def config_data():
return read_yaml("config/config.yml")
@pytest.fixture(scope="session")
def base_url(config_data):
return config_data["base_url"]
@pytest.fixture(scope="session")
def login_url(config_data, base_url):
return base_url + config_data["login_path"]
@pytest.fixture(scope="session")
def timeout(config_data):
return config_data["timeout"]
@pytest.fixture(scope="session")
def login_cases():
data = read_yaml("data/login.yml")
return data["login_cases"]
这里你可以复习一下 fixture 的意义:
config_data:读取配置base_url:基础地址login_url:完整登录地址timeout:请求超时login_cases:读取 YAML 用例数据
而且这些都是 session 级别,只读一次就够了。
十三、写测试用例
文件:tests/test_login.py
python
import pytest
from common.request_util import send_post
def build_ids(cases):
return [case["title"] for case in cases]
# 先读取一份静态数据用于 ids 展示
from common.yaml_util import read_yaml
_temp_cases = read_yaml("data/login.yml")["login_cases"]
@pytest.mark.parametrize("case", _temp_cases, ids=build_ids(_temp_cases))
def test_login(case, login_url, timeout):
req_data = case["request"]
expect_data = case["expect"]
response = send_post(
url=login_url,
json_data=req_data,
timeout=timeout
)
assert response.status_code == 200
result = response.json()
assert result["code"] == expect_data["code"]
assert result["msg"] == expect_data["msg"]
if expect_data["token_not_null"]:
assert result["token"] is not None
else:
assert result["token"] is None
十四、这个测试文件你要重点看懂什么
这个文件已经把今天的知识都串起来了。
1)参数化
python
@pytest.mark.parametrize("case", _temp_cases, ids=build_ids(_temp_cases))
意思是:
case是参数名_temp_cases是多组 YAML 数据ids=...用标题作为测试名称
所以它会执行 4 次测试。
2)fixture 注入
python
def test_login(case, login_url, timeout):
这里:
case来自参数化login_url来自 fixturetimeout来自 fixture
这就是"参数化 + fixture"一起用。
3)请求发送
python
response = send_post(
url=login_url,
json_data=req_data,
timeout=timeout
)
这里就是 requests.post() 真正出场的地方。
4)断言
python
assert response.status_code == 200
assert result["code"] == expect_data["code"]
assert result["msg"] == expect_data["msg"]
这就是接口自动化测试的核心:
- 先断言 HTTP 层
- 再断言业务层
十五、整个执行流程图
再看一张更完整的图:

十六、怎么运行项目
先开一个终端,启动接口服务:
bash
python app.py
再开第二个终端,执行测试:
bash
pytest
你大概会看到类似输出:
text
tests/test_login.py::test_login[正确登录] PASSED
tests/test_login.py::test_login[密码错误] PASSED
tests/test_login.py::test_login[用户名为空] PASSED
tests/test_login.py::test_login[密码为空] PASSED
十七、这个项目你学到了什么
这个小项目虽然简单,但它已经有"真实项目雏形"了。
你已经用到了:
requests发 POST 请求YAML管理测试数据pytest执行测试parametrize做数据驱动fixture管理公共资源conftest.py管理共享 fixturepytest.ini管理测试配置
这套组合,就是接口自动化项目最常见的基础骨架。
十八、你现在可以继续升级的方向
下面是这个项目的自然升级路线。
1)加日志
把请求 URL、请求参数、响应结果打印出来。
2)加断言封装
把重复的断言逻辑提到公共方法里。
3)加 token 提取
登录成功后自动提取 token,给后续接口复用。
4)加更多接口
比如用户信息查询、修改密码、退出登录。
5)接入 Allure 报告
让测试报告更像企业项目。
十九、我建议你马上做的练习
你自己先动手改这 3 个点:
- 再往
login.yml里加两条异常数据 - 在
request_util.py里打印请求和响应 - 新增一个"获取用户信息"的假接口,并继续用同样方式写测试
这样你就不是"看懂了",而是真正会用了。