欢迎光临
我们一直在努力

软件测试接口测试从入门到精通:Python接口自动化 - pytest测试框架

文章目录

  • 14 Python接口自动化 – pytest测试框架
    • 14.1 什么是pytest
      • pytest vs unittest
    • 14.2 pytest 基础
      • 第一个测试
      • 运行测试
    • 14.3 夹具(Fixture)
      • 什么是Fixture
      • 基础Fixture
      • Fixture作用域
    • 14.4 参数化测试
      • 基础参数化
      • 多参数参数化
    • 14.5 标记(Marker)
      • 自定义标记
      • 运行指定标记
      • 配置标记(pytest.ini)
    • 14.6 钩子函数(Hook)
      • 常用钩子
    • 14.7 完整的接口自动化项目
      • 项目结构
      • 配置文件
      • 基础API封装
      • 用户模块API
      • 测试用例
      • conftest.py
      • pytest.ini
    • 14.8 生成测试报告
      • HTML报告
      • Allure报告
    • 14.9 本章小结
      • pytest核心特性
      • 课后练习 📝
    • 14.10 下章预告

14 Python接口自动化 – pytest测试框架

🎯 本章目标:掌握pytest测试框架,学会用pytest编写专业的接口自动化测试。


14.1 什么是pytest

pytest 是Python最流行的测试框架,简洁、强大、易用。

pytest vs unittest

特性pytestunittest
语法 简洁(assert) 繁琐(self.assertEqual)
插件 丰富 较少
参数化 内置支持 需额外实现
夹具(Fixture) 强大 setUp/tearDown
社区 活跃 标准库

14.2 pytest 基础

第一个测试

# test_demo.py

def add(x, y):
return x + y

def test_add():
assert add(1, 2) == 3

def test_add_negative():
assert add(1, 2) == 3

运行测试

# 运行当前目录所有测试
pytest

# 运行指定文件
pytest test_demo.py

# 运行指定函数
pytest test_demo.py::test_add

# 显示详细信息
pytest -v

# 生成HTML报告
pytest –html=report.html


14.3 夹具(Fixture)

什么是Fixture

Fixture 是pytest的核心特性,用于准备测试环境(如创建数据库连接、初始化数据等)。

基础Fixture

import pytest
import requests

@pytest.fixture
def base_url():
"""提供基础URL"""
return "https://api.example.com"

@pytest.fixture
def session():
"""创建HTTP会话"""
s = requests.Session()
s.headers.update({"Content-Type": "application/json"})
yield s # yield前是setup,yield后是teardown
s.close()

@pytest.fixture
def auth_token(session, base_url):
"""获取认证token"""
response = session.post(f"{base_url}/api/v1/login", json={
"username": "admin",
"password": "123456"
})
return response.json()["data"]["token"]

# 使用Fixture
def test_get_user(session, base_url, auth_token):
session.headers.update({"Authorization": f"Bearer {auth_token}"})
response = session.get(f"{base_url}/api/v1/users/me")
assert response.status_code == 200

Fixture作用域

@pytest.fixture(scope="function") # 每个测试函数执行一次(默认)
@pytest.fixture(scope="class") # 每个测试类执行一次
@pytest.fixture(scope="module") # 每个模块执行一次
@pytest.fixture(scope="session") # 整个测试会话执行一次


14.4 参数化测试

基础参数化

import pytest

@pytest.mark.parametrize("username,password,expected", [
("admin", "123456", 0),
("admin", "wrong", 1001),
("", "123456", 1002),
("test", "123", 1003),
])
def test_login(username, password, expected):
"""参数化登录测试"""
result = login(username, password)
assert result["code"] == expected

多参数参数化

@pytest.mark.parametrize("user,expected_status,expected_msg", [
({"username": "admin", "password": "123456"}, 200, "成功"),
({"username": "admin", "password": "wrong"}, 401, "密码错误"}),
({"username": "", "password": "123456"}, 400, "用户名不能为空"}),
])
def test_login_complex(user, expected_status, expected_msg):
response = requests.post(url, json=user)
assert response.status_code == expected_status
assert expected_msg in response.json()["message"]


14.5 标记(Marker)

自定义标记

import pytest

@pytest.mark.smoke # 冒烟测试
@pytest.mark.api # API测试
@pytest.mark.login # 登录相关
def test_login():
pass

@pytest.mark.slow # 慢测试
def test_heavy_load():
pass

运行指定标记

# 只运行冒烟测试
pytest -m smoke

# 排除慢测试
pytest -m "not slow"

# 运行多个标记
pytest -m "smoke and api"

配置标记(pytest.ini)

[pytest]
markers =
smoke: 冒烟测试
api: API接口测试
login: 登录相关
slow: 慢测试


14.6 钩子函数(Hook)

常用钩子

# conftest.py

import pytest

def pytest_collection_modifyitems(config, items):
"""收集测试用例后执行"""
# 自动添加标记
for item in items:
if "login" in item.nodeid:
item.add_marker(pytest.mark.login)

def pytest_runtest_setup(item):
"""每个测试用例执行前"""
print(f"\\n开始执行: {item.name}")

def pytest_runtest_teardown(item, nextitem):
"""每个测试用例执行后"""
print(f"执行结束: {item.name}")


14.7 完整的接口自动化项目

项目结构

api_test/
├── pytest.ini # pytest配置
├── conftest.py # 全局Fixture和钩子
├── requirements.txt # 依赖
├── config/
│ └── settings.py # 配置文件
├── api/
│ ├── __init__.py
│ ├── base_api.py # 基础API封装
│ ├── user_api.py # 用户模块API
│ └── order_api.py # 订单模块API
├── tests/
│ ├── __init__.py
│ ├── test_user.py # 用户测试
│ └── test_order.py # 订单测试
├── data/
│ ├── users.csv # 测试数据
│ └── orders.json
└── reports/ # 测试报告

配置文件

config/settings.py:

import os

class Settings:
BASE_URL = os.getenv("BASE_URL", "https://api.example.com")
TIMEOUT = int(os.getenv("TIMEOUT", "10"))
USERNAME = os.getenv("TEST_USERNAME", "admin")
PASSWORD = os.getenv("TEST_PASSWORD", "123456")

settings = Settings()

基础API封装

api/base_api.py:

import requests
from config.settings import settings

class BaseAPI:
def __init__(self):
self.session = requests.Session()
self.session.headers.update({
"Content-Type": "application/json",
"Accept": "application/json"
})
self.base_url = settings.BASE_URL

def request(self, method, path, **kwargs):
url = f"{self.base_url}{path}"
kwargs.setdefault("timeout", settings.TIMEOUT)
response = self.session.request(method, url, **kwargs)
return response

def get(self, path, **kwargs):
return self.request("GET", path, **kwargs)

def post(self, path, **kwargs):
return self.request("POST", path, **kwargs)

def put(self, path, **kwargs):
return self.request("PUT", path, **kwargs)

def delete(self, path, **kwargs):
return self.request("DELETE", path, **kwargs)

用户模块API

api/user_api.py:

from api.base_api import BaseAPI

class UserAPI(BaseAPI):
def login(self, username, password):
return self.post("/api/v1/login", json={
"username": username,
"password": password
})

def create_user(self, user_data):
return self.post("/api/v1/users", json=user_data)

def get_user(self, user_id):
return self.get(f"/api/v1/users/{user_id}")

def update_user(self, user_id, user_data):
return self.put(f"/api/v1/users/{user_id}", json=user_data)

def delete_user(self, user_id):
return self.delete(f"/api/v1/users/{user_id}")

测试用例

tests/test_user.py:

import pytest
from api.user_api import UserAPI
from config.settings import settings

@pytest.fixture
def user_api():
api = UserAPI()
# 登录获取token
response = api.login(settings.USERNAME, settings.PASSWORD)
token = response.json()["data"]["token"]
api.session.headers.update({"Authorization": f"Bearer {token}"})
return api

class TestUser:

def test_create_user(self, user_api):
"""测试创建用户"""
data = {
"username": "testuser001",
"email": "test001@example.com",
"password": "123456"
}
response = user_api.create_user(data)

assert response.status_code == 201
result = response.json()
assert result["code"] == 0
assert result["data"]["username"] == "testuser001"

# 保存用户ID
pytest.user_id = result["data"]["id"]

def test_get_user(self, user_api):
"""测试获取用户"""
user_id = getattr(pytest, "user_id", 1)
response = user_api.get_user(user_id)

assert response.status_code == 200
assert response.json()["data"]["id"] == user_id

@pytest.mark.parametrize("username,expected_code", [
("ab", 400), # 太短
("a" * 21, 400), # 太长
("", 400), # 为空
])
def test_create_user_invalid_username(self, user_api, username, expected_code):
"""测试无效用户名"""
data = {
"username": username,
"email": "test@example.com",
"password": "123456"
}
response = user_api.create_user(data)
assert response.status_code == expected_code

conftest.py

import pytest

def pytest_configure(config):
"""pytest配置"""
config.addinivalue_line("markers", "smoke: 冒烟测试")
config.addinivalue_line("markers", "api: API测试")

def pytest_collection_modifyitems(config, items):
"""自动添加标记"""
for item in items:
if "test_" in item.nodeid:
item.add_marker(pytest.mark.api)

@pytest.fixture(scope="session", autouse=True)
def setup_session():
"""会话级setup"""
print("\\n=== 测试会话开始 ===")
yield
print("\\n=== 测试会话结束 ===")

pytest.ini

[pytest]
testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*
addopts = -v –tb=short –strict-markers
markers =
smoke: 冒烟测试
api: API接口测试
slow: 慢测试


14.8 生成测试报告

HTML报告

# 安装插件
pip install pytest-html

# 生成报告
pytest –html=reports/report.html –self-contained-html

Allure报告

# 安装
pip install allure-pytest

# 运行测试并生成Allure数据
pytest –alluredir=reports/allure

# 生成并打开报告
allure serve reports/allure


14.9 本章小结

pytest核心特性

#mermaid-svg-fq6jSU1fDazaMQM4{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-fq6jSU1fDazaMQM4 .error-icon{fill:#552222;}#mermaid-svg-fq6jSU1fDazaMQM4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fq6jSU1fDazaMQM4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fq6jSU1fDazaMQM4 .marker.cross{stroke:#333333;}#mermaid-svg-fq6jSU1fDazaMQM4 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fq6jSU1fDazaMQM4 p{margin:0;}#mermaid-svg-fq6jSU1fDazaMQM4 .edge{stroke-width:3;}#mermaid-svg-fq6jSU1fDazaMQM4 .section–1 rect,#mermaid-svg-fq6jSU1fDazaMQM4 .section–1 path,#mermaid-svg-fq6jSU1fDazaMQM4 .section–1 circle,#mermaid-svg-fq6jSU1fDazaMQM4 .section–1 polygon,#mermaid-svg-fq6jSU1fDazaMQM4 .section–1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .section–1 text{fill:#ffffff;}#mermaid-svg-fq6jSU1fDazaMQM4 .node-icon–1{font-size:40px;color:#ffffff;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-edge–1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-depth–1{stroke-width:17;}#mermaid-svg-fq6jSU1fDazaMQM4 .section–1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled circle,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:lightgray;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:#efefef;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-0 rect,#mermaid-svg-fq6jSU1fDazaMQM4 .section-0 path,#mermaid-svg-fq6jSU1fDazaMQM4 .section-0 circle,#mermaid-svg-fq6jSU1fDazaMQM4 .section-0 polygon,#mermaid-svg-fq6jSU1fDazaMQM4 .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-fq6jSU1fDazaMQM4 .section-0 text{fill:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .node-icon-0{font-size:40px;color:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-depth-0{stroke-width:14;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled circle,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:lightgray;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:#efefef;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-1 rect,#mermaid-svg-fq6jSU1fDazaMQM4 .section-1 path,#mermaid-svg-fq6jSU1fDazaMQM4 .section-1 circle,#mermaid-svg-fq6jSU1fDazaMQM4 .section-1 polygon,#mermaid-svg-fq6jSU1fDazaMQM4 .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .section-1 text{fill:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .node-icon-1{font-size:40px;color:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-depth-1{stroke-width:11;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled circle,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:lightgray;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:#efefef;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-2 rect,#mermaid-svg-fq6jSU1fDazaMQM4 .section-2 path,#mermaid-svg-fq6jSU1fDazaMQM4 .section-2 circle,#mermaid-svg-fq6jSU1fDazaMQM4 .section-2 polygon,#mermaid-svg-fq6jSU1fDazaMQM4 .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .section-2 text{fill:#ffffff;}#mermaid-svg-fq6jSU1fDazaMQM4 .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-depth-2{stroke-width:8;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled circle,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:lightgray;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:#efefef;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-3 rect,#mermaid-svg-fq6jSU1fDazaMQM4 .section-3 path,#mermaid-svg-fq6jSU1fDazaMQM4 .section-3 circle,#mermaid-svg-fq6jSU1fDazaMQM4 .section-3 polygon,#mermaid-svg-fq6jSU1fDazaMQM4 .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .section-3 text{fill:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .node-icon-3{font-size:40px;color:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-depth-3{stroke-width:5;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled circle,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:lightgray;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:#efefef;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-4 rect,#mermaid-svg-fq6jSU1fDazaMQM4 .section-4 path,#mermaid-svg-fq6jSU1fDazaMQM4 .section-4 circle,#mermaid-svg-fq6jSU1fDazaMQM4 .section-4 polygon,#mermaid-svg-fq6jSU1fDazaMQM4 .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .section-4 text{fill:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .node-icon-4{font-size:40px;color:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-depth-4{stroke-width:2;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled circle,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:lightgray;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:#efefef;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-5 rect,#mermaid-svg-fq6jSU1fDazaMQM4 .section-5 path,#mermaid-svg-fq6jSU1fDazaMQM4 .section-5 circle,#mermaid-svg-fq6jSU1fDazaMQM4 .section-5 polygon,#mermaid-svg-fq6jSU1fDazaMQM4 .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .section-5 text{fill:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .node-icon-5{font-size:40px;color:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-depth-5{stroke-width:-1;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled circle,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:lightgray;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:#efefef;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-6 rect,#mermaid-svg-fq6jSU1fDazaMQM4 .section-6 path,#mermaid-svg-fq6jSU1fDazaMQM4 .section-6 circle,#mermaid-svg-fq6jSU1fDazaMQM4 .section-6 polygon,#mermaid-svg-fq6jSU1fDazaMQM4 .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .section-6 text{fill:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .node-icon-6{font-size:40px;color:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-depth-6{stroke-width:-4;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled circle,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:lightgray;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:#efefef;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-7 rect,#mermaid-svg-fq6jSU1fDazaMQM4 .section-7 path,#mermaid-svg-fq6jSU1fDazaMQM4 .section-7 circle,#mermaid-svg-fq6jSU1fDazaMQM4 .section-7 polygon,#mermaid-svg-fq6jSU1fDazaMQM4 .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .section-7 text{fill:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .node-icon-7{font-size:40px;color:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-depth-7{stroke-width:-7;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled circle,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:lightgray;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:#efefef;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-8 rect,#mermaid-svg-fq6jSU1fDazaMQM4 .section-8 path,#mermaid-svg-fq6jSU1fDazaMQM4 .section-8 circle,#mermaid-svg-fq6jSU1fDazaMQM4 .section-8 polygon,#mermaid-svg-fq6jSU1fDazaMQM4 .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .section-8 text{fill:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .node-icon-8{font-size:40px;color:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-depth-8{stroke-width:-10;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled circle,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:lightgray;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:#efefef;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-9 rect,#mermaid-svg-fq6jSU1fDazaMQM4 .section-9 path,#mermaid-svg-fq6jSU1fDazaMQM4 .section-9 circle,#mermaid-svg-fq6jSU1fDazaMQM4 .section-9 polygon,#mermaid-svg-fq6jSU1fDazaMQM4 .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .section-9 text{fill:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .node-icon-9{font-size:40px;color:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-depth-9{stroke-width:-13;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled circle,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:lightgray;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:#efefef;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-10 rect,#mermaid-svg-fq6jSU1fDazaMQM4 .section-10 path,#mermaid-svg-fq6jSU1fDazaMQM4 .section-10 circle,#mermaid-svg-fq6jSU1fDazaMQM4 .section-10 polygon,#mermaid-svg-fq6jSU1fDazaMQM4 .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .section-10 text{fill:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .node-icon-10{font-size:40px;color:black;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .edge-depth-10{stroke-width:-16;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled circle,#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:lightgray;}#mermaid-svg-fq6jSU1fDazaMQM4 .disabled text{fill:#efefef;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-root rect,#mermaid-svg-fq6jSU1fDazaMQM4 .section-root path,#mermaid-svg-fq6jSU1fDazaMQM4 .section-root circle,#mermaid-svg-fq6jSU1fDazaMQM4 .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-fq6jSU1fDazaMQM4 .section-root text{fill:#ffffff;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-root span{color:#ffffff;}#mermaid-svg-fq6jSU1fDazaMQM4 .section-2 span{color:#ffffff;}#mermaid-svg-fq6jSU1fDazaMQM4 .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-fq6jSU1fDazaMQM4 .edge{fill:none;}#mermaid-svg-fq6jSU1fDazaMQM4 .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-fq6jSU1fDazaMQM4 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

pytest

基础

assert断言

自动发现

详细报告

Fixture

作用域控制

setup/teardown

依赖注入

参数化

多组数据

多参数

自动展开

标记

自定义marker

选择性执行

分类管理

插件

HTML报告

Allure报告

覆盖率

课后练习 📝

  • 基础题:用pytest编写一个计算器测试,包含加、减、乘、除。

  • 进阶题:按照上面的项目结构,搭建一个完整的接口自动化项目。


  • 14.10 下章预告

    下一章我们将学习Java + RestAssured进行接口自动化!


    “pytest让Python测试变得简单而优雅,它是接口自动化测试的最佳搭档。”

    赞(0)
    未经允许不得转载:171主机测评 » 软件测试接口测试从入门到精通:Python接口自动化 - pytest测试框架
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址