# API 文档 - 测试执行(优化版 v2.1.0) ## 元数据 - 需求编号:002-03 - API 版本:v2.1.0 - 创建时间:2026-02-05 - 创建人:AI Assistant - 状态:已完成 - 父版本:v2.0.0(重构版) - 基础路径:`/api/salesforce/apex/test` ## API 概述 测试执行 API 提供 Salesforce Apex 测试的运行、查询和管理功能。支持多种测试运行模式(全部测试、按类、按包、按方法),并提供测试结果、代码覆盖率和 Flow 覆盖率的查询功能。 ### 核心功能 1. **运行测试**:支持运行所有测试、按类运行、按包运行、按方法运行 2. **查询测试结果**:支持分页查询测试结果列表 3. **查询成功详情**:查询测试成功的详细信息 4. **查询失败详情**:查询测试失败的详细信息 5. **查询代码覆盖率**:查询代码覆盖率统计 6. **查询 Flow 覆盖率**:查询 Flow 覆盖率统计 ### 技术栈 - Spring Boot 2.7.x - MyBatis Plus - Salesforce Apex API - RESTful API ## 接口列表 ### 1. 运行所有测试 #### 接口说明 运行 Salesforce 组织中的所有 Apex 测试。 #### 请求信息 | 项目 | 内容 | |------|------| | 请求方式 | POST | | 请求路径 | `/api/salesforce/apex/test/run/all` | | Content-Type | application/json | #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | sfUserId | Long | 是 | Salesforce 用户 ID | | namespace | String | 否 | 命名空间,默认为空 | | maxFailedTests | Integer | 否 | 最大失败测试数,达到后停止测试 | | skipCodeCoverage | Boolean | 否 | 是否跳过代码覆盖率检查,默认 false | #### 请求示例 ```json { "sfUserId": 12345, "namespace": "MyNamespace", "maxFailedTests": 10, "skipCodeCoverage": false } ``` #### 响应参数 | 参数名 | 类型 | 说明 | |--------|------|------| | code | Integer | 状态码(200 成功,其他失败) | | msg | String | 提示信息 | | data | Object | 响应数据 | | data.numTestsRun | Integer | 运行的测试数量 | | data.numFailures | Integer | 失败的测试数量 | | data.totalTime | Double | 总执行时间(毫秒) | | data.successes | Array | 成功的测试结果列表 | | data.successes[].name | String | 测试名称 | | data.successes[].methodName | String | 方法名称 | | data.successes[].className | String | 类名称 | | data.successes[].time | Double | 执行时间(毫秒) | | data.failures | Array | 失败的测试结果列表 | | data.failures[].name | String | 测试名称 | | data.failures[].methodName | String | 方法名称 | | data.failures[].className | String | 类名称 | | data.failures[].message | String | 失败消息 | | data.failures[].stackTrace | String | 堆栈跟踪 | | data.failures[].type | String | 异常类型 | | data.codeCoverage | Array | 代码覆盖率结果列表 | | data.codeCoverage[].id | String | 类/触发器 ID | | data.codeCoverage[].name | String | 类/触发器名称 | | data.codeCoverage[].type | String | 类型(Class 或 Trigger) | | data.codeCoverage[].numLocations | Integer | 总位置数 | | data.codeCoverage[].numLocationsNotCovered | Integer | 未覆盖的位置数 | | data.codeCoverage[].coveragePercentage | Double | 覆盖率百分比 | | data.flowCoverage | Array | Flow 覆盖率结果列表 | | data.flowCoverage[].id | String | Flow ID | | data.flowCoverage[].name | String | Flow 名称 | | data.flowCoverage[].numElements | Integer | 总元素数量 | | data.flowCoverage[].numElementsCovered | Integer | 覆盖的元素数量 | | data.flowCoverage[].coveragePercentage | Double | 覆盖率百分比 | | data.apexLogId | String | Apex 日志 ID | | data.allPassed | Boolean | 是否全部通过 | | data.totalCoverage | Double | 总体覆盖率百分比 | | data.testResultId | Long | 测试结果 ID(数据库) | #### 成功响应示例 ```json { "code": 200, "msg": "操作成功", "data": { "numTestsRun": 100, "numFailures": 5, "totalTime": 15000.5, "successes": [ { "name": "TestClass1.testMethod1", "methodName": "testMethod1", "className": "TestClass1", "time": 150.5 } ], "failures": [ { "name": "TestClass2.testMethod2", "methodName": "testMethod2", "className": "TestClass2", "message": "Assertion failed", "stackTrace": "...", "type": "System.AssertException" } ], "codeCoverage": [ { "id": "01pxx000000xxxxx", "name": "MyClass", "type": "Class", "numLocations": 100, "numLocationsNotCovered": 20, "coveragePercentage": 80.0 } ], "flowCoverage": [ { "id": "301xx000000xxxxx", "name": "MyFlow", "numElements": 50, "numElementsCovered": 40, "coveragePercentage": 80.0 } ], "apexLogId": "07Lxx000000xxxxx", "allPassed": false, "totalCoverage": 78.5, "testResultId": 12345 } } ``` #### 失败响应示例 ```json { "code": 500, "msg": "运行所有测试失败: INVALID_SESSION_ID" } ``` --- ### 2. 按类运行测试 #### 接口说明 按指定的 Apex 类运行测试。 #### 请求信息 | 项目 | 内容 | |------|------| | 请求方式 | POST | | 请求路径 | `/api/salesforce/apex/test/run/classes` | | Content-Type | application/json | #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | sfUserId | Long | 是 | Salesforce 用户 ID | | classes | Array | 是 | 要测试的类名称数组 | | namespace | String | 否 | 命名空间,默认为空 | | maxFailedTests | Integer | 否 | 最大失败测试数 | | skipCodeCoverage | Boolean | 否 | 是否跳过代码覆盖率检查 | #### 请求示例 ```json { "sfUserId": 12345, "classes": ["TestClass1", "TestClass2"], "namespace": "MyNamespace", "maxFailedTests": 5, "skipCodeCoverage": false } ``` #### 响应参数 同"运行所有测试"接口。 --- ### 3. 按包运行测试 #### 接口说明 按指定的命名空间包运行测试。 #### 请求信息 | 项目 | 内容 | |------|------| | 请求方式 | POST | | 请求路径 | `/api/salesforce/apex/test/run/packages` | | Content-Type | application/json | #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | sfUserId | Long | 是 | Salesforce 用户 ID | | packages | Array | 是 | 要测试的包名称数组 | | namespace | String | 否 | 命名空间,默认为空 | | maxFailedTests | Integer | 否 | 最大失败测试数 | | skipCodeCoverage | Boolean | 否 | 是否跳过代码覆盖率检查 | #### 请求示例 ```json { "sfUserId": 12345, "packages": ["Package1", "Package2"], "namespace": "MyNamespace", "maxFailedTests": 5, "skipCodeCoverage": false } ``` #### 响应参数 同"运行所有测试"接口。 --- ### 4. 按方法运行测试 #### 接口说明 按指定的测试方法运行测试。 #### 请求信息 | 项目 | 内容 | |------|------| | 请求方式 | POST | | 请求路径 | `/api/salesforce/apex/test/run/methods` | | Content-Type | application/json | #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | sfUserId | Long | 是 | Salesforce 用户 ID | | tests | Array | 是 | 要运行的测试方法数组 | | tests[].className | String | 是 | 类名称 | | tests[].methodName | String | 是 | 方法名称 | | namespace | String | 否 | 命名空间,默认为空 | | maxFailedTests | Integer | 否 | 最大失败测试数 | | skipCodeCoverage | Boolean | 否 | 是否跳过代码覆盖率检查 | #### 请求示例 ```json { "sfUserId": 12345, "tests": [ { "className": "TestClass1", "methodName": "testMethod1" }, { "className": "TestClass2", "methodName": "testMethod2" } ], "namespace": "MyNamespace", "maxFailedTests": 5, "skipCodeCoverage": false } ``` #### 响应参数 同"运行所有测试"接口。 --- ### 5. 查询测试结果列表 #### 接口说明 分页查询测试结果列表。 #### 请求信息 | 项目 | 内容 | |------|------| | 请求方式 | GET | | 请求路径 | `/api/salesforce/apex/test/results` | | Content-Type | application/x-www-form-urlencoded | #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | sfUserId | Long | 是 | Salesforce 用户 ID | | pageNum | Integer | 否 | 页码,默认 1 | | pageSize | Integer | 否 | 每页大小,默认 10 | | startTime | String | 否 | 开始时间(yyyy-MM-dd HH:mm:ss) | | endTime | String | 否 | 结束时间(yyyy-MM-dd HH:mm:ss) | #### 请求示例 ``` GET /api/salesforce/apex/test/results?sfUserId=12345&pageNum=1&pageSize=10&startTime=2026-01-01 00:00:00&endTime=2026-02-01 00:00:00 ``` #### 响应参数 | 参数名 | 类型 | 说明 | |--------|------|------| | code | Integer | 状态码 | | msg | String | 提示信息 | | data | Object | 响应数据 | | data.total | Long | 总记录数 | | data.rows | Array | 结果列表 | | data.rows[].id | Long | 结果 ID | | data.rows[].sfUserId | Long | Salesforce 用户 ID | | data.rows[].numTestsRun | Integer | 运行的测试数量 | | data.rows[].numFailures | Integer | 失败的测试数量 | | data.rows[].totalTime | Double | 总执行时间 | | data.rows[].apexLogId | String | Apex 日志 ID | | data.rows[].allPassed | Boolean | 是否全部通过 | | data.rows[].totalCoverage | Double | 总体覆盖率 | | data.rows[].createTime | String | 创建时间 | #### 成功响应示例 ```json { "code": 200, "msg": "操作成功", "data": { "total": 100, "rows": [ { "id": 1, "sfUserId": 12345, "numTestsRun": 100, "numFailures": 5, "totalTime": 15000.5, "apexLogId": "07Lxx000000xxxxx", "allPassed": false, "totalCoverage": 78.5, "createTime": "2026-02-05 10:30:00" } ] } } ``` --- ### 6. 查询测试成功列表 #### 接口说明 查询指定测试结果的成功详情列表。 #### 请求信息 | 项目 | 内容 | |------|------| | 请求方式 | GET | | 请求路径 | `/api/salesforce/apex/test/successes/{testResultId}` | | Content-Type | application/x-www-form-urlencoded | #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | testResultId | Long | 是 | 测试结果 ID(路径参数) | | pageNum | Integer | 否 | 页码,默认 1 | | pageSize | Integer | 否 | 每页大小,默认 10 | #### 请求示例 ``` GET /api/salesforce/apex/test/successes/12345?pageNum=1&pageSize=10 ``` #### 响应参数 | 参数名 | 类型 | 说明 | |--------|------|------| | code | Integer | 状态码 | | msg | String | 提示信息 | | data | Object | 响应数据 | | data.total | Long | 总记录数 | | data.rows | Array | 成功详情列表 | | data.rows[].id | Long | 成功记录 ID | | data.rows[].testResultId | Long | 测试结果 ID | | data.rows[].name | String | 测试名称 | | data.rows[].methodName | String | 方法名称 | | data.rows[].className | String | 类名称 | | data.rows[].time | Double | 执行时间(毫秒) | | data.rows[].createTime | String | 创建时间 | --- ### 7. 查询测试失败列表 #### 接口说明 查询指定测试结果的失败详情列表。 #### 请求信息 | 项目 | 内容 | |------|------| | 请求方式 | GET | | 请求路径 | `/api/salesforce/apex/test/failures/{testResultId}` | | Content-Type | application/x-www-form-urlencoded | #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | testResultId | Long | 是 | 测试结果 ID(路径参数) | | pageNum | Integer | 否 | 页码,默认 1 | | pageSize | Integer | 否 | 每页大小,默认 10 | #### 请求示例 ``` GET /api/salesforce/apex/test/failures/12345?pageNum=1&pageSize=10 ``` #### 响应参数 | 参数名 | 类型 | 说明 | |--------|------|------| | code | Integer | 状态码 | | msg | String | 提示信息 | | data | Object | 响应数据 | | data.total | Long | 总记录数 | | data.rows | Array | 失败详情列表 | | data.rows[].id | Long | 失败记录 ID | | data.rows[].testResultId | Long | 测试结果 ID | | data.rows[].name | String | 测试名称 | | data.rows[].methodName | String | 方法名称 | | data.rows[].className | String | 类名称 | | data.rows[].message | String | 失败消息 | | data.rows[].stackTrace | String | 堆栈跟踪 | | data.rows[].type | String | 异常类型 | | data.rows[].time | Double | 执行时间(毫秒) | | data.rows[].createTime | String | 创建时间 | --- ### 8. 查询代码覆盖率 #### 接口说明 查询指定测试结果的代码覆盖率详情。 #### 请求信息 | 项目 | 内容 | |------|------| | 请求方式 | GET | | 请求路径 | `/api/salesforce/apex/test/coverage/code/{testResultId}` | | Content-Type | application/x-www-form-urlencoded | #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | testResultId | Long | 是 | 测试结果 ID(路径参数) | | pageNum | Integer | 否 | 页码,默认 1 | | pageSize | Integer | 否 | 每页大小,默认 10 | #### 请求示例 ``` GET /api/salesforce/apex/test/coverage/code/12345?pageNum=1&pageSize=10 ``` #### 响应参数 | 参数名 | 类型 | 说明 | |--------|------|------| | code | Integer | 状态码 | | msg | String | 提示信息 | | data | Object | 响应数据 | | data.total | Long | 总记录数 | | data.rows | Array | 代码覆盖率列表 | | data.rows[].id | Long | 覆盖率记录 ID | | data.rows[].testResultId | Long | 测试结果 ID | | data.rows[].sfId | String | Salesforce ID | | data.rows[].name | String | 类/触发器名称 | | data.rows[].type | String | 类型(Class 或 Trigger) | | data.rows[].namespace | String | 命名空间 | | data.rows[].numLocations | Integer | 总位置数 | | data.rows[].numLocationsNotCovered | Integer | 未覆盖的位置数 | | data.rows[].coveragePercentage | Double | 覆盖率百分比 | | data.rows[].createTime | String | 创建时间 | --- ### 9. 查询 Flow 覆盖率 #### 接口说明 查询指定测试结果的 Flow 覆盖率详情。 #### 请求信息 | 项目 | 内容 | |------|------| | 请求方式 | GET | | 请求路径 | `/api/salesforce/apex/test/coverage/flow/{testResultId}` | | Content-Type | application/x-www-form-urlencoded | #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | testResultId | Long | 是 | 测试结果 ID(路径参数) | | pageNum | Integer | 否 | 页码,默认 1 | | pageSize | Integer | 否 | 每页大小,默认 10 | #### 请求示例 ``` GET /api/salesforce/apex/test/coverage/flow/12345?pageNum=1&pageSize=10 ``` #### 响应参数 | 参数名 | 类型 | 说明 | |--------|------|------| | code | Integer | 状态码 | | msg | String | 提示信息 | | data | Object | 响应数据 | | data.total | Long | 总记录数 | | data.rows | Array | Flow 覆盖率列表 | | data.rows[].id | Long | 覆盖率记录 ID | | data.rows[].testResultId | Long | 测试结果 ID | | data.rows[].sfId | String | Salesforce ID | | data.rows[].name | String | Flow 名称 | | data.rows[].type | String | Flow 类型 | | data.rows[].namespace | String | 命名空间 | | data.rows[].numElements | Integer | 总元素数量 | | data.rows[].numElementsCovered | Integer | 覆盖的元素数量 | | data.rows[].numElementsNotCovered | Integer | 未覆盖的元素数量 | | data.rows[].coveragePercentage | Double | 覆盖率百分比 | | data.rows[].createTime | String | 创建时间 | ## 错误码 ### 系统错误码 | 错误码 | 说明 | 处理建议 | |--------|------|----------| | 200 | 操作成功 | - | | 500 | 系统内部错误 | 联系管理员 | | 401 | 未授权 | 检查登录状态 | | 403 | 无权限 | 检查用户权限 | | 404 | 资源不存在 | 检查请求参数 | | 400 | 请求参数错误 | 检查请求参数格式 | ### 业务错误码 | 错误码 | 说明 | 处理建议 | |--------|------|----------| | APEX_TEST_001 | 运行所有测试失败 | 检查 Salesforce 连接和权限 | | APEX_TEST_002 | 按类运行测试失败 | 检查类名是否正确 | | APEX_TEST_003 | 按包运行测试失败 | 检查包名是否正确 | | APEX_TEST_004 | 按方法运行测试失败 | 检查类名和方法名是否正确 | | APEX_TEST_005 | 查询测试结果列表失败 | 检查查询参数 | | APEX_TEST_006 | 查询测试成功列表失败 | 检查测试结果 ID 是否存在 | | APEX_TEST_007 | 查询测试失败列表失败 | 检查测试结果 ID 是否存在 | | APEX_TEST_008 | 查询代码覆盖率失败 | 检查测试结果 ID 是否存在 | | APEX_TEST_009 | 查询 Flow 覆盖率失败 | 检查测试结果 ID 是否存在 | | APEX_TEST_010 | 保存测试结果失败 | 检查数据库连接 | | APEX_TEST_011 | 保存测试成功详情失败 | 检查数据库连接 | | APEX_TEST_012 | 保存测试失败详情失败 | 检查数据库连接 | | APEX_TEST_013 | 保存代码覆盖率失败 | 检查数据库连接 | | APEX_TEST_014 | 保存 Flow 覆盖率失败 | 检查数据库连接 | | APEX_TEST_015 | 无效的 Salesforce 会话 | 重新登录 Salesforce | | APEX_TEST_016 | Salesforce 连接超时 | 检查网络连接 | | APEX_TEST_017 | 无效的测试类名 | 检查类名是否正确 | | APEX_TEST_018 | 无效的测试方法名 | 检查方法名是否正确 | | APEX_TEST_019 | 无效的命名空间 | 检查命名空间是否正确 | | APEX_TEST_020 | 测试执行被中断 | 重新执行测试 | ## 相关文档 - [需求文档](../requirements/sub/2026-01-28-002-03-测试执行.md) - [设计文档(优化版 v2.1.0)](../design/2026-02-04-002-03-测试执行-设计-v2.md) - [决策记录(优化版 v2.1.0)](../decisions/2026-02-04-002-03-ADR-测试执行技术选型-v2.md) - [变更日志(优化版 v2.1.0)](../changelog/2026-02-05-002-03-changelog-v2.md) - [复盘文档(优化版 v2.1.0)](../retros/2026-02-05-002-03-retro-v2.md) - [会话记录(优化版 v2.1.0)](../sessions/2026-02-04-002-03-session-v2.md) - [API 文档(重构版 v2.0.0)](./2026-02-04-002-03-api.md)