Apifox CLI + GitLab CI:接口自动化测试实施记录
-
- 一、前置准备清单
-
- [1.1 账号与权限](#1.1 账号与权限)
- [1.2 环境依赖](#1.2 环境依赖)
- [1.3 网络要求](#1.3 网络要求)
- [1.4 项目文件检查](#1.4 项目文件检查)
- 二、环境变量声明
-
- [2.1 环境变量定义](#2.1 环境变量定义)
- [2.2 GitLab CI/CD Variables 配置](#2.2 GitLab CI/CD Variables 配置)
- [2.3 本地开发环境配置](#2.3 本地开发环境配置)
- 三、整体架构图
-
- [3.1 系统架构图](#3.1 系统架构图)
- [3.2 CI/CD 流水线时序图](#3.2 CI/CD 流水线时序图)
- [3.3 目录结构图](#3.3 目录结构图)
- 四、实施步骤
-
- [4.1 阶段一:GitLab Runner 部署](#4.1 阶段一:GitLab Runner 部署)
-
- [4.1.1 创建 Runner 部署目录](#4.1.1 创建 Runner 部署目录)
- [4.1.2 创建 Docker Compose 配置文件](#4.1.2 创建 Docker Compose 配置文件)
- [4.1.3 创建 Runner 注册脚本](#4.1.3 创建 Runner 注册脚本)
- [4.1.4 创建启动/停止脚本](#4.1.4 创建启动/停止脚本)
- [4.1.5 执行部署](#4.1.5 执行部署)
- [4.2 阶段二:Apifox 项目配置](#4.2 阶段二:Apifox 项目配置)
-
- [4.2.1 创建 Apifox 项目](#4.2.1 创建 Apifox 项目)
- [4.2.2 创建 Access Token](#4.2.2 创建 Access Token)
- [4.2.3 导入 API 定义](#4.2.3 导入 API 定义)
- [4.2.4 创建测试场景 (详细步骤)](#4.2.4 创建测试场景 (详细步骤))
-
- [4.2.4.1 创建测试场景入口](#4.2.4.1 创建测试场景入口)
- [4.2.4.2 配置测试环境](#4.2.4.2 配置测试环境)
- [4.2.4.3 添加测试步骤](#4.2.4.3 添加测试步骤)
- [4.2.4.4 测试场景流程图](#4.2.4.4 测试场景流程图)
- [4.2.4.5 运行测试验证](#4.2.4.5 运行测试验证)
- [4.2.4.6 导出测试场景](#4.2.4.6 导出测试场景)
- [4.2.4.7 测试用例汇总](#4.2.4.7 测试用例汇总)
- [4.2.5 创建本地配置文件](#4.2.5 创建本地配置文件)
- [4.3 阶段三:Apifox CLI 本地验证](#4.3 阶段三:Apifox CLI 本地验证)
-
- [4.3.1 安装 Apifox CLI](#4.3.1 安装 Apifox CLI)
- [4.3.2 启动本地服务](#4.3.2 启动本地服务)
- [4.3.3 执行 Apifox 测试](#4.3.3 执行 Apifox 测试)
- [4.4 阶段四:GitLab CI 配置](#4.4 阶段四:GitLab CI 配置)
-
- [4.4.1 创建 GitLab CI 配置文件](#4.4.1 创建 GitLab CI 配置文件)
- [4.4.2 配置 GitLab CI Variables](#4.4.2 配置 GitLab CI Variables)
- [4.4.3 提交并触发流水线](#4.4.3 提交并触发流水线)
- 五、遇到的问题与解决方案
-
- [5.1 问题一:GitLab CI `needs` 配置格式不兼容](#5.1 问题一:GitLab CI
needs配置格式不兼容) - [5.2 问题二:GitLab CI `rules` 中不能使用 `||` 操作符](#5.2 问题二:GitLab CI
rules中不能使用||操作符) - [5.3 问题三:npm 网络问题导致 Apifox CLI 安装失败](#5.3 问题三:npm 网络问题导致 Apifox CLI 安装失败)
- [5.4 问题四:Apifox 删除接口返回 null 的 Schema 验证问题](#5.4 问题四:Apifox 删除接口返回 null 的 Schema 验证问题)
- [5.5 问题五:CI 环境 npm 安装超时 (53+ 分钟)](#5.5 问题五:CI 环境 npm 安装超时 (53+ 分钟))
- [5.6 问题六:Apifox CLI API 调用返回 HTTP 500](#5.6 问题六:Apifox CLI API 调用返回 HTTP 500)
- [5.7 问题七:JUnit 报告路径配置错误](#5.7 问题七:JUnit 报告路径配置错误)
- [5.8 问题八:GitLab Runner 无法连接 GitLab 服务器](#5.8 问题八:GitLab Runner 无法连接 GitLab 服务器)
- [5.1 问题一:GitLab CI `needs` 配置格式不兼容](#5.1 问题一:GitLab CI
- 六、验证与测试
-
- [6.1 本地验证清单](#6.1 本地验证清单)
- [6.2 CI/CD 验证清单](#6.2 CI/CD 验证清单)
- [6.3 执行完整测试](#6.3 执行完整测试)
- [6.4 触发 CI 流水线](#6.4 触发 CI 流水线)
- 七、附录:完整配置文件
-
- [7.1 Makefile](#7.1 Makefile)
- [7.2 API 测试脚本](#7.2 API 测试脚本)
- [7.3 .gitignore 配置](#7.3 .gitignore 配置)
- 变更记录
- 实验工程
版本 : 2.3.0
创建时间 : 2025-01-14
更新时间 : 2025-01-15
项目 : api-test-demo
目标: 将接口自动化测试融入研发工作流
一、前置准备清单
在开始实施前,请确保以下准备工作已完成:
1.1 账号与权限
| 序号 | 准备项 | 状态 | 负责人 | 备注 |
|---|---|---|---|---|
| 1 | GitLab 账号 | [ ] | - | 需要项目的 Maintainer 权限 |
| 2 | Apifox 账号 | [ ] | - | 注册地址: https://apifox.com |
| 3 | Apifox Access Token | [ ] | - | 个人设置 -> API 访问令牌 |
| 4 | GitLab CI/CD Variables 配置权限 | [ ] | - | 项目设置 -> CI/CD -> Variables |
| 5 | 服务器 Docker 权限 | [ ] | - | 用于部署 GitLab Runner |
1.2 环境依赖
| 序号 | 依赖项 | 版本要求 | 验证命令 | 状态 |
|---|---|---|---|---|
| 1 | JDK | 17+ | java -version |
[ ] |
| 2 | Maven | 3.8+ | mvn -version |
[ ] |
| 3 | Node.js | 18+ | node -version |
[ ] |
| 4 | npm | 8+ | npm -version |
[ ] |
| 5 | Docker | 20+ | docker -version |
[ ] |
| 6 | Docker Compose | 2.0+ | docker compose version |
[ ] |
| 7 | Git | 2.30+ | git --version |
[ ] |
| 8 | curl | - | curl --version |
[ ] |
1.3 网络要求
| 序号 | 网络访问 | 地址 | 用途 | 状态 |
|---|---|---|---|---|
| 1 | GitLab 服务器 | http://192.168.50.7 | 代码仓库、CI/CD | [ ] |
| 2 | Apifox API | https://api.apifox.com | 测试执行 | [ ] |
| 3 | npm 镜像源 | https://registry.npmmirror.com | 安装 Apifox CLI | [ ] |
| 4 | Maven 中央仓库 | https://repo.maven.apache.org | 依赖下载 | [ ] |
1.4 项目文件检查
| 序号 | 文件/目录 | 路径 | 状态 |
|---|---|---|---|
| 1 | Maven 配置 | pom.xml |
[ ] |
| 2 | Spring Boot 配置 | src/main/resources/application.yml |
[ ] |
| 3 | 测试配置 | src/test/resources/application-test.yml |
[ ] |
| 4 | Controller 类 | src/main/java/.../controller/ |
[ ] |
二、环境变量声明
2.1 环境变量定义
将以下环境变量配置到相应位置,确保整个流程可复用。
bash
# ============================================================
# 环境变量定义 - API 自动化测试
# 文件: .env 或 GitLab CI/CD Variables
# ============================================================
# --------------------- Apifox 配置 ---------------------
# Apifox API 访问令牌
# 获取方式: Apifox -> 个人设置 -> API 访问令牌 -> 新建令牌
# 格式: APS-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
export APIFOX_ACCESS_TOKEN="APS-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# Apifox 项目 ID
# 获取方式: Apifox -> 项目设置 -> 基本信息 -> 项目 ID
# 格式: 数字 ID
export APIFOX_PROJECT_ID="1234567"
# --------------------- GitLab 配置 ---------------------
# GitLab 服务器地址
# 注意: 内网部署的 GitLab 需使用内网 IP
export GITLAB_URL="http://192.168.50.7"
# GitLab Runner 注册令牌
# 获取方式: GitLab -> 项目设置 -> CI/CD -> Runners -> New project runner
# 格式: glrt-xxxxxxxxxxxxxxxxxxxx
export GITLAB_RUNNER_TOKEN="glrt-xxxxxxxxxxxxxxxxxxxx"
# --------------------- 应用配置 ---------------------
# 应用服务端口
export SERVER_PORT="8080"
# 测试环境标识
export TEST_ENV="dev"
# --------------------- npm 配置 ---------------------
# npm 镜像源 (国内网络必须配置)
export NPM_REGISTRY="https://registry.npmmirror.com"
2.2 GitLab CI/CD Variables 配置
在 GitLab 项目中配置以下变量:
配置路径 : 项目 -> Settings -> CI/CD -> Variables -> Add variable
| Variable Key | Value | Type | Flags | 说明 |
|---|---|---|---|---|
APIFOX_ACCESS_TOKEN |
APS-xxx... |
Variable | Masked, Protected | Apifox 访问令牌 |
APIFOX_PROJECT_ID |
1234567 |
Variable | - | Apifox 项目 ID |
配置截图说明:
┌─────────────────────────────────────────────────────────────┐
│ Add variable │
├─────────────────────────────────────────────────────────────┤
│ Key: APIFOX_ACCESS_TOKEN │
│ Value: APS-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx │
│ │
│ Type: ○ Variable ○ File │
│ │
│ Flags: [✓] Protect variable │
│ [✓] Mask variable │
│ [ ] Expand variable reference │
│ │
│ [ Add variable ] │
└─────────────────────────────────────────────────────────────┘
2.3 本地开发环境配置
bash
# 在 ~/.bashrc 或 ~/.zshrc 中添加
export APIFOX_ACCESS_TOKEN="your-token-here"
export APIFOX_PROJECT_ID="your-project-id"
# 配置 npm 镜像源
npm config set registry https://registry.npmmirror.com
# 验证配置
echo $APIFOX_ACCESS_TOKEN
echo $APIFOX_PROJECT_ID
npm config get registry
三、整体架构图
3.1 系统架构图
┌─────────────────────────────────────────────────────────────────────────────────┐
│ API 自动化测试系统架构 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ │
│ │ 开发者 │ │
│ └──────┬──────┘ │
│ │ 1. git push │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ GitLab (http://192.168.50.7) │ │
│ │ ┌─────────────────────────────────────────────────────────────────┐ │ │
│ │ │ 代码仓库 │ │ │
│ │ │ - api-test-demo │ │ │
│ │ │ - .gitlab-ci.yml (CI 配置) │ │ │
│ │ └─────────────────────────────────────────────────────────────────┘ │ │
│ │ │ 2. 触发 Pipeline │ │
│ │ ▼ │ │
│ │ ┌─────────────────────────────────────────────────────────────────┐ │ │
│ │ │ GitLab CI/CD │ │ │
│ │ │ │ │ │
│ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │
│ │ │ │ Build │──▶│ Test │──▶│ API-Test │──▶│ Report │ │ │ │
│ │ │ │ 构建 │ │ 单元测试 │ │ Apifox │ │ 报告 │ │ │ │
│ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │ │
│ │ │ │ │ │ │
│ │ └──────────────────────────────────────│──────────────────────────┘ │ │
│ └─────────────────────────────────────────│────────────────────────────────┘ │
│ │ 3. 调用 Apifox API │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ Apifox (https://apifox.com) │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │
│ │ │ API 定义 │ │ 测试用例 │ │ 测试报告 │ │ │
│ │ │ - 5个端点 │ │ - 正向测试 │ │ - HTML格式 │ │ │
│ │ │ - OpenAPI导入 │ │ - 异常测试 │ │ - JSON格式 │ │ │
│ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ GitLab Runner (Docker 部署) │ │
│ │ ┌───────────────────────────────────────────────────────────────────┐ │ │
│ │ │ Container: gitlab-runner-api-test │ │ │
│ │ │ - Image: gitlab/gitlab-runner:latest │ │ │
│ │ │ - Executor: docker │ │ │
│ │ │ - 挂载: /var/run/docker.sock │ │ │
│ │ └───────────────────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
3.2 CI/CD 流水线时序图
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Developer│ │ GitLab │ │ Runner │ │ App(8080)│ │ Apifox │
└────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │ │ │
│ 1. git push │ │ │ │
│───────────────>│ │ │ │
│ │ │ │ │
│ │ 2. 触发Pipeline │ │ │
│ │───────────────>│ │ │
│ │ │ │ │
│ │ │ 3. Build阶段 │ │
│ │ │ mvn compile │ │
│ │ │───────────────>│ │
│ │ │ │ │
│ │ │ 4. Test阶段 │ │
│ │ │ mvn test │ │
│ │ │───────────────>│ │
│ │ │ │ │
│ │ │ 5. 启动Spring Boot │
│ │ │───────────────>│ │
│ │ │ │ 6. 服务就绪 │
│ │ │<───────────────│ │
│ │ │ │ │
│ │ │ 7. apifox run │ │
│ │ │────────────────────────────────>│
│ │ │ │ │
│ │ │ │ 8. 执行测试用例 │
│ │ │ │<───────────────│
│ │ │ │ │
│ │ │ │ 9. 返回结果 │
│ │ │<───────────────────────────────│
│ │ │ │ │
│ │ 10. 上传Artifacts │ │
│ │<───────────────│ │ │
│ │ │ │ │
│ 11. 查看报告 │ │ │ │
│<───────────────│ │ │ │
│ │ │ │ │
3.3 目录结构图
api-test-demo/
├── .gitlab-ci.yml # GitLab CI 配置文件
├── pom.xml # Maven 项目配置
├── Makefile # 统一命令入口
├── README.md # 项目说明
│
├── docs/ # 文档目录
│ └── API-TEST-IMPLEMENTATION-PLAN.md # 本实施文档
│
├── apifox/ # Apifox 配置目录
│ ├── apifox-cli.json # CLI 配置文件 (可选)
│ ├── user-crud-scenario.json # 用户 CRUD 测试场景 (从 Apifox 导出)
│ └── environments/ # 环境配置
│ ├── dev.json # 开发环境
│ ├── test.json # 测试环境
│ └── prod.json # 生产环境
│
├── scripts/ # 脚本目录
│ ├── run-api-test.sh # API 测试执行脚本
│ ├── setup-apifox.sh # Apifox CLI 安装脚本
│ └── gitlab-runner/ # GitLab Runner 部署
│ ├── docker-compose.yml # Docker Compose 配置
│ ├── config/ # Runner 配置目录
│ │ └── config.toml # Runner 配置文件
│ ├── register-runner.sh # Runner 注册脚本
│ ├── start.sh # 启动脚本
│ ├── stop.sh # 停止脚本
│ ├── status.sh # 状态检查脚本
│ └── README.md # 使用说明
│
├── reports/ # 测试报告目录 (gitignore)
│ ├── apifox-report.html # HTML 报告
│ ├── apifox-report.json # JSON 报告
│ └── apifox-junit.xml # JUnit XML 报告
│
└── src/
├── main/
│ ├── java/com/example/demo/
│ │ ├── DemoApplication.java
│ │ ├── config/
│ │ │ └── GlobalExceptionHandler.java
│ │ ├── controller/
│ │ │ └── UserController.java
│ │ ├── service/
│ │ │ ├── UserService.java
│ │ │ └── impl/UserServiceImpl.java
│ │ ├── domain/
│ │ │ ├── entity/User.java
│ │ │ ├── dto/UserCreateDTO.java
│ │ │ ├── dto/UserUpdateDTO.java
│ │ │ └── vo/UserVO.java, Result.java
│ │ └── exception/
│ │ ├── BusinessException.java
│ │ └── UserNotFoundException.java
│ └── resources/
│ └── application.yml
└── test/
├── java/com/example/demo/
│ ├── controller/UserControllerTest.java
│ └── integration/UserApiIntegrationTest.java
└── resources/
└── application-test.yml
四、实施步骤
4.1 阶段一:GitLab Runner 部署
4.1.1 创建 Runner 部署目录
bash
# 进入项目目录
cd /home/shouzhi/ccwork/project/api-test-demo
# 创建 GitLab Runner 部署目录
mkdir -p scripts/gitlab-runner/config
cd scripts/gitlab-runner
4.1.2 创建 Docker Compose 配置文件
文件路径 : scripts/gitlab-runner/docker-compose.yml
yaml
version: '3.8'
services:
gitlab-runner:
image: gitlab/gitlab-runner:latest
container_name: gitlab-runner-api-test
restart: always
volumes:
- ./config:/etc/gitlab-runner
- /var/run/docker.sock:/var/run/docker.sock
environment:
- TZ=Asia/Shanghai
4.1.3 创建 Runner 注册脚本
文件路径 : scripts/gitlab-runner/register-runner.sh
bash
#!/bin/bash
# ============================================================
# GitLab Runner 注册脚本
# ============================================================
# 默认配置
GITLAB_URL="${GITLAB_URL:-http://192.168.50.7}"
RUNNER_NAME="${RUNNER_NAME:-api-test-demo-runner}"
RUNNER_TAGS="${RUNNER_TAGS:-api-test,docker,maven}"
DEFAULT_IMAGE="${DEFAULT_IMAGE:-maven:3.9-eclipse-temurin-17}"
# 解析命令行参数
while [[ $# -gt 0 ]]; do
case $1 in
-u|--url) GITLAB_URL="$2"; shift 2 ;;
-t|--token) REGISTRATION_TOKEN="$2"; shift 2 ;;
-n|--name) RUNNER_NAME="$2"; shift 2 ;;
-g|--tags) RUNNER_TAGS="$2"; shift 2 ;;
-i|--image) DEFAULT_IMAGE="$2"; shift 2 ;;
-h|--help)
echo "用法: $0 -t <token> [options]"
echo " -u, --url GitLab URL (默认: $GITLAB_URL)"
echo " -t, --token 注册令牌 (必需)"
echo " -n, --name Runner 名称 (默认: $RUNNER_NAME)"
echo " -g, --tags Runner 标签 (默认: $RUNNER_TAGS)"
echo " -i, --image 默认镜像 (默认: $DEFAULT_IMAGE)"
exit 0
;;
*) echo "未知参数: $1"; exit 1 ;;
esac
done
# 检查必需参数
if [ -z "$REGISTRATION_TOKEN" ]; then
echo "错误: 请提供注册令牌 (-t)"
exit 1
fi
# 执行注册
echo "开始注册 GitLab Runner..."
echo " GitLab URL: $GITLAB_URL"
echo " Runner 名称: $RUNNER_NAME"
echo " 标签: $RUNNER_TAGS"
echo " 默认镜像: $DEFAULT_IMAGE"
docker exec -it gitlab-runner-api-test gitlab-runner register \
--non-interactive \
--url "$GITLAB_URL" \
--token "$REGISTRATION_TOKEN" \
--name "$RUNNER_NAME" \
--executor "docker" \
--docker-image "$DEFAULT_IMAGE" \
--docker-volumes "/var/run/docker.sock:/var/run/docker.sock" \
--docker-volumes "/cache:/cache" \
--tag-list "$RUNNER_TAGS"
echo "Runner 注册完成!"
4.1.4 创建启动/停止脚本
启动脚本 - scripts/gitlab-runner/start.sh:
bash
#!/bin/bash
cd "$(dirname "$0")"
echo "启动 GitLab Runner..."
docker compose up -d
echo "Runner 已启动"
docker compose ps
停止脚本 - scripts/gitlab-runner/stop.sh:
bash
#!/bin/bash
cd "$(dirname "$0")"
echo "停止 GitLab Runner..."
docker compose down
echo "Runner 已停止"
状态检查脚本 - scripts/gitlab-runner/status.sh:
bash
#!/bin/bash
cd "$(dirname "$0")"
echo "============ GitLab Runner 状态 ============"
docker compose ps
echo ""
echo "============ 已注册的 Runner ============"
docker exec gitlab-runner-api-test gitlab-runner list 2>/dev/null || echo "Runner 容器未运行"
4.1.5 执行部署
bash
# 进入 Runner 目录
cd scripts/gitlab-runner
# 添加执行权限
chmod +x *.sh
# 启动 Runner 容器
./start.sh
# 验证启动状态
./status.sh
# 注册 Runner (替换为实际的注册令牌)
./register-runner.sh -t glrt-xxxxxxxxxxxxxxxxxxxx
# 再次检查状态
./status.sh
预期输出:
============ GitLab Runner 状态 ============
NAME IMAGE STATUS
gitlab-runner-api-test gitlab/gitlab-runner:latest Up 5 seconds
============ 已注册的 Runner ============
Listing configured runners ConfigFile=/etc/gitlab-runner/config.toml
api-test-demo-runner Executor=docker Token=xxxxxx URL=http://192.168.50.7
4.2 阶段二:Apifox 项目配置
4.2.1 创建 Apifox 项目
- 访问 https://apifox.com 并登录
- 点击「新建项目」
- 输入项目名称:
api-test-demo - 记录项目 ID (在项目设置 -> 基本信息中查看)
4.2.2 创建 Access Token
- 点击右上角头像 -> 个人设置
- 选择「API 访问令牌」
- 点击「新建令牌」
- 输入令牌名称:
ci-runner - 选择权限: 项目读写
- 点击「创建」并保存令牌
4.2.3 导入 API 定义
方式一: 手动创建 (推荐初学)
在 Apifox 中手动创建以下 5 个接口:
| 方法 | 路径 | 名称 |
|---|---|---|
| POST | /api/v1/users | 创建用户 |
| GET | /api/v1/users | 获取用户列表 |
| GET | /api/v1/users/{id} | 获取用户详情 |
| PATCH | /api/v1/users/{id} | 更新用户 |
| DELETE | /api/v1/users/{id} | 删除用户 |
方式二: 从 OpenAPI 导入
- 启动本地服务:
mvn spring-boot:run - 访问
http://localhost:8080/v3/api-docs获取 OpenAPI JSON - 在 Apifox 中: 导入 -> OpenAPI -> 粘贴 JSON
4.2.4 创建测试场景 (详细步骤)
本节详细记录如何在 Apifox 中创建用户 CRUD 测试场景的完整过程。

4.2.4.1 创建测试场景入口
-
在 Apifox 左侧导航栏,点击「自动化测试」
-
点击「新建测试场景」
-
输入场景名称:
用户CRUD完整流程 -
点击「确定」创建
┌─────────────────────────────────────────────────────────────┐
│ 自动化测试 │
├─────────────────────────────────────────────────────────────┤
│ 📁 测试场景 │
│ └── 📋 用户CRUD完整流程 ← 新建的测试场景 │
└─────────────────────────────────────────────────────────────┘
4.2.4.2 配置测试环境
在测试场景中配置环境变量:
- 点击测试场景右上角「环境」下拉框
- 选择或新建环境(如:
开发环境) - 配置以下环境变量:
| 变量名 | 初始值 | 说明 |
|---|---|---|
baseUrl |
http://192.168.60.81:8080 |
服务器地址 (CI 中会替换为 localhost) |
userId |
(空) | 运行时动态获取 |
4.2.4.3 添加测试步骤
按以下顺序添加 5 个测试步骤,形成完整的 CRUD 流程:
步骤 1: 创建用户 (POST)
- 点击「添加步骤」-> 选择「从接口导入」或「新建请求」
- 配置请求:
| 配置项 | 值 |
|---|---|
| 方法 | POST |
| URL | {``{baseUrl}}/api/v1/users |
| Content-Type | application/json |
- 请求体 (Body - JSON):
json
{
"name": "测试用户",
"email": "test@example.com",
"age": 25
}
- 后置操作 - 提取变量 (关键!用于传递给后续步骤):
点击「后置操作」->「提取变量」->「添加」
| 变量名 | 提取表达式 | 说明 |
|---|---|---|
userId |
$.data.id |
从响应中提取用户 ID |
javascript
// 后置脚本方式 (可选,更灵活)
var jsonData = pm.response.json();
if (jsonData.code === 200 && jsonData.data) {
pm.environment.set("userId", jsonData.data.id);
console.log("创建用户成功,userId: " + jsonData.data.id);
}
- 断言配置:
点击「断言」->「添加断言」
| 断言类型 | 表达式 | 条件 | 期望值 |
|---|---|---|---|
| JSONPath | $.code |
等于 | 200 |
| JSONPath | $.data.id |
不为空 | - |
| JSONPath | $.data.name |
等于 | 测试用户 |
步骤 2: 获取用户列表 (GET)
- 添加新步骤,配置请求:
| 配置项 | 值 |
|---|---|
| 方法 | GET |
| URL | {``{baseUrl}}/api/v1/users |
- 断言配置:
| 断言类型 | 表达式 | 条件 | 期望值 |
|---|---|---|---|
| JSONPath | $.code |
等于 | 200 |
| JSONPath | $.data |
是数组 | - |
步骤 3: 获取用户详情 (GET)
- 添加新步骤,配置请求:
| 配置项 | 值 |
|---|---|
| 方法 | GET |
| URL | {``{baseUrl}}/api/v1/users/{``{userId}} |
注意 : URL 中使用
{``{userId}}引用步骤 1 提取的变量
- 断言配置:
| 断言类型 | 表达式 | 条件 | 期望值 |
|---|---|---|---|
| JSONPath | $.code |
等于 | 200 |
| JSONPath | $.data.id |
等于 | {``{userId}} |
| JSONPath | $.data.name |
等于 | 测试用户 |
步骤 4: 更新用户 (PATCH)
- 添加新步骤,配置请求:
| 配置项 | 值 |
|---|---|
| 方法 | PATCH |
| URL | {``{baseUrl}}/api/v1/users/{``{userId}} |
| Content-Type | application/json |
- 请求体 (Body - JSON):
json
{
"name": "更新后的用户名",
"age": 30
}
- 断言配置:
| 断言类型 | 表达式 | 条件 | 期望值 |
|---|---|---|---|
| JSONPath | $.code |
等于 | 200 |
| JSONPath | $.data.name |
等于 | 更新后的用户名 |
| JSONPath | $.data.age |
等于 | 30 |
步骤 5: 删除用户 (DELETE)
- 添加新步骤,配置请求:
| 配置项 | 值 |
|---|---|
| 方法 | DELETE |
| URL | {``{baseUrl}}/api/v1/users/{``{userId}} |
- 断言配置:
| 断言类型 | 表达式 | 条件 | 期望值 |
|---|---|---|---|
| JSONPath | $.code |
等于 | 200 |
重要 : 删除接口返回
data: null是正常的,需要在 Schema 中配置允许 null(见问题 5.4)
4.2.4.4 测试场景流程图
┌─────────────────────────────────────────────────────────────────────────┐
│ 用户 CRUD 测试场景流程 │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 1. 创建用户 │────▶│ 提取 userId │────▶│ 2. 获取列表 │ │
│ │ POST │ │ $.data.id │ │ GET │ │
│ └─────────────┘ └─────────────┘ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 5. 删除用户 │◀────│ 4. 更新用户 │◀────│ 3. 获取详情 │ │
│ │ DELETE │ │ PATCH │ │ GET/{id} │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ 变量传递: userId 在步骤 1 提取,步骤 3/4/5 中使用 {{userId}} 引用 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
4.2.4.5 运行测试验证
-
确保本地服务已启动:
mvn spring-boot:run -
在 Apifox 中点击测试场景的「运行」按钮
-
查看运行结果:
用户CRUD完整流程
├── ✅ createUser [POST] http://192.168.60.81:8080/api/v1/users
│ ├── ✓ .code 等于 200 │ ├── ✓ .data.id 不为空
│ └── ✓ .data.name 等于 "测试用户" ├── ✅ getUserList [GET] http://192.168.60.81:8080/api/v1/users │ ├── ✓ .code 等于 200
│ └── ✓ .data 是数组 ├── ✅ getUserById [GET] http://192.168.60.81:8080/api/v1/users/1 │ ├── ✓ .code 等于 200
│ └── ✓ .data.id 等于 1 ├── ✅ updateUser [PATCH] http://192.168.60.81:8080/api/v1/users/1 │ ├── ✓ .code 等于 200
│ └── ✓ .data.name 等于 "更新后的用户名" └── ✅ deleteUser [DELETE] http://192.168.60.81:8080/api/v1/users/1 └── ✓ .code 等于 200总计: 5 请求 | 7 断言 | 0 失败
4.2.4.6 导出测试场景
将测试场景导出为 JSON 文件,用于 CI/CD 本地执行:
- 在测试场景上右键 -> 「导出」
- 选择导出格式:
Apifox CLI - 勾选「包含环境」
- 点击「导出」,保存为
user-crud-scenario.json - 将文件放入项目
apifox/目录
bash
# 项目结构
api-test-demo/
├── apifox/
│ └── user-crud-scenario.json ← 导出的测试场景文件
└── ...
重要提示:
- 导出的 JSON 文件中
baseUrl为 Apifox 环境配置的 IP 地址- CI 中会通过
sed命令替换为localhost- 如果 Schema 验证失败(如 data: null),需要手动修改 JSON 中的 Schema 定义(见问题 5.4)
4.2.4.7 测试用例汇总
| 序号 | 步骤名称 | 方法 | URL | 关键断言 | 变量操作 |
|---|---|---|---|---|---|
| 1 | createUser | POST | /api/v1/users | code=200, data.id 不为空 | 提取 userId |
| 2 | getUserList | GET | /api/v1/users | code=200, data 是数组 | - |
| 3 | getUserById | GET | /api/v1/users/{{userId}} | code=200, data.id={{userId}} | 使用 userId |
| 4 | updateUser | PATCH | /api/v1/users/{{userId}} | code=200, name 已更新 | 使用 userId |
| 5 | deleteUser | DELETE | /api/v1/users/{{userId}} | code=200 | 使用 userId |
4.2.5 创建本地配置文件
文件路径 : apifox/apifox-cli.json
json
{
"$schema": "https://cdn.apifox.cn/schemas/apifox-cli.json",
"version": "1.0.0",
"projectId": "${APIFOX_PROJECT_ID}",
"reporters": [
"cli",
"html",
"json",
"junit"
],
"reporterOptions": {
"html": {
"output": "./reports/api-test-report.html",
"title": "API Test Report"
},
"json": {
"output": "./reports/api-test-report.json"
},
"junit": {
"output": "./reports/api-test-report.xml"
}
},
"timeout": {
"request": 30000,
"script": 10000
},
"insecure": false,
"bail": false,
"color": "auto"
}
开发环境配置 - apifox/environments/dev.json:
json
{
"id": "dev",
"name": "开发环境",
"values": [
{
"key": "baseUrl",
"value": "http://localhost:8080",
"enabled": true
},
{
"key": "apiPrefix",
"value": "/api/v1",
"enabled": true
}
]
}
4.3 阶段三:Apifox CLI 本地验证
4.3.1 安装 Apifox CLI
bash
# 配置 npm 镜像源 (重要: 解决网络问题)
npm config set registry https://registry.npmmirror.com
# 安装 Apifox CLI
npm install -g apifox-cli
# 验证安装
apifox --version
预期输出:
1.3.2 # 版本号可能不同
4.3.2 启动本地服务
bash
# 进入项目目录
cd /home/shouzhi/ccwork/project/api-test-demo
# 启动服务
mvn spring-boot:run
# 新开终端验证服务
curl http://localhost:8080/api/v1/users
预期输出:
json
{"code":200,"message":"操作成功","data":[]}
4.3.3 执行 Apifox 测试

bash
# 设置环境变量
export APIFOX_ACCESS_TOKEN="your-token-here"
export APIFOX_PROJECT_ID="your-project-id"
# 创建报告目录
mkdir -p reports
# 执行测试
apifox run \
--access-token $APIFOX_ACCESS_TOKEN \
--project-id $APIFOX_PROJECT_ID \
--environment dev \
-r cli,html,json,junit \
--reporter-html-export ./reports/apifox-report.html \
--reporter-json-export ./reports/apifox-report.json \
--reporter-junit-export ./reports/apifox-junit.xml
预期输出:
┌─────────────────────────────────────────────────────────────────────┐
│ │
│ Apifox CLI │
│ │
│ Running collection... │
│ │
└─────────────────────────────────────────────────────────────────────┘
用户接口测试
→ 创建用户-正常
POST http://localhost:8080/api/v1/users [200 OK, 156B, 45ms]
✓ 状态码为200
✓ 响应包含用户ID
→ 获取用户列表
GET http://localhost:8080/api/v1/users [200 OK, 203B, 12ms]
✓ 状态码为200
... (更多测试用例)
┌─────────────────────────────────────────────────────────────────────┐
│ Test Results │
├─────────────────────────────────────────────────────────────────────┤
│ executed │ passed │ failed │ total │
│ 8 │ 8 │ 0 │ 8 │
└─────────────────────────────────────────────────────────────────────┘
4.4 阶段四:GitLab CI 配置
4.4.1 创建 GitLab CI 配置文件
文件路径 : .gitlab-ci.yml
重要说明: 本配置经过多次优化调整,主要改进包括:
- 使用
node:18-bullseye镜像替代maven镜像,大幅减少 npm 安装时间- 采用本地 JSON 文件运行测试,避免 Apifox 云服务 API 调用问题
- 添加 npm 缓存和超时保护机制
yaml
# ============================================================
# GitLab CI/CD 配置 - API 自动化测试流水线
# 项目: api-test-demo
# ============================================================
variables:
MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end"
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .m2/repository/
stages:
- build
- test
- api-test
- report
# ============================================================
# 阶段1: 构建
# ============================================================
build:
stage: build
image: maven:3.9-eclipse-temurin-17
script:
- echo "============ 开始构建项目 ============"
- mvn $MAVEN_CLI_OPTS clean compile -DskipTests
- echo "============ 构建完成 ============"
artifacts:
paths:
- target/classes/
expire_in: 1 hour
rules:
- if: '$CI_PIPELINE_SOURCE == "push"'
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_PIPELINE_SOURCE == "web"'
# ============================================================
# 阶段2: 单元测试
# ============================================================
unit-test:
stage: test
image: maven:3.9-eclipse-temurin-17
needs:
- build
script:
- echo "============ 运行单元测试 ============"
- mvn $MAVEN_CLI_OPTS test -Dtest=*Test
- echo "============ 单元测试完成 ============"
artifacts:
when: always
paths:
- target/surefire-reports/
reports:
junit: target/surefire-reports/TEST-*.xml
expire_in: 7 days
rules:
- if: '$CI_PIPELINE_SOURCE == "push"'
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
# ============================================================
# 阶段2: 集成测试
# ============================================================
integration-test:
stage: test
image: maven:3.9-eclipse-temurin-17
needs:
- build
script:
- echo "============ 运行集成测试 ============"
- mvn $MAVEN_CLI_OPTS test -Dtest=*IntegrationTest
- echo "============ 集成测试完成 ============"
artifacts:
when: always
paths:
- target/surefire-reports/
reports:
junit: target/surefire-reports/TEST-*.xml
expire_in: 7 days
rules:
- if: '$CI_PIPELINE_SOURCE == "push"'
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
# ============================================================
# 阶段3: Apifox API 自动化测试
# ============================================================
apifox-api-test:
stage: api-test
# 使用预装 Node.js 的镜像,避免耗时的 npm 安装
image: node:18-bullseye
timeout: 30 minutes
needs:
- unit-test
variables:
# npm 缓存配置
NPM_CONFIG_CACHE: "$CI_PROJECT_DIR/.npm"
cache:
key: npm-${CI_COMMIT_REF_SLUG}
paths:
- .npm/
- node_modules/
before_script:
# 安装 JDK 17 和 Maven
- apt-get update && apt-get install -y openjdk-17-jdk maven curl
- export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
- export PATH=$JAVA_HOME/bin:$PATH
- java -version
# 配置 npm 镜像源并安装 Apifox CLI
- npm config set registry https://registry.npmmirror.com
- npm install -g apifox-cli --registry=https://registry.npmmirror.com
- apifox --version
script:
- echo "============ 启动应用服务 ============"
# 使用离线模式如果缓存可用
- mvn $MAVEN_CLI_OPTS spring-boot:run &
- APP_PID=$!
# 等待服务就绪
- |
echo "等待服务启动..."
for i in $(seq 1 60); do
if curl -s http://localhost:8080/api/v1/users > /dev/null 2>&1; then
echo "服务已就绪!"
break
fi
echo "等待中... ($i/60)"
sleep 2
done
- curl -f http://localhost:8080/api/v1/users || (echo "服务启动失败" && exit 1)
- echo "============ 运行 Apifox 测试 ============"
- mkdir -p reports
# 使用本地测试场景文件运行(更稳定,不依赖 Apifox 云服务)
# 替换 IP 地址为 CI 环境的 localhost
- sed -i 's/192\.168\.60\.81/localhost/g' apifox/user-crud-scenario.json
# 运行测试,设置超时防止挂起
- |
timeout 300 apifox run ./apifox/user-crud-scenario.json \
-r cli,html,json,junit \
--out-dir ./reports \
--out-file apifox-report \
--timeout-request 30000 \
|| APIFOX_EXIT_CODE=$?
- echo "============ Apifox 测试完成 ============"
- kill $APP_PID 2>/dev/null || true
- ls -la reports/ || echo "报告目录为空"
- exit ${APIFOX_EXIT_CODE:-0}
artifacts:
when: always
paths:
- reports/
reports:
junit: reports/apifox-report.xml
expire_in: 30 days
rules:
- if: '$CI_PIPELINE_SOURCE == "push"'
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_PIPELINE_SOURCE == "web"'
# ============================================================
# 阶段4: 报告汇总
# ============================================================
generate-report:
stage: report
image: alpine:latest
needs:
- unit-test
- integration-test
- apifox-api-test
script:
- echo "============ 测试报告汇总 ============"
- echo "单元测试报告 - target/surefire-reports/"
- echo "Apifox报告 - reports/"
- ls -la reports/ || echo "无 Apifox 报告"
artifacts:
when: always
paths:
- target/surefire-reports/
- reports/
expire_in: 90 days
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
- if: '$CI_COMMIT_BRANCH == "dev"'
# ============================================================
# 手动触发: 全量回归测试
# ============================================================
full-regression:
stage: api-test
image: node:18-bullseye
timeout: 30 minutes
when: manual
needs:
- build
variables:
NPM_CONFIG_CACHE: "$CI_PROJECT_DIR/.npm"
cache:
key: npm-${CI_COMMIT_REF_SLUG}
paths:
- .npm/
- node_modules/
before_script:
- apt-get update && apt-get install -y openjdk-17-jdk maven curl
- export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
- export PATH=$JAVA_HOME/bin:$PATH
- npm config set registry https://registry.npmmirror.com
- npm install -g apifox-cli --registry=https://registry.npmmirror.com
script:
- echo "============ 全量回归测试 ============"
- mvn $MAVEN_CLI_OPTS spring-boot:run &
- |
echo "等待服务启动..."
for i in $(seq 1 60); do
if curl -s http://localhost:8080/api/v1/users > /dev/null 2>&1; then
echo "服务已就绪!"
break
fi
echo "等待中... ($i/60)"
sleep 2
done
- mkdir -p reports
# 替换 IP 地址为 CI 环境的 localhost
- sed -i 's/192\.168\.60\.81/localhost/g' apifox/user-crud-scenario.json
- |
timeout 600 apifox run ./apifox/user-crud-scenario.json \
--iteration-count 3 \
-r cli,html,json \
--out-dir ./reports \
--out-file regression-report \
--timeout-request 30000
- pkill -f "spring-boot:run" || true
artifacts:
when: always
paths:
- reports/
expire_in: 90 days
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manual
- if: '$CI_COMMIT_BRANCH == "dev"'
when: manual
4.4.2 配置 GitLab CI Variables
- 进入 GitLab 项目: http://192.168.50.7/your-group/api-test-demo
- 导航到: Settings -> CI/CD -> Variables
- 添加以下变量:
| Key | Value | Masked | Protected |
|---|---|---|---|
| APIFOX_ACCESS_TOKEN | APS-xxx... | Yes | Yes |
| APIFOX_PROJECT_ID | 1234567 | No | No |
4.4.3 提交并触发流水线
bash
# 添加文件
git add .gitlab-ci.yml
# 提交
git commit -m "feat(ci): 添加 GitLab CI 自动化测试配置"
# 推送
git push origin dev
五、遇到的问题与解决方案
5.1 问题一:GitLab CI needs 配置格式不兼容
问题描述
在 GitLab CI 配置中使用 needs 时,出现语法验证错误。
错误信息:
jobs:apifox-api-test:needs config should be an array of strings or objects
原始配置 (错误):
yaml
apifox-api-test:
needs:
- job: unit-test
artifacts: true
解决方案
简化 needs 配置,直接使用 job 名称字符串。
修正后配置:
yaml
apifox-api-test:
needs:
- unit-test
说明 : GitLab CI 的 needs 配置支持两种格式:
- 简单格式: 字符串数组
["job1", "job2"] - 对象格式:
[{job: "job1", artifacts: true}]
不同版本的 GitLab 对格式支持有差异,推荐使用简单格式以保证兼容性。
5.2 问题二:GitLab CI rules 中不能使用 || 操作符
问题描述
在 rules 条件中使用 || 操作符时,语法验证失败。
错误信息:
invalid value for 'rules' option
原始配置 (错误):
yaml
rules:
- if: '$CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "dev"'
解决方案
将复合条件拆分为多个独立的 if 规则。
修正后配置:
yaml
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
- if: '$CI_COMMIT_BRANCH == "dev"'
说明 : GitLab CI 的 rules:if 不支持 || 操作符进行条件组合,但多个 if 规则之间默认是 OR 关系。
5.3 问题三:npm 网络问题导致 Apifox CLI 安装失败
问题描述
在 CI 环境中安装 Apifox CLI 时,由于网络原因超时失败。
错误信息:
npm ERR! network timeout at: https://registry.npmjs.org/apifox-cli
npm ERR! network This is a problem related to network connectivity.
解决方案
配置国内 npm 镜像源。
在 .gitlab-ci.yml 的 before_script 中添加:
yaml
before_script:
# 配置 npm 镜像源 (解决网络问题)
- npm config set registry https://registry.npmmirror.com
- npm install -g apifox-cli --registry=https://registry.npmmirror.com
本地配置:
bash
# 永久配置
npm config set registry https://registry.npmmirror.com
# 验证配置
npm config get registry
# 输出: https://registry.npmmirror.com/
5.4 问题四:Apifox 删除接口返回 null 的 Schema 验证问题
问题描述
删除接口成功后返回 data: null,但 Apifox 响应 Schema 校验期望 data 为 object 类型导致测试失败。
接口响应:
json
{
"code": 200,
"message": "操作成功",
"data": null
}
错误信息:
AssertionError: data.data 应当是 object 类型,但实际是 null
原始 Schema 定义 (错误):
json
{
"type": "object",
"properties": {
"data": { "type": "object" }
}
}
解决方案
修改响应 Schema 定义,允许 data 字段为 null。
修正后 Schema (apifox/user-crud-scenario.json):
json
{
"type": "object",
"properties": {
"data": { "type": ["object", "null"] }
}
}
修改位置 : 在导出的测试场景 JSON 文件中找到 ResultVoid 类型的 Schema 定义 (ID: 238585426),将 data 字段的 type 从 "object" 改为 ["object", "null"]。
验证结果:
✓ deleteUser [DELETE] http://localhost:8080/api/v1/users/{{userId}}
✓ $.code 等于 200
✓ 响应数据符合 Schema
5.5 问题五:CI 环境 npm 安装超时 (53+ 分钟)
问题描述
使用 maven:3.9-eclipse-temurin-17 镜像时,需要从头安装 Node.js 和 npm,导致 CI Job 执行时间过长,最终超时失败。
错误现象:
Job 执行时间: 53 分钟
apt-get install nodejs...
npm install -g apifox-cli...
ERROR: Job timed out (1 hour limit)
解决方案
- 更换 Docker 镜像 : 使用预装 Node.js 的
node:18-bullseye镜像 - 添加 npm 缓存: 配置 npm 缓存目录
- 设置超时保护: 添加 job 超时和命令超时
修正后配置 (.gitlab-ci.yml):
yaml
apifox-api-test:
stage: api-test
# 改用预装 Node.js 的镜像
image: node:18-bullseye
timeout: 30 minutes
variables:
NPM_CONFIG_CACHE: "$CI_PROJECT_DIR/.npm"
cache:
key: npm-${CI_COMMIT_REF_SLUG}
paths:
- .npm/
- node_modules/
before_script:
# 只需安装 JDK 和 Maven
- apt-get update && apt-get install -y openjdk-17-jdk maven curl
- export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
- npm config set registry https://registry.npmmirror.com
- npm install -g apifox-cli --registry=https://registry.npmmirror.com
script:
# ... (省略)
# 使用 timeout 包装 apifox 命令防止挂起
- timeout 300 apifox run ./apifox/user-crud-scenario.json ...
优化效果:
| 指标 | 优化前 | 优化后 |
|---|---|---|
| npm 安装时间 | 53+ 分钟 | ~3 分钟 |
| 总执行时间 | 超时失败 | ~5-8 分钟 |
| 稳定性 | 频繁超时 | 稳定通过 |
5.6 问题六:Apifox CLI API 调用返回 HTTP 500
问题描述
使用 Apifox CLI 通过 API 方式执行测试时,返回 HTTP 500 错误。
错误信息:
Error: Request failed with status code 500
at Apifox CLI
原始命令 (失败):
bash
apifox run \
--access-token $APIFOX_ACCESS_TOKEN \
--project-id $APIFOX_PROJECT_ID \
--test-scenario-id 7787577
解决方案
改用本地 JSON 文件方式执行测试,避免依赖 Apifox 云服务 API。
步骤:
- 从 Apifox 导出测试场景为 JSON 文件
- 保存到
apifox/user-crud-scenario.json - 使用本地文件执行测试
修正后命令:
bash
# 替换 IP 地址为 CI 环境的 localhost
sed -i 's/192\.168\.60\.81/localhost/g' apifox/user-crud-scenario.json
# 使用本地文件运行
apifox run ./apifox/user-crud-scenario.json \
-r cli,html,json,junit \
--out-dir ./reports \
--out-file apifox-report
优势:
- 不依赖 Apifox 云服务网络
- 测试执行更稳定
- 测试场景可版本控制
5.7 问题七:JUnit 报告路径配置错误
问题描述
GitLab CI 配置的 JUnit 报告路径与 Apifox CLI 生成的实际路径不匹配,导致测试报告无法正确显示。
错误配置:
yaml
artifacts:
reports:
junit: reports/apifox-report.junit.xml # 错误!
实际生成的文件:
reports/apifox-report.xml # 正确路径
解决方案
修正 JUnit 报告路径配置。
修正后配置:
yaml
artifacts:
when: always
paths:
- reports/
reports:
junit: reports/apifox-report.xml # 正确路径
5.8 问题八:GitLab Runner 无法连接 GitLab 服务器
问题描述
注册 Runner 时提示无法连接到 GitLab。
错误信息:
ERROR: Registering runner... failed
runner=xxxxxx status=couldn't execute POST against http://192.168.50.7/api/v4/runners
解决方案
- 检查网络连通性:
bash
# 测试 GitLab 是否可访问
curl -I http://192.168.50.7
# 测试 API 端点
curl http://192.168.50.7/api/v4/version
- 检查 Docker 网络:
bash
# 如果使用 Docker 网络,确保可以访问宿主机
docker exec gitlab-runner-api-test curl http://host.docker.internal:80
# 或使用宿主机 IP
docker exec gitlab-runner-api-test curl http://192.168.50.7
- 检查防火墙:
bash
# 检查端口是否开放
sudo ufw status
sudo ufw allow 80/tcp
六、验证与测试

6.1 本地验证清单
| 序号 | 验证项 | 验证命令 | 预期结果 | 状态 |
|---|---|---|---|---|
| 1 | Maven 编译 | mvn compile |
BUILD SUCCESS | [ ] |
| 2 | 单元测试 | mvn test -Dtest=*Test |
Tests run: 12, Failures: 0 | [ ] |
| 3 | 服务启动 | mvn spring-boot:run |
Started DemoApplication | [ ] |
| 4 | API 响应 | curl http://localhost:8080/api/v1/users |
{"code":200,...} | [ ] |
| 5 | Apifox CLI | apifox --version |
1.x.x | [ ] |
| 6 | Apifox 测试 | apifox run ... |
All tests passed | [ ] |
6.2 CI/CD 验证清单
| 序号 | 验证项 | 验证方式 | 预期结果 | 状态 |
|---|---|---|---|---|
| 1 | Runner 注册 | GitLab -> CI/CD -> Runners | Runner 状态: online | [ ] |
| 2 | Pipeline 触发 | git push | Pipeline 自动创建 | [ ] |
| 3 | Build 阶段 | 查看 Job 日志 | BUILD SUCCESS | [ ] |
| 4 | Test 阶段 | 查看测试报告 | 所有测试通过 | [ ] |
| 5 | API-Test 阶段 | 查看 Apifox 报告 | 所有用例通过 | [ ] |
| 6 | Artifacts 下载 | 下载报告 | 报告可正常打开 | [ ] |
6.3 执行完整测试
bash
# 1. 进入项目目录
cd /home/shouzhi/ccwork/project/api-test-demo
# 2. 运行所有测试
make all-test
# 或手动执行:
# 编译
mvn clean compile -DskipTests
# 单元测试
mvn test -Dtest=*Test
# 集成测试
mvn test -Dtest=*IntegrationTest
# API 测试 (需先启动服务)
mvn spring-boot:run &
sleep 15
./scripts/run-api-test.sh
pkill -f "spring-boot:run"
# 3. 查看报告
ls -la reports/
# apifox-report.html
# apifox-report.json
# apifox-junit.xml
6.4 触发 CI 流水线
bash
# 提交代码触发流水线
git add .
git commit -m "test: 验证 CI 流水线"
git push origin dev
# 查看流水线状态
# 访问: http://192.168.50.7/your-group/api-test-demo/-/pipelines
七、附录:完整配置文件
7.1 Makefile
文件路径 : /home/shouzhi/ccwork/project/api-test-demo/Makefile
makefile
# ============================================================
# Makefile - API Test Demo 项目命令入口
# ============================================================
.PHONY: all build test integration api-test run clean help
# 默认目标
all: build test
# 显示帮助
help:
@echo "API Test Demo - 可用命令:"
@echo ""
@echo " make build - 编译项目"
@echo " make test - 运行单元测试"
@echo " make integration - 运行集成测试"
@echo " make api-test - 运行 Apifox API 测试"
@echo " make all-test - 运行所有测试"
@echo " make run - 启动服务"
@echo " make clean - 清理构建产物"
@echo ""
# 编译
build:
@echo "============ 编译项目 ============"
mvn clean compile -DskipTests
# 单元测试
test:
@echo "============ 运行单元测试 ============"
mvn test -Dtest=*Test
# 集成测试
integration:
@echo "============ 运行集成测试 ============"
mvn test -Dtest=*IntegrationTest
# Apifox API 测试
api-test:
@echo "============ 运行 Apifox API 测试 ============"
@./scripts/run-api-test.sh
# 所有测试
all-test: test integration api-test
@echo "============ 所有测试完成 ============"
# 启动服务
run:
@echo "============ 启动服务 ============"
mvn spring-boot:run
# 后台启动服务
run-bg:
@echo "============ 后台启动服务 ============"
mvn spring-boot:run &
@sleep 15
@curl -s http://localhost:8080/api/v1/users > /dev/null && echo "服务已启动" || echo "服务启动失败"
# 停止后台服务
stop:
@echo "============ 停止服务 ============"
@pkill -f "spring-boot:run" || echo "无运行中的服务"
# 清理
clean:
@echo "============ 清理构建产物 ============"
mvn clean
rm -rf reports/
# 安装 Apifox CLI
install-apifox:
@echo "============ 安装 Apifox CLI ============"
npm config set registry https://registry.npmmirror.com
npm install -g apifox-cli
apifox --version
7.2 API 测试脚本
文件路径 : /home/shouzhi/ccwork/project/api-test-demo/scripts/run-api-test.sh
bash
#!/bin/bash
# ============================================================
# API 测试运行脚本
# ============================================================
set -e
# 配置
SERVER_PORT=${SERVER_PORT:-8080}
WAIT_TIMEOUT=${WAIT_TIMEOUT:-60}
ENV=${ENV:-dev}
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo -e "${GREEN}============ API 测试脚本 ============${NC}"
# 检查环境变量
if [ -z "$APIFOX_ACCESS_TOKEN" ]; then
echo -e "${RED}错误: APIFOX_ACCESS_TOKEN 未设置${NC}"
echo "请执行: export APIFOX_ACCESS_TOKEN=your-token"
exit 1
fi
if [ -z "$APIFOX_PROJECT_ID" ]; then
echo -e "${RED}错误: APIFOX_PROJECT_ID 未设置${NC}"
echo "请执行: export APIFOX_PROJECT_ID=your-project-id"
exit 1
fi
# 检查 Apifox CLI
if ! command -v apifox &> /dev/null; then
echo -e "${YELLOW}Apifox CLI 未安装,正在安装...${NC}"
npm config set registry https://registry.npmmirror.com
npm install -g apifox-cli
fi
# 检查服务状态
check_service() {
curl -s "http://localhost:${SERVER_PORT}/api/v1/users" > /dev/null 2>&1
}
# 启动服务(如未运行)
if ! check_service; then
echo -e "${YELLOW}服务未运行,正在启动...${NC}"
mvn spring-boot:run &
SERVER_PID=$!
# 等待服务就绪
echo "等待服务启动..."
for i in $(seq 1 $WAIT_TIMEOUT); do
if check_service; then
echo -e "${GREEN}服务已就绪!${NC}"
break
fi
echo "等待中... ($i/$WAIT_TIMEOUT)"
sleep 1
done
if ! check_service; then
echo -e "${RED}服务启动超时!${NC}"
kill $SERVER_PID 2>/dev/null || true
exit 1
fi
SHOULD_STOP_SERVER=true
else
echo -e "${GREEN}服务已在运行${NC}"
SHOULD_STOP_SERVER=false
fi
# 创建报告目录
mkdir -p reports
# 运行 Apifox 测试
echo -e "${GREEN}============ 运行 Apifox 测试 ============${NC}"
apifox run \
--access-token "$APIFOX_ACCESS_TOKEN" \
--project-id "$APIFOX_PROJECT_ID" \
--environment "$ENV" \
-r cli,html,json,junit \
--reporter-html-export ./reports/apifox-report.html \
--reporter-json-export ./reports/apifox-report.json \
--reporter-junit-export ./reports/apifox-junit.xml \
|| APIFOX_EXIT_CODE=$?
# 停止服务(如果是本脚本启动的)
if [ "$SHOULD_STOP_SERVER" = true ]; then
echo "停止服务..."
kill $SERVER_PID 2>/dev/null || true
fi
# 显示报告路径
echo -e "${GREEN}============ 测试完成 ============${NC}"
echo "报告路径:"
echo " HTML: ./reports/apifox-report.html"
echo " JSON: ./reports/apifox-report.json"
echo " JUnit: ./reports/apifox-junit.xml"
exit ${APIFOX_EXIT_CODE:-0}
7.3 .gitignore 配置
添加到项目根目录的 .gitignore:
gitignore
# Apifox 报告
reports/
# 临时文件
*.tmp
*.log
# IDE
.idea/
*.iml
.vscode/
# 编译产物
target/
# Node
node_modules/
# 环境变量文件
.env
.env.local
变更记录
| 版本 | 日期 | 变更内容 | 作者 |
|---|---|---|---|
| 1.0.0 | 2025-01-14 | 初始版本 | shouzhi |
| 2.0.0 | 2025-01-14 | 按新标准重写: 前置清单、环境变量、问题记录 | shouzhi |
| 2.1.0 | 2025-01-15 | 新增问题记录: npm 超时优化、API 500 错误处理、Schema 验证修复、JUnit 路径修正 | shouzhi |
| 2.2.0 | 2025-01-15 | 同步更新 .gitlab-ci.yml 配置示例与实际生产配置一致;CI 流水线验证通过 |
shouzhi |
| 2.3.0 | 2025-01-15 | 新增 4.2.4 节:Apifox 测试场景详细录入步骤,包含 5 个接口的完整配置、变量传递、断言设置和导出流程 | shouzhi |
实验工程
