4. 接口自动化测试框架选型与设计

医疗系统接口自动化测试的框架选型,不能只看工具是否流行,而要看它能否适配医疗业务的真实约束:接口协议多样(HTTP/HL7/FHIR/WebService)、数据敏感、环境隔离严格、回归频率高、审计要求强。Pytest + Requests + Allure + Jenkins 这一组合之所以在医疗项目中常见,是因为它分别覆盖了“用例组织与执行、协议请求与断言、结果可视化与追溯、持续集成与定时回归”四个关键能力,并且都能通过插件或配置与医疗场景对接。

四个组件在医疗项目中的职责边界

Requests 负责最底层的 HTTP 交互,适合封装统一的会话、超时、重试、证书校验和日志脱敏。医疗接口常涉及患者标识、就诊号、检验结果等敏感字段,因此请求层必须内置脱敏与审计日志,而不是把日志直接打印到控制台。Pytest 负责用例发现、参数化、夹具(fixture)和标记(marker),它把“一个接口用例”组织成可复用、可分组、可并行执行的测试单元。Allure 负责把执行结果转成可读报告,附加请求响应、步骤、附件和环境信息,便于测试、开发和业务方共同定位问题。Jenkins 负责触发、调度、环境参数注入和结果归档,把自动化从“本地能跑”推进到“每天定时跑、每次提交跑”。

需要强调的是,这四者不是简单叠加,而是分层协作。Requests 是执行层,Pytest 是调度与断言层,Allure 是观测层,Jenkins 是触发与治理层。分层清晰后,医疗项目中最常见的“环境切换混乱、用例互相污染、报告无法追溯”三类问题才有解。

医疗接口自动化测试分层架构 触发层 → 调度层 → 执行层 → 观测层,逐层解耦 触发与治理层 · Jenkins 定时回归 / 提交触发 环境参数注入 凭据与密钥管理 报告归档与通知 失败重跑 pytest 命令 + 环境变量 用例调度与断言层 · Pytest 用例发现 参数化 Fixture 夹具 Marker 分组 断言与校验 并发 调用封装后的请求方法 协议执行层 · Requests Session 会话 超时 / 重试 证书校验 日志脱敏 HL7/FHIR 适配 结果与附件写入 观测与追溯层 · Allure 步骤与用例树 请求响应附件 环境与版本信息 失败分类与趋势 审计留痕

医疗项目适配的关键设计点

第一,环境隔离。医疗系统通常有开发、测试、预生产、生产四套环境,接口地址、数据库、鉴权方式都不同。推荐用 Pytest 的 fixture 结合环境变量读取配置,例如通过 --env=uat 参数选择 config/uat.yaml,而不是在代码里硬编码 URL。第二,数据脱敏。Requests 的日志钩子应在写入前对 patientId、idCard、phone 等字段做掩码,Allure 附件同样要过滤,避免报告泄露真实患者信息。第三,鉴权与令牌。医疗接口常用 OAuth2 或院内统一认证,建议在 session 级 fixture 中获取 token 并自动刷新,避免每个用例重复登录。第四,协议适配。对于 HL7 v2 或 FHIR 接口,可在 Requests 之上再封装一层消息构造与解析,把 MLLP 或 JSON 的差异收敛到适配器里。

分层架构的落地方式

建议把项目目录划分为五层:config/ 放环境配置,core/ 放请求封装、断言工具、脱敏与日志,api/ 放各业务模块的接口定义,testcases/ 放 Pytest 用例,reports/ 放 Allure 结果。用例只调用 api/ 层的方法,不直接写 URL 和请求体;api/ 层只调用 core/ 层的请求方法,不关心断言;断言放在用例层,便于按业务场景组合。这样当接口地址或鉴权方式变化时,只需改 core/ 或 config/,用例基本不动。

下面给出一个可参考的请求封装示例,体现超时、重试与脱敏三个医疗项目必备能力:

import requests, time, logging
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

SENSITIVE = ["patientId", "idCard", "phone", "name"]

def mask(data):
    if isinstance(data, dict):
        return {k: ("***" if k in SENSITIVE else mask(v)) for k, v in data.items()}
    if isinstance(data, list):
        return [mask(i) for i in data]
    return data

class ApiClient:
    def __init__(self, base_url, token=None, timeout=10):
        self.base_url = base_url.rstrip("/")
        self.timeout = timeout
        self.session = requests.Session()
        retry = Retry(total=2, backoff_factor=0.5,
                      status_forcelist=[500, 502, 503, 504])
        self.session.mount("https://", HTTPAdapter(max_retries=retry))
        if token:
            self.session.headers["Authorization"] = f"Bearer {token}"

    def request(self, method, path, **kwargs):
        url = f"{self.base_url}{path}"
        kwargs.setdefault("timeout", self.timeout)
        logging.info("REQ %s %s %s", method, url, mask(kwargs.get("json")))
        resp = self.session.request(method, url, **kwargs)
        logging.info("RESP %s %s", resp.status_code, mask(resp.text[:500]))
        return resp

在 Pytest 中,可以用 fixture 把 ApiClient 注入到用例,并通过 marker 区分冒烟、回归、专项:

import pytest
from core.client import ApiClient

@pytest.fixture(scope="session")
def client(env_config):
    return ApiClient(env_config["base_url"], token=env_config["token"])

@pytest.mark.smoke
def test_query_patient(client):
    resp = client.request("GET", "/api/patient/1001")
    assert resp.status_code == 200
    assert resp.json()["code"] == "0"

执行时通过 pytest -m smoke --alluredir=reports/allure-results 生成结果,再由 allure generate 转成 HTML 报告。Jenkins 中配置参数化构建,把 ENV 作为环境变量传入,构建后归档 reports/ 并发布 Allure 报告。这样一条从代码提交到报告可追溯的链路就完整了。

医疗项目的自动化框架选型,核心不是“用了哪些工具”,而是“分层是否清晰、敏感数据是否受控、环境是否可切换、报告是否可追溯”。Pytest、Requests、Allure、Jenkins 只是承载这些要求的成熟载体。

选型对比与判断依据

维度Pytest + Requests + Allure + JenkinsRobot Framework 方案纯 Postman/Newman 方案
代码复用与分层强,Python 生态灵活中,关键字驱动弱,脚本化为主
医疗协议扩展强,可封装 HL7/FHIR中,需自定义库弱
报告与审计Allure 步骤、附件、环境齐全自带报告,定制有限报告较简单
CI 集成Jenkins 原生支持支持Newman 可集成
团队门槛需 Python 基础较低最低

如果团队已有 Python 能力、接口协议复杂、审计要求高,优先选择 Pytest 组合;如果测试人员以业务为主、代码能力弱,可考虑 Robot Framework;Postman/Newman 更适合接口调试和少量冒烟,不适合作为医疗核心回归框架。选型没有绝对优劣,关键是让框架能力与项目约束匹配。