Apifox CLI + GitLab CI:接口自动化测试实施记录

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 服务器)
    • 六、验证与测试
      • [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 项目
  1. 访问 https://apifox.com 并登录
  2. 点击「新建项目」
  3. 输入项目名称: api-test-demo
  4. 记录项目 ID (在项目设置 -> 基本信息中查看)
4.2.2 创建 Access Token
  1. 点击右上角头像 -> 个人设置
  2. 选择「API 访问令牌」
  3. 点击「新建令牌」
  4. 输入令牌名称: ci-runner
  5. 选择权限: 项目读写
  6. 点击「创建」并保存令牌
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 导入

  1. 启动本地服务: mvn spring-boot:run
  2. 访问 http://localhost:8080/v3/api-docs 获取 OpenAPI JSON
  3. 在 Apifox 中: 导入 -> OpenAPI -> 粘贴 JSON
4.2.4 创建测试场景 (详细步骤)

本节详细记录如何在 Apifox 中创建用户 CRUD 测试场景的完整过程。

4.2.4.1 创建测试场景入口
  1. 在 Apifox 左侧导航栏,点击「自动化测试」

  2. 点击「新建测试场景」

  3. 输入场景名称: 用户CRUD完整流程

  4. 点击「确定」创建

    ┌─────────────────────────────────────────────────────────────┐
    │ 自动化测试 │
    ├─────────────────────────────────────────────────────────────┤
    │ 📁 测试场景 │
    │ └── 📋 用户CRUD完整流程 ← 新建的测试场景 │
    └─────────────────────────────────────────────────────────────┘

4.2.4.2 配置测试环境

在测试场景中配置环境变量:

  1. 点击测试场景右上角「环境」下拉框
  2. 选择或新建环境(如: 开发环境
  3. 配置以下环境变量:
变量名 初始值 说明
baseUrl http://192.168.60.81:8080 服务器地址 (CI 中会替换为 localhost)
userId (空) 运行时动态获取
4.2.4.3 添加测试步骤

按以下顺序添加 5 个测试步骤,形成完整的 CRUD 流程:


步骤 1: 创建用户 (POST)

  1. 点击「添加步骤」-> 选择「从接口导入」或「新建请求」
  2. 配置请求:
配置项
方法 POST
URL {``{baseUrl}}/api/v1/users
Content-Type application/json
  1. 请求体 (Body - JSON):
json 复制代码
{
  "name": "测试用户",
  "email": "test@example.com",
  "age": 25
}
  1. 后置操作 - 提取变量 (关键!用于传递给后续步骤):

点击「后置操作」->「提取变量」->「添加」

变量名 提取表达式 说明
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);
}
  1. 断言配置:

点击「断言」->「添加断言」

断言类型 表达式 条件 期望值
JSONPath $.code 等于 200
JSONPath $.data.id 不为空 -
JSONPath $.data.name 等于 测试用户

步骤 2: 获取用户列表 (GET)

  1. 添加新步骤,配置请求:
配置项
方法 GET
URL {``{baseUrl}}/api/v1/users
  1. 断言配置:
断言类型 表达式 条件 期望值
JSONPath $.code 等于 200
JSONPath $.data 是数组 -

步骤 3: 获取用户详情 (GET)

  1. 添加新步骤,配置请求:
配置项
方法 GET
URL {``{baseUrl}}/api/v1/users/{``{userId}}

注意 : URL 中使用 {``{userId}} 引用步骤 1 提取的变量

  1. 断言配置:
断言类型 表达式 条件 期望值
JSONPath $.code 等于 200
JSONPath $.data.id 等于 {``{userId}}
JSONPath $.data.name 等于 测试用户

步骤 4: 更新用户 (PATCH)

  1. 添加新步骤,配置请求:
配置项
方法 PATCH
URL {``{baseUrl}}/api/v1/users/{``{userId}}
Content-Type application/json
  1. 请求体 (Body - JSON):
json 复制代码
{
  "name": "更新后的用户名",
  "age": 30
}
  1. 断言配置:
断言类型 表达式 条件 期望值
JSONPath $.code 等于 200
JSONPath $.data.name 等于 更新后的用户名
JSONPath $.data.age 等于 30

步骤 5: 删除用户 (DELETE)

  1. 添加新步骤,配置请求:
配置项
方法 DELETE
URL {``{baseUrl}}/api/v1/users/{``{userId}}
  1. 断言配置:
断言类型 表达式 条件 期望值
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 运行测试验证
  1. 确保本地服务已启动: mvn spring-boot:run

  2. 在 Apifox 中点击测试场景的「运行」按钮

  3. 查看运行结果:

    用户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 本地执行:

  1. 在测试场景上右键 -> 「导出」
  2. 选择导出格式: Apifox CLI
  3. 勾选「包含环境」
  4. 点击「导出」,保存为 user-crud-scenario.json
  5. 将文件放入项目 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
  1. 进入 GitLab 项目: http://192.168.50.7/your-group/api-test-demo
  2. 导航到: Settings -> CI/CD -> Variables
  3. 添加以下变量:
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 配置支持两种格式:

  1. 简单格式: 字符串数组 ["job1", "job2"]
  2. 对象格式: [{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 校验期望 dataobject 类型导致测试失败。

接口响应:

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)
解决方案
  1. 更换 Docker 镜像 : 使用预装 Node.js 的 node:18-bullseye 镜像
  2. 添加 npm 缓存: 配置 npm 缓存目录
  3. 设置超时保护: 添加 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。

步骤:

  1. 从 Apifox 导出测试场景为 JSON 文件
  2. 保存到 apifox/user-crud-scenario.json
  3. 使用本地文件执行测试

修正后命令:

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
解决方案
  1. 检查网络连通性:
bash 复制代码
# 测试 GitLab 是否可访问
curl -I http://192.168.50.7

# 测试 API 端点
curl http://192.168.50.7/api/v4/version
  1. 检查 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
  1. 检查防火墙:
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

实验工程

相关推荐
间彧1 小时前
Arthas Tunnel Server 在 Kubernetes 中的深度集成与实战指南
kubernetes
我爱娃哈哈2 小时前
SpringBoot + XXL-JOB + Quartz:任务调度双引擎选型与高可用调度平台搭建
java·spring boot·后端
间彧2 小时前
在Docker Compose或Kubernetes中集成Arthas的最佳实践是什么?
kubernetes
小宇的天下2 小时前
Synopsys Technology File and Routing Rules Reference Manual (1)
java·服务器·前端
Coder_Boy_2 小时前
基于SpringAI的在线考试系统-AI智能化拓展
java·大数据·人工智能·spring boot
kida_yuan2 小时前
【Linux】在树莓派上搭建自建 Git 服务(基于 GitLab)- 实战笔记与运维清单
运维·gitlab·树莓派
n***33352 小时前
TCP/IP协议栈深度解析技术文章大纲
java·spring boot
奋进的芋圆2 小时前
Java 线程池深度指南(JDK 17+)
java
蓁蓁啊2 小时前
GCC 头文件搜索路径:-I vs -idirafter 深度解析
java·前端·javascript·嵌入式硬件·物联网