523 lines
14 KiB
Markdown
523 lines
14 KiB
Markdown
# API 文档 - 测试执行(重构版)
|
||
|
||
## 元数据
|
||
- 需求编号:002-03
|
||
- 文档版本:v2.0.0
|
||
- 创建时间:2026-02-04
|
||
- 创建人:AI Assistant
|
||
- 状态:已完成
|
||
|
||
## API 概述
|
||
测试执行 API 提供 Salesforce Apex 测试的完整功能,包括运行测试(全部、按类、按包、按方法)、查询测试结果、查询代码覆盖率、查询 Flow 覆盖率等。所有接口都使用 source org 类型进行测试执行。
|
||
|
||
### 基础信息
|
||
- **Base URL**:`/apex/test`
|
||
- **Content-Type**:`application/json`
|
||
- **认证方式**:JWT Token(通过 Header 传递)
|
||
|
||
## 接口列表
|
||
|
||
### 1. 运行所有测试
|
||
|
||
#### 接口说明
|
||
运行 Salesforce Org 中的所有 Apex 测试。
|
||
|
||
- **请求方式**:POST
|
||
- **请求路径**:`/apex/test/run-all`
|
||
- **权限要求**:`apex:test:run`
|
||
|
||
#### 请求参数
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| skipCodeCoverage | Boolean | 否 | 是否跳过代码覆盖率检查,默认 false |
|
||
| maxFailedTests | Integer | 否 | 最大失败测试数,默认 -1(不限制) |
|
||
|
||
#### 请求示例
|
||
```json
|
||
{
|
||
"skipCodeCoverage": false,
|
||
"maxFailedTests": -1
|
||
}
|
||
```
|
||
|
||
#### 响应参数
|
||
|
||
| 参数名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| 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 覆盖率结果数组 |
|
||
|
||
#### 成功响应示例
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"numTestsRun": 100,
|
||
"numFailures": 5,
|
||
"totalTime": 15000.5,
|
||
"successes": [
|
||
{
|
||
"id": "01pxx000000xxxx",
|
||
"name": "AccountTriggerTest",
|
||
"methodName": "testInsert",
|
||
"className": "AccountTriggerTest",
|
||
"time": 150.5,
|
||
"message": null
|
||
}
|
||
],
|
||
"failures": [
|
||
{
|
||
"id": "01pxx000000xxxx",
|
||
"name": "ContactTriggerTest",
|
||
"methodName": "testUpdate",
|
||
"className": "ContactTriggerTest",
|
||
"message": "Assertion failed",
|
||
"stackTrace": "...",
|
||
"time": 200.0
|
||
}
|
||
],
|
||
"codeCoverage": [
|
||
{
|
||
"id": "01pxx000000xxxx",
|
||
"name": "AccountTrigger",
|
||
"type": "Trigger",
|
||
"coveragePercent": 85.5
|
||
}
|
||
],
|
||
"flowCoverage": [
|
||
{
|
||
"id": "301xx000000xxxx",
|
||
"name": "Account_Automation",
|
||
"type": "AutoLaunchedFlow",
|
||
"coveragePercent": 90.0
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 失败响应示例
|
||
```json
|
||
{
|
||
"code": 500,
|
||
"msg": "运行测试失败: 连接超时"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 2. 按类运行测试
|
||
|
||
#### 接口说明
|
||
运行指定 Apex 类的测试。
|
||
|
||
- **请求方式**:POST
|
||
- **请求路径**:`/apex/test/run-by-classes`
|
||
- **权限要求**:`apex:test:run`
|
||
|
||
#### 请求参数
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| classes | Array<String> | 是 | 要测试的类名称数组 |
|
||
| namespace | String | 否 | 命名空间 |
|
||
| skipCodeCoverage | Boolean | 否 | 是否跳过代码覆盖率检查,默认 false |
|
||
| maxFailedTests | Integer | 否 | 最大失败测试数,默认 -1(不限制) |
|
||
|
||
#### 请求示例
|
||
```json
|
||
{
|
||
"classes": ["AccountTriggerTest", "ContactTriggerTest"],
|
||
"namespace": "",
|
||
"skipCodeCoverage": false,
|
||
"maxFailedTests": -1
|
||
}
|
||
```
|
||
|
||
#### 响应参数
|
||
同「运行所有测试」接口。
|
||
|
||
---
|
||
|
||
### 3. 按包运行测试
|
||
|
||
#### 接口说明
|
||
运行指定包中的所有 Apex 测试。
|
||
|
||
- **请求方式**:POST
|
||
- **请求路径**:`/apex/test/run-by-packages`
|
||
- **权限要求**:`apex:test:run`
|
||
|
||
#### 请求参数
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| packages | Array<String> | 是 | 要测试的包数组 |
|
||
| namespace | String | 否 | 命名空间 |
|
||
| skipCodeCoverage | Boolean | 否 | 是否跳过代码覆盖率检查,默认 false |
|
||
| maxFailedTests | Integer | 否 | 最大失败测试数,默认 -1(不限制) |
|
||
|
||
#### 请求示例
|
||
```json
|
||
{
|
||
"packages": ["com.example.tests", "com.example.integration"],
|
||
"namespace": "",
|
||
"skipCodeCoverage": false,
|
||
"maxFailedTests": -1
|
||
}
|
||
```
|
||
|
||
#### 响应参数
|
||
同「运行所有测试」接口。
|
||
|
||
---
|
||
|
||
### 4. 按方法运行测试
|
||
|
||
#### 接口说明
|
||
运行指定的 Apex 测试方法。
|
||
|
||
- **请求方式**:POST
|
||
- **请求路径**:`/apex/test/run-by-methods`
|
||
- **权限要求**:`apex:test:run`
|
||
|
||
#### 请求参数
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| tests | Array<Object> | 是 | 要运行的测试方法数组 |
|
||
| tests[].classId | String | 否 | 测试类 ID |
|
||
| tests[].className | String | 是 | 测试类名称 |
|
||
| tests[].testMethods | Array<String> | 是 | 要运行的测试方法名称数组 |
|
||
| namespace | String | 否 | 命名空间 |
|
||
| skipCodeCoverage | Boolean | 否 | 是否跳过代码覆盖率检查,默认 false |
|
||
| maxFailedTests | Integer | 否 | 最大失败测试数,默认 -1(不限制) |
|
||
|
||
#### 请求示例
|
||
```json
|
||
{
|
||
"tests": [
|
||
{
|
||
"className": "AccountTriggerTest",
|
||
"testMethods": ["testInsert", "testUpdate"]
|
||
},
|
||
{
|
||
"className": "ContactTriggerTest",
|
||
"testMethods": ["testDelete"]
|
||
}
|
||
],
|
||
"namespace": "",
|
||
"skipCodeCoverage": false,
|
||
"maxFailedTests": -1
|
||
}
|
||
```
|
||
|
||
#### 响应参数
|
||
同「运行所有测试」接口。
|
||
|
||
---
|
||
|
||
### 5. 查询测试成功详情
|
||
|
||
#### 接口说明
|
||
查询指定测试结果的成功详情。
|
||
|
||
- **请求方式**:GET
|
||
- **请求路径**:`/apex/test/successes`
|
||
- **权限要求**:`apex:test:query`
|
||
|
||
#### 请求参数
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| testResultId | String | 是 | 测试结果 ID |
|
||
| pageNum | Integer | 否 | 页码,默认 1 |
|
||
| pageSize | Integer | 否 | 每页大小,默认 10 |
|
||
|
||
#### 请求示例
|
||
```
|
||
GET /apex/test/successes?testResultId=12345&pageNum=1&pageSize=10
|
||
```
|
||
|
||
#### 响应参数
|
||
|
||
| 参数名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| code | Integer | 状态码(200 成功,其他失败) |
|
||
| msg | String | 提示信息 |
|
||
| data | Object | 分页结果 |
|
||
| data.total | Integer | 总记录数 |
|
||
| data.list | Array | 测试成功详情列表 |
|
||
| data.list[].id | String | 测试 ID |
|
||
| data.list[].className | String | 类名 |
|
||
| data.list[].methodName | String | 方法名 |
|
||
| data.list[].time | Double | 执行时间(毫秒) |
|
||
| data.list[].message | String | 消息 |
|
||
|
||
#### 成功响应示例
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"total": 95,
|
||
"list": [
|
||
{
|
||
"id": "01pxx000000xxxx",
|
||
"className": "AccountTriggerTest",
|
||
"methodName": "testInsert",
|
||
"time": 150.5,
|
||
"message": null
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 6. 查询测试失败详情
|
||
|
||
#### 接口说明
|
||
查询指定测试结果的失败详情。
|
||
|
||
- **请求方式**:GET
|
||
- **请求路径**:`/apex/test/failures`
|
||
- **权限要求**:`apex:test:query`
|
||
|
||
#### 请求参数
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| testResultId | String | 是 | 测试结果 ID |
|
||
| pageNum | Integer | 否 | 页码,默认 1 |
|
||
| pageSize | Integer | 否 | 每页大小,默认 10 |
|
||
|
||
#### 请求示例
|
||
```
|
||
GET /apex/test/failures?testResultId=12345&pageNum=1&pageSize=10
|
||
```
|
||
|
||
#### 响应参数
|
||
|
||
| 参数名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| code | Integer | 状态码(200 成功,其他失败) |
|
||
| msg | String | 提示信息 |
|
||
| data | Object | 分页结果 |
|
||
| data.total | Integer | 总记录数 |
|
||
| data.list | Array | 测试失败详情列表 |
|
||
| data.list[].id | String | 测试 ID |
|
||
| data.list[].className | String | 类名 |
|
||
| data.list[].methodName | String | 方法名 |
|
||
| data.list[].message | String | 失败消息 |
|
||
| data.list[].stackTrace | String | 堆栈跟踪 |
|
||
| data.list[].time | Double | 执行时间(毫秒) |
|
||
|
||
#### 成功响应示例
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"total": 5,
|
||
"list": [
|
||
{
|
||
"id": "01pxx000000xxxx",
|
||
"className": "ContactTriggerTest",
|
||
"methodName": "testUpdate",
|
||
"message": "Assertion failed",
|
||
"stackTrace": "Class.ContactTriggerTest.testUpdate: line 25, column 1",
|
||
"time": 200.0
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 7. 查询代码覆盖率
|
||
|
||
#### 接口说明
|
||
查询指定测试结果的代码覆盖率。
|
||
|
||
- **请求方式**:GET
|
||
- **请求路径**:`/apex/test/coverage/{testResultId}`
|
||
- **权限要求**:`apex:test:query`
|
||
|
||
#### 请求参数
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| testResultId | String | 是 | 测试结果 ID(路径参数) |
|
||
| pageNum | Integer | 否 | 页码,默认 1 |
|
||
| pageSize | Integer | 否 | 每页大小,默认 10 |
|
||
|
||
#### 请求示例
|
||
```
|
||
GET /apex/test/coverage/12345?pageNum=1&pageSize=10
|
||
```
|
||
|
||
#### 响应参数
|
||
|
||
| 参数名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| code | Integer | 状态码(200 成功,其他失败) |
|
||
| msg | String | 提示信息 |
|
||
| data | Object | 分页结果 |
|
||
| data.total | Integer | 总记录数 |
|
||
| data.list | Array | 代码覆盖率列表 |
|
||
| data.list[].id | String | 类/触发器 ID |
|
||
| data.list[].name | String | 类/触发器名称 |
|
||
| data.list[].type | String | 类型(Class/Trigger) |
|
||
| data.list[].namespace | String | 命名空间 |
|
||
| data.list[].numLocations | Integer | 总位置数 |
|
||
| data.list[].numLocationsNotCovered | Integer | 未覆盖的位置数 |
|
||
| data.list[].coveragePercent | Double | 覆盖率百分比 |
|
||
|
||
#### 成功响应示例
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"total": 50,
|
||
"list": [
|
||
{
|
||
"id": "01pxx000000xxxx",
|
||
"name": "AccountTrigger",
|
||
"type": "Trigger",
|
||
"namespace": "",
|
||
"numLocations": 100,
|
||
"numLocationsNotCovered": 15,
|
||
"coveragePercent": 85.0
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 8. 查询 Flow 覆盖率
|
||
|
||
#### 接口说明
|
||
查询指定测试结果的 Flow 覆盖率。
|
||
|
||
- **请求方式**:GET
|
||
- **请求路径**:`/apex/test/flow-coverage/{testResultId}`
|
||
- **权限要求**:`apex:test:query`
|
||
|
||
#### 请求参数
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| testResultId | String | 是 | 测试结果 ID(路径参数) |
|
||
| pageNum | Integer | 否 | 页码,默认 1 |
|
||
| pageSize | Integer | 否 | 每页大小,默认 10 |
|
||
|
||
#### 请求示例
|
||
```
|
||
GET /apex/test/flow-coverage/12345?pageNum=1&pageSize=10
|
||
```
|
||
|
||
#### 响应参数
|
||
|
||
| 参数名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| code | Integer | 状态码(200 成功,其他失败) |
|
||
| msg | String | 提示信息 |
|
||
| data | Object | 分页结果 |
|
||
| data.total | Integer | 总记录数 |
|
||
| data.list | Array | Flow 覆盖率列表 |
|
||
| data.list[].id | String | Flow ID |
|
||
| data.list[].name | String | Flow 名称 |
|
||
| data.list[].type | String | Flow 类型 |
|
||
| data.list[].namespace | String | 命名空间 |
|
||
| data.list[].numElements | Integer | 总元素数量 |
|
||
| data.list[].numElementsCovered | Integer | 覆盖的元素数量 |
|
||
| data.list[].coveragePercent | Double | 覆盖率百分比 |
|
||
|
||
#### 成功响应示例
|
||
```json
|
||
{
|
||
"code": 200,
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"total": 10,
|
||
"list": [
|
||
{
|
||
"id": "301xx000000xxxx",
|
||
"name": "Account_Automation",
|
||
"type": "AutoLaunchedFlow",
|
||
"namespace": "",
|
||
"numElements": 20,
|
||
"numElementsCovered": 18,
|
||
"coveragePercent": 90.0
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 错误码
|
||
|
||
### 统一错误码体系
|
||
|
||
| 错误码 | 说明 | 场景 |
|
||
|--------|------|------|
|
||
| APEX_TEST_001 | 参数校验失败 | 请求参数不合法 |
|
||
| APEX_TEST_002 | 连接失败 | 无法连接到 Salesforce |
|
||
| APEX_TEST_003 | 执行失败 | 测试执行过程中出错 |
|
||
| APEX_TEST_004 | 保存失败 | 保存测试结果到数据库失败 |
|
||
| APEX_TEST_005 | 查询失败 | 查询测试结果失败 |
|
||
| APEX_TEST_006 | 类不存在 | 指定的测试类不存在 |
|
||
| APEX_TEST_007 | 包不存在 | 指定的测试包不存在 |
|
||
| APEX_TEST_008 | 方法不存在 | 指定的测试方法不存在 |
|
||
| APEX_TEST_009 | 无权限 | 用户没有执行测试的权限 |
|
||
| APEX_TEST_010 | 会话过期 | Salesforce 会话已过期 |
|
||
| APEX_TEST_011 | 命名空间错误 | 指定的命名空间不存在 |
|
||
| APEX_TEST_012 | 测试运行超时 | 测试运行超时 |
|
||
| APEX_TEST_013 | 覆盖率计算失败 | 代码覆盖率计算失败 |
|
||
| APEX_TEST_014 | Flow覆盖率计算失败 | Flow 覆盖率计算失败 |
|
||
| APEX_TEST_015 | 批量插入失败 | 批量插入测试结果失败 |
|
||
| APEX_TEST_016 | 事务回滚 | 数据库事务回滚 |
|
||
| APEX_TEST_017 | 并发冲突 | 多线程并发执行冲突 |
|
||
| APEX_TEST_018 | 数据转换失败 | Salesforce 数据转换失败 |
|
||
| APEX_TEST_019 | 配置错误 | 系统配置错误 |
|
||
| APEX_TEST_020 | 未知错误 | 其他未知错误 |
|
||
|
||
### HTTP 状态码
|
||
|
||
| 状态码 | 说明 |
|
||
|--------|------|
|
||
| 200 | 请求成功 |
|
||
| 400 | 请求参数错误 |
|
||
| 401 | 未授权 |
|
||
| 403 | 禁止访问 |
|
||
| 404 | 资源不存在 |
|
||
| 500 | 服务器内部错误 |
|
||
|
||
---
|
||
|
||
## 相关文档
|
||
- [需求文档](../requirements/sub/2026-01-28-002-03-测试执行.md)
|
||
- [设计文档(重构版)](../design/2026-02-04-002-03-测试执行-设计.md)
|
||
- [决策记录(重构版)](../decisions/2026-02-04-002-03-ADR-测试执行技术选型.md)
|
||
- [变更日志(重构版)](../changelog/2026-02-04-002-03-changelog.md)
|
||
- [复盘文档(重构版)](../retros/2026-02-04-002-03-retro.md)
|
||
- [会话记录(重构版)](../sessions/2026-02-04-002-03-session.md)
|