20 KiB
API 文档 - 测试执行
元数据
- 需求编号:002-03
- 需求名称:测试执行
- 创建时间:2026-02-03
- 创建人:AI Assistant
- 版本:v1.0.0
- 状态:已完成
API 概述
本文档描述了 Salesforce Apex 测试执行功能的 RESTful API 接口。这些接口提供了运行 Apex 测试、查询测试结果、查看代码覆盖率和 Flow 覆盖率等功能。
核心功能
- 测试执行:支持运行所有测试、按类运行、按包运行、按方法运行
- 结果查询:支持分页查询历史测试结果
- 详情查询:支持查询测试成功、失败、覆盖率等详细信息
- 覆盖率分析:支持查询代码覆盖率和 Flow 覆盖率
技术栈
- 框架:Spring Boot 2.7.x
- 文档:Swagger 3.0 (OpenAPI 3.0)
- 权限:Spring Security + @PreAuthorize
- 基础路径:
/api/apex/test
权限说明
所有接口都需要相应的权限才能访问:
| 权限标识 | 说明 | 适用接口 |
|---|---|---|
apex:test:execute |
测试执行权限 | run-all、run-by-classes、run-by-packages、run-by-methods |
apex:test:query |
测试查询权限 | results、details、code-coverage、flow-coverage |
接口列表
1. 运行所有测试
接口名称:运行所有测试
功能描述:运行 Salesforce 组织中的所有 Apex 测试类
请求方式:POST
请求路径:/api/apex/test/run-all
权限要求:apex:test:execute
请求参数:
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
| skipCodeCoverage | Boolean | 否 | 是否跳过代码覆盖率检查 | false |
| maxFailedTests | Integer | 否 | 最大失败测试数,0 表示不限制 | 0 |
请求示例:
{
"skipCodeCoverage": false,
"maxFailedTests": 0
}
响应参数:
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | Integer | 状态码(200 成功,其他失败) |
| msg | String | 提示信息 |
| data | Object | 测试结果数据 |
| data.numTestsRun | Integer | 运行的测试数量 |
| data.numFailures | Integer | 失败的测试数量 |
| data.totalTime | Double | 总执行时间(毫秒) |
| data.successes | Array | 成功的测试列表 |
| data.failures | Array | 失败的测试列表 |
| data.codeCoverage | Array | 代码覆盖率结果列表 |
| data.flowCoverage | Array | Flow 覆盖率结果列表 |
| data.apexLogId | String | Apex 日志 ID |
成功响应示例:
{
"code": 200,
"msg": "操作成功",
"data": {
"numTestsRun": 100,
"numFailures": 2,
"totalTime": 12345.67,
"successes": [
{
"name": "AccountTest.testCreate",
"time": 123.45,
"methodName": "testCreate",
"className": "AccountTest"
}
],
"failures": [
{
"name": "AccountTest.testUpdate",
"message": "System.AssertException: Assertion Failed",
"methodName": "testUpdate",
"className": "AccountTest",
"stackTrace": "Class.AccountTest.testUpdate: line 15, column 1",
"type": "System.AssertException"
}
],
"codeCoverage": [
{
"name": "AccountTest",
"type": "Class",
"numLocations": 100,
"numLocationsNotCovered": 20,
"coveragePercent": 80.0
}
],
"flowCoverage": [],
"apexLogId": "07Lxx0000003DHb2AAG"
}
}
失败响应示例:
{
"code": 500,
"msg": "运行所有测试失败: ConnectionException: Invalid session ID"
}
2. 运行指定类的测试
接口名称:运行指定类的测试
功能描述:运行指定 Apex 类的所有测试方法
请求方式:POST
请求路径:/api/apex/test/run-by-classes
权限要求:apex:test:execute
请求参数:
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
| classes | Array[String] | 是 | 要测试的类名称数组 | ["AccountTest", "ContactTest"] |
| skipCodeCoverage | Boolean | 否 | 是否跳过代码覆盖率检查 | false |
| maxFailedTests | Integer | 否 | 最大失败测试数 | 0 |
请求示例:
{
"classes": ["AccountTest", "ContactTest"],
"skipCodeCoverage": false,
"maxFailedTests": 0
}
响应参数:同「运行所有测试」接口
成功响应示例:
{
"code": 200,
"msg": "操作成功",
"data": {
"numTestsRun": 20,
"numFailures": 0,
"totalTime": 2345.67,
"successes": [
{
"name": "AccountTest.testCreate",
"time": 123.45,
"methodName": "testCreate",
"className": "AccountTest"
}
],
"failures": [],
"codeCoverage": [
{
"name": "AccountTest",
"type": "Class",
"numLocations": 100,
"numLocationsNotCovered": 20,
"coveragePercent": 80.0
}
],
"flowCoverage": [],
"apexLogId": "07Lxx0000003DHb2AAG"
}
}
3. 运行指定包的测试
接口名称:运行指定包的测试
功能描述:运行指定命名空间包中的所有 Apex 测试
请求方式:POST
请求路径:/api/apex/test/run-by-packages
权限要求:apex:test:execute
请求参数:
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
| namespace | String | 否 | 命名空间 | "datai" |
| packages | Array[String] | 是 | 要测试的包数组 | ["com.datai.test"] |
| skipCodeCoverage | Boolean | 否 | 是否跳过代码覆盖率检查 | false |
| maxFailedTests | Integer | 否 | 最大失败测试数 | 0 |
请求示例:
{
"namespace": "datai",
"packages": ["com.datai.test"],
"skipCodeCoverage": false,
"maxFailedTests": 0
}
响应参数:同「运行所有测试」接口
4. 运行指定测试方法
接口名称:运行指定测试方法
功能描述:运行指定的 Apex 测试方法
请求方式:POST
请求路径:/api/apex/test/run-by-methods
权限要求:apex:test:execute
请求参数:
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
| tests | Array[Object] | 是 | 测试方法数组 | 见示例 |
| tests[].className | String | 是 | 测试类名称 | "AccountTest" |
| tests[].testMethods | Array[String] | 是 | 测试方法名称数组 | ["testCreate", "testUpdate"] |
| skipCodeCoverage | Boolean | 否 | 是否跳过代码覆盖率检查 | false |
| maxFailedTests | Integer | 否 | 最大失败测试数 | 0 |
请求示例:
{
"tests": [
{
"className": "AccountTest",
"testMethods": ["testCreate", "testUpdate", "testDelete"]
},
{
"className": "ContactTest",
"testMethods": ["testCreate", "testUpdate"]
}
],
"skipCodeCoverage": false,
"maxFailedTests": 0
}
响应参数:同「运行所有测试」接口
5. 查询测试结果列表
接口名称:查询测试结果列表
功能描述:分页查询历史测试结果
请求方式:GET
请求路径:/api/apex/test/results
权限要求:apex:test:query
请求参数:
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
| testRunId | String | 否 | 测试运行 ID | "707xx0000003DHb2AAG" |
| startTime | String | 否 | 开始时间(yyyy-MM-dd HH:mm:ss) | "2026-01-28 10:00:00" |
| endTime | String | 否 | 结束时间(yyyy-MM-dd HH:mm:ss) | "2026-01-28 12:00:00" |
| pageNum | Integer | 否 | 页码,默认为 1 | 1 |
| pageSize | Integer | 否 | 每页大小,默认为 10 | 20 |
请求示例:
GET /api/apex/test/results?pageNum=1&pageSize=20
响应参数:
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | Integer | 状态码 |
| msg | String | 提示信息 |
| data | Object | 分页数据 |
| data.total | Integer | 总记录数 |
| data.rows | Array | 测试结果列表 |
| data.rows[].id | Long | 记录 ID |
| data.rows[].testRunId | String | 测试运行 ID |
| data.rows[].numTestsRun | Integer | 运行的测试数量 |
| data.rows[].numFailures | Integer | 失败的测试数量 |
| data.rows[].totalTime | Double | 总执行时间 |
| data.rows[].apexLogId | String | Apex 日志 ID |
| data.rows[].testTime | String | 测试时间 |
| data.rows[].createTime | String | 创建时间 |
成功响应示例:
{
"code": 200,
"msg": "操作成功",
"data": {
"total": 50,
"rows": [
{
"id": 1,
"testRunId": "707xx0000003DHb2AAG",
"numTestsRun": 10,
"numFailures": 0,
"totalTime": 1234.56,
"apexLogId": "07Lxx0000003DHb2AAG",
"testTime": "2026-01-28 10:00:00",
"createTime": "2026-01-28 10:00:00"
}
]
}
}
6. 查询测试详情
接口名称:查询测试详情
功能描述:查询指定测试结果的详细信息,包括成功、失败、覆盖率等
请求方式:GET
请求路径:/api/apex/test/details
权限要求:apex:test:query
请求参数:
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
| testResultId | Long | 是 | 测试结果 ID | 1 |
| type | String | 否 | 类型(success/failure/all),默认为 "all" | "all" |
| pageNum | Integer | 否 | 页码,默认为 1 | 1 |
| pageSize | Integer | 否 | 每页大小,默认为 10 | 20 |
请求示例:
GET /api/apex/test/details?testResultId=1&type=all&pageNum=1&pageSize=20
响应参数:
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | Integer | 状态码 |
| msg | String | 提示信息 |
| data | Object | 测试详情数据 |
| data.successes | Array | 成功的测试列表 |
| data.successes[].id | Long | 记录 ID |
| data.successes[].testResultId | Long | 测试结果 ID |
| data.successes[].className | String | 类名 |
| data.successes[].methodName | String | 方法名 |
| data.successes[].time | Double | 执行时间 |
| data.failures | Array | 失败的测试列表 |
| data.failures[].id | Long | 记录 ID |
| data.failures[].testResultId | Long | 测试结果 ID |
| data.failures[].className | String | 类名 |
| data.failures[].methodName | String | 方法名 |
| data.failures[].message | String | 失败消息 |
| data.failures[].stackTrace | String | 堆栈跟踪 |
| data.failures[].type | String | 异常类型 |
成功响应示例:
{
"code": 200,
"msg": "操作成功",
"data": {
"successes": [
{
"id": 1,
"testResultId": 1,
"className": "AccountTest",
"methodName": "testCreate",
"time": 123.45,
"createTime": "2026-01-28 10:00:00"
}
],
"failures": [
{
"id": 2,
"testResultId": 1,
"className": "AccountTest",
"methodName": "testUpdate",
"message": "System.AssertException: Assertion Failed",
"stackTrace": "Class.AccountTest.testUpdate: line 15, column 1",
"type": "System.AssertException",
"createTime": "2026-01-28 10:00:00"
}
]
}
}
7. 查询代码覆盖率
接口名称:查询代码覆盖率
功能描述:查询指定测试结果的代码覆盖率
请求方式:GET
请求路径:/api/apex/test/code-coverage
权限要求:apex:test:query
请求参数:
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
| testResultId | Long | 否 | 测试结果 ID | 1 |
| name | String | 否 | 类/触发器名称 | "AccountTest" |
| type | String | 否 | 类型(Class/Trigger) | "Class" |
| minCoverage | Double | 否 | 最小覆盖率 | 75.0 |
| maxCoverage | Double | 否 | 最大覆盖率 | 100.0 |
| pageNum | Integer | 否 | 页码,默认为 1 | 1 |
| pageSize | Integer | 否 | 每页大小,默认为 10 | 20 |
请求示例:
GET /api/apex/test/code-coverage?type=Class&minCoverage=75&pageNum=1&pageSize=20
响应参数:
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | Integer | 状态码 |
| msg | String | 提示信息 |
| data | Object | 分页数据 |
| data.total | Integer | 总记录数 |
| data.rows | Array | 代码覆盖率列表 |
| data.rows[].id | Long | 记录 ID |
| data.rows[].testResultId | Long | 测试结果 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[].coveragePercent | Double | 覆盖率百分比 |
| data.rows[].createTime | String | 创建时间 |
成功响应示例:
{
"code": 200,
"msg": "操作成功",
"data": {
"total": 30,
"rows": [
{
"id": 1,
"testResultId": 1,
"name": "AccountTest",
"type": "Class",
"namespace": null,
"numLocations": 100,
"numLocationsNotCovered": 20,
"coveragePercent": 80.0,
"createTime": "2026-01-28 10:00:00"
}
]
}
}
8. 查询 Flow 覆盖率
接口名称:查询 Flow 覆盖率
功能描述:查询指定测试结果的 Flow 覆盖率
请求方式:GET
请求路径:/api/apex/test/flow-coverage
权限要求:apex:test:query
请求参数:
| 参数名 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
| testResultId | Long | 否 | 测试结果 ID | 1 |
| name | String | 否 | Flow 名称 | "Account_Flow" |
| type | String | 否 | Flow 类型 | "RecordTriggeredFlow" |
| minCoverage | Double | 否 | 最小覆盖率 | 75.0 |
| maxCoverage | Double | 否 | 最大覆盖率 | 100.0 |
| pageNum | Integer | 否 | 页码,默认为 1 | 1 |
| pageSize | Integer | 否 | 每页大小,默认为 10 | 20 |
请求示例:
GET /api/apex/test/flow-coverage?pageNum=1&pageSize=20
响应参数:
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | Integer | 状态码 |
| msg | String | 提示信息 |
| data | Object | 分页数据 |
| data.total | Integer | 总记录数 |
| data.rows | Array | Flow 覆盖率列表 |
| data.rows[].id | Long | 记录 ID |
| data.rows[].testResultId | Long | 测试结果 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[].coveragePercent | Double | 覆盖率百分比 |
| data.rows[].createTime | String | 创建时间 |
成功响应示例:
{
"code": 200,
"msg": "操作成功",
"data": {
"total": 10,
"rows": [
{
"id": 1,
"testResultId": 1,
"name": "Account_Flow",
"type": "RecordTriggeredFlow",
"namespace": null,
"numElements": 50,
"numElementsCovered": 40,
"coveragePercent": 80.0,
"createTime": "2026-01-28 10:00:00"
}
]
}
}
错误码
系统错误码
| 错误码 | 错误消息 | 说明 | HTTP 状态码 |
|---|---|---|---|
| 200 | 操作成功 | 请求处理成功 | 200 |
| 500 | 操作失败 | 服务器内部错误 | 500 |
| 401 | 未授权 | 用户未登录或 Token 无效 | 401 |
| 403 | 禁止访问 | 用户没有权限访问该资源 | 403 |
| 404 | 资源不存在 | 请求的资源不存在 | 404 |
| 400 | 请求参数错误 | 请求参数不合法 | 400 |
业务错误码
| 错误码 | 错误消息 | 说明 | HTTP 状态码 |
|---|---|---|---|
| APEX_TEST_001 | 测试请求为空 | 测试请求参数不能为空 | 400 |
| APEX_TEST_002 | 测试类为空 | 测试类名称数组不能为空 | 400 |
| APEX_TEST_003 | 测试包为空 | 测试包数组不能为空 | 400 |
| APEX_TEST_004 | 测试方法为空 | 测试方法数组不能为空 | 400 |
| APEX_TEST_005 | 测试结果 ID 为空 | 测试结果 ID 不能为空 | 400 |
| APEX_TEST_006 | 连接失败 | 无法建立与 Salesforce 的连接 | 500 |
| APEX_TEST_007 | 测试执行失败 | Apex 测试执行失败 | 500 |
| APEX_TEST_008 | 测试结果保存失败 | 测试结果保存到数据库失败 | 500 |
| APEX_TEST_009 | 代码覆盖率保存失败 | 代码覆盖率保存到数据库失败 | 500 |
| APEX_TEST_010 | Flow 覆盖率保存失败 | Flow 覆盖率保存到数据库失败 | 500 |
| APEX_TEST_011 | 测试结果不存在 | 指定的测试结果不存在 | 404 |
| APEX_TEST_012 | 测试结果查询失败 | 查询测试结果失败 | 500 |
| APEX_TEST_013 | 测试详情查询失败 | 查询测试详情失败 | 500 |
| APEX_TEST_014 | 覆盖率查询失败 | 查询覆盖率失败 | 500 |
错误响应示例
参数错误:
{
"code": 400,
"msg": "测试类不能为空",
"data": null
}
权限不足:
{
"code": 403,
"msg": "访问权限不足",
"data": null
}
服务器错误:
{
"code": 500,
"msg": "测试执行失败: ConnectionException: Invalid session ID",
"data": null
}
数据模型
测试结果 (RunTestsResultVo)
| 字段名 | 类型 | 说明 |
|---|---|---|
| numTestsRun | Integer | 运行的测试数量 |
| numFailures | Integer | 失败的测试数量 |
| totalTime | Double | 总执行时间(毫秒) |
| successes | List | 成功的测试列表 |
| failures | List | 失败的测试列表 |
| codeCoverage | List | 代码覆盖率列表 |
| codeCoverageWarnings | List | 代码覆盖率警告列表 |
| flowCoverage | List | Flow 覆盖率列表 |
| flowCoverageWarnings | List | Flow 覆盖率警告列表 |
| apexLogId | String | Apex 日志 ID |
测试成功详情 (RunTestSuccessVo)
| 字段名 | 类型 | 说明 |
|---|---|---|
| name | String | 测试名称 |
| time | Double | 执行时间(毫秒) |
| methodName | String | 方法名称 |
| className | String | 类名称 |
测试失败详情 (RunTestFailureVo)
| 字段名 | 类型 | 说明 |
|---|---|---|
| name | String | 测试名称 |
| message | String | 失败消息 |
| methodName | String | 方法名称 |
| className | String | 类名称 |
| stackTrace | String | 堆栈跟踪 |
| type | String | 异常类型 |
代码覆盖率结果 (CodeCoverageResultVo)
| 字段名 | 类型 | 说明 |
|---|---|---|
| name | String | 类/触发器名称 |
| type | String | 类型(Class/Trigger) |
| namespace | String | 命名空间 |
| numLocations | Integer | 总位置数 |
| numLocationsNotCovered | Integer | 未覆盖位置数 |
| coveragePercent | Double | 覆盖率百分比 |
Flow 覆盖率结果 (FlowCoverageResultVo)
| 字段名 | 类型 | 说明 |
|---|---|---|
| name | String | Flow 名称 |
| type | String | Flow 类型 |
| namespace | String | 命名空间 |
| numElements | Integer | 总元素数量 |
| numElementsCovered | Integer | 覆盖的元素数量 |
| coveragePercent | Double | 覆盖率百分比 |
相关文档
文档版本:v1.0.0
最后更新时间:2026-02-03
维护人:AI Assistant