datai/datai-scenes/datai-scene-salesforce/docs/api-docs/2026-02-02-002-03-api.md

712 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# API 文档 - 测试执行
## 元数据
- 需求编号002-03
- 需求名称:测试执行
- 创建时间2026-02-03
- 创建人AI Assistant
- 版本v1.0.0
- 状态:已完成
## API 概述
本文档描述了 Salesforce Apex 测试执行功能的 RESTful API 接口。这些接口提供了运行 Apex 测试、查询测试结果、查看代码覆盖率和 Flow 覆盖率等功能。
### 核心功能
1. **测试执行**:支持运行所有测试、按类运行、按包运行、按方法运行
2. **结果查询**:支持分页查询历史测试结果
3. **详情查询**:支持查询测试成功、失败、覆盖率等详细信息
4. **覆盖率分析**:支持查询代码覆盖率和 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 |
**请求示例**
```json
{
"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 |
**成功响应示例**
```json
{
"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"
}
}
```
**失败响应示例**
```json
{
"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 |
**请求示例**
```json
{
"classes": ["AccountTest", "ContactTest"],
"skipCodeCoverage": false,
"maxFailedTests": 0
}
```
**响应参数**:同「运行所有测试」接口
**成功响应示例**
```json
{
"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 |
**请求示例**
```json
{
"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 |
**请求示例**
```json
{
"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 | 创建时间 |
**成功响应示例**
```json
{
"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 | 异常类型 |
**成功响应示例**
```json
{
"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 | 创建时间 |
**成功响应示例**
```json
{
"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 | 创建时间 |
**成功响应示例**
```json
{
"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 |
### 错误响应示例
**参数错误**
```json
{
"code": 400,
"msg": "测试类不能为空",
"data": null
}
```
**权限不足**
```json
{
"code": 403,
"msg": "访问权限不足",
"data": null
}
```
**服务器错误**
```json
{
"code": 500,
"msg": "测试执行失败: ConnectionException: Invalid session ID",
"data": null
}
```
## 数据模型
### 测试结果 (RunTestsResultVo)
| 字段名 | 类型 | 说明 |
|--------|------|------|
| numTestsRun | Integer | 运行的测试数量 |
| numFailures | Integer | 失败的测试数量 |
| totalTime | Double | 总执行时间(毫秒) |
| successes | List<RunTestSuccessVo> | 成功的测试列表 |
| failures | List<RunTestFailureVo> | 失败的测试列表 |
| codeCoverage | List<CodeCoverageResultVo> | 代码覆盖率列表 |
| codeCoverageWarnings | List<CodeCoverageWarningVo> | 代码覆盖率警告列表 |
| flowCoverage | List<FlowCoverageResultVo> | Flow 覆盖率列表 |
| flowCoverageWarnings | List<FlowCoverageWarningVo> | 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 | 覆盖率百分比 |
## 相关文档
- [需求文档](../requirements/sub/2026-01-28-002-03-测试执行.md)
- [设计文档](../design/2026-02-02-002-03-测试执行-设计.md)
- [决策记录](../decisions/2026-02-02-002-03-ADR-测试执行技术选型.md)
- [变更日志](../changelog/2026-02-02-002-03-changelog.md)
- [复盘文档](../retros/2026-02-02-002-03-retro.md)
- [会话记录](../sessions/2026-02-02-002-03-session.md)
---
**文档版本**v1.0.0
**最后更新时间**2026-02-03
**维护人**AI Assistant