Files
httprunner/docs/dev-instruct.md
2025-08-17 04:36:13 +00:00

449 lines
15 KiB
Markdown
Raw 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.
# 代码阅读指南
## 核心数据结构
HttpRunner 以 `TestCase` 为核心,将任意测试场景抽象为有序步骤的集合。
```go
type TestCase struct {
Config IConfig `json:"config" yaml:"config"`
TestSteps []IStep `json:"teststeps" yaml:"teststeps"`
}
type IConfig interface {
Get() *TConfig
}
```
其中,测试步骤 `IStep` 采用了 `go interface` 的设计理念,支持进行任意拓展;步骤内容统一在 `Run` 方法中进行实现。
```go
type IStep interface {
Name() string
Type() StepType
Config() *StepConfig
Run(*SessionRunner) (*StepResult, error)
}
```
我们只需遵循 `IStep` 的接口定义,即可实现各种类型的测试步骤类型。当前 HttpRunner v5 已支持的步骤类型包括:
**协议测试步骤**
- [request](step_request.go):发起单次 HTTP/HTTP2 请求
- [api](step_api.go):引用执行其它 API 文件
- [testcase](step_testcase.go):引用执行其它测试用例文件
- [websocket](step_websocket.go)WebSocket 通信
**性能测试步骤**
- [transaction](step_transaction.go):事务机制,用于压测
- [rendezvous](step_rendezvous.go):集合点机制,用于压测
- [thinktime](step_thinktime.go):思考时间,按照配置的逻辑进行等待
**UI 自动化步骤**
- [android](step_ui.go)Android UI 自动化(支持 ADB 和 UIAutomator2
- [ios](step_ui.go)iOS UI 自动化(基于 WebDriverAgent
- [harmony](step_ui.go)Harmony UI 自动化(基于 HDC
- [browser](step_ui.go):浏览器 UI 自动化(支持 Chrome、Firefox、Safari、Edge
**系统集成步骤**
- [shell](step_shell.go):执行 shell 命令
- [function](step_function.go):自定义函数调用
基于该机制,我们可以扩展支持新的协议类型,例如 HTTP2/WebSocket/RPC 等;同时也可以支持新的测试类型,例如 UI 自动化。甚至我们还可以在一个测试用例中混合调用多种不同的 Step 类型,例如实现 HTTP/RPC/UI 混合场景。
## 运行主流程
### 整体控制器 HRPRunner
执行测试时,会初始化一个 `HRPRunner`,用于控制测试的执行策略。
```go
type HRPRunner struct {
t *testing.T
failfast bool
httpStatOn bool
requestsLogOn bool
pluginLogOn bool
venv string
saveTests bool
genHTMLReport bool
httpClient *http.Client
http2Client *http.Client
wsDialer *websocket.Dialer
caseTimeoutTimer *time.Timer // case timeout timer
interruptSignal chan os.Signal // interrupt signal channel
}
func (r *HRPRunner) Run(testcases ...ITestCase) error
func NewCaseRunner(testcase TestCase, hrpRunner *HRPRunner) (*CaseRunner, error)
```
重点关注的方法:
- Run测试执行的主入口支持运行一个或多个测试用例
- NewCaseRunner针对给定的测试用例初始化一个 CaseRunner
HRPRunner 支持多种配置选项:
- SetFailfast配置是否在步骤失败时立即停止
- SetRequestsLogOn开启请求响应详细日志
- SetHTTPStatOn开启 HTTP 延迟统计
- SetPluginLogOn开启插件日志
- SetProxyUrl配置代理 URL用于抓包调试
- SetRequestTimeout配置全局请求超时
- SetCaseTimeout配置测试用例超时
- GenHTMLReport生成 HTML 测试报告
### 用例执行器 CaseRunner
针对每个测试用例,采用 CaseRunner 存储其公共信息,包括 plugin/parser
```go
type CaseRunner struct {
TestCase // each testcase init its own CaseRunner
hrpRunner *HRPRunner // all case runners share one HRPRunner
parser *Parser // each CaseRunner init its own Parser
parametersIterator *ParametersIterator
}
func (r *CaseRunner) NewSession() *SessionRunner
```
重点关注一个方法:
- NewSession测试用例的每一次执行对应一个 SessionRunner
### SessionRunner
测试用例的具体执行都由 `SessionRunner` 完成,每个 session 实例中除了包含测试用例自身内容外,还会包含测试过程的 session 数据和最终测试结果 summary。
```go
type SessionRunner struct {
caseRunner *CaseRunner // all session runners share one CaseRunner
sessionVariables map[string]interface{} // testcase execution session variables
summary *TestCaseSummary // record test case summary
// transactions stores transaction timing info.
// key is transaction name, value is map of transaction type and time, e.g. start time and end time.
transactions map[string]map[TransactionType]time.Time
// websocket session
ws *wsSession
}
func (r *SessionRunner) Start(givenVars map[string]interface{}) (summary *TestCaseSummary, err error)
func (r *SessionRunner) RunStep(step IStep) (stepResult *StepResult, err error)
func (r *SessionRunner) ParseStep(step IStep) error
```
重点关注的方法:
- Start启动执行用例依次执行所有测试步骤
- RunStep执行单个测试步骤支持循环执行
- ParseStep解析步骤配置包括变量替换和验证器解析
```go
func (r *SessionRunner) Start(givenVars map[string]interface{}) (summary *TestCaseSummary, err error) {
// report GA event
sdk.SendGA4Event("hrp_session_runner_start", nil)
config := r.caseRunner.TestCase.Config.Get()
log.Info().Str("testcase", config.Name).Msg("run testcase start")
// update config variables with given variables
r.InitWithParameters(givenVars)
defer func() {
// release session resources
r.ReleaseResources()
summary = r.summary
summary.Name = config.Name
summary.Time.Duration = time.Since(summary.Time.StartAt).Seconds()
// ... handle export variables and logs
}()
// run step in sequential order
for _, step := range r.caseRunner.TestSteps {
select {
case <-r.caseRunner.hrpRunner.caseTimeoutTimer.C:
log.Warn().Msg("timeout in session runner")
return summary, errors.Wrap(code.TimeoutError, "session runner timeout")
case <-r.caseRunner.hrpRunner.interruptSignal:
log.Warn().Msg("interrupted in session runner")
return summary, errors.Wrap(code.InterruptError, "session runner interrupted")
default:
_, err := r.RunStep(step)
if err == nil {
continue
}
// interrupted or timeout, abort running
if errors.Is(err, code.InterruptError) || errors.Is(err, code.TimeoutError) {
return summary, err
}
// check if failfast
if r.caseRunner.hrpRunner.failfast {
return summary, errors.Wrap(err, "abort running due to failfast setting")
}
}
}
log.Info().Str("testcase", config.Name).Msg("run testcase end")
return summary, nil
}
```
在主流程中SessionRunner 并不需要关注 step 的具体类型,统一都是调用 `r.RunStep(step)`,具体实现逻辑都在对应 step 的 `Run(*SessionRunner)` 方法中。
## 新增特性
### 1. 超时和中断处理
v5 版本增加了完善的超时和中断处理机制:
- 支持测试用例级别的超时控制
- 支持优雅的中断处理SIGTERM, SIGINT
- 在执行过程中实时检查超时和中断信号
### 2. 多平台 UI 自动化
统一的 UI 自动化接口,支持多个平台:
- **Android**:基于 ADB 和 UIAutomator2
- **iOS**:基于 WebDriverAgent (WDA)
- **Harmony**:基于 HDC (Harmony Device Connector)
- **Browser**:基于 WebDriver 协议
### 3. AI 集成
集成了大模型能力:
- 支持 AI 驱动的 UI 操作
- 通过 MCP (Model Context Protocol) 与大模型通信
- 支持自然语言描述的测试步骤
### 4. 增强的步骤配置
步骤配置支持更多选项:
```go
type StepConfig struct {
StepName string `json:"name" yaml:"name"` // required
Variables map[string]interface{} `json:"variables,omitempty" yaml:"variables,omitempty"`
SetupHooks []string `json:"setup_hooks,omitempty" yaml:"setup_hooks,omitempty"`
TeardownHooks []string `json:"teardown_hooks,omitempty" yaml:"teardown_hooks,omitempty"`
Extract map[string]string `json:"extract,omitempty" yaml:"extract,omitempty"`
Validators []interface{} `json:"validate,omitempty" yaml:"validate,omitempty"`
StepExport []string `json:"export,omitempty" yaml:"export,omitempty"`
Loops *types.IntOrString `json:"loops,omitempty" yaml:"loops,omitempty"`
AutoPopupHandler bool `json:"auto_popup_handler,omitempty" yaml:"auto_popup_handler,omitempty"` // enable auto popup handler for this step
}
```
### 5. 协议支持扩展
除了 HTTP/HTTPS还支持
- HTTP/2 协议
- WebSocket 通信
- 自定义函数调用
### 6. 资源管理
增强的资源管理机制:
- 自动释放会话资源
- UI 驱动器缓存管理
- 日志收集和聚合
## UI 自动化步骤示例
### StepMobile 结构
UI 自动化步骤统一使用 `StepMobile` 结构:
```go
type StepMobile struct {
StepConfig
Mobile *MobileUI `json:"mobile,omitempty" yaml:"mobile,omitempty"`
Android *MobileUI `json:"android,omitempty" yaml:"android,omitempty"`
Harmony *MobileUI `json:"harmony,omitempty" yaml:"harmony,omitempty"`
IOS *MobileUI `json:"ios,omitempty" yaml:"ios,omitempty"`
Browser *MobileUI `json:"browser,omitempty" yaml:"browser,omitempty"`
}
```
### 常用 UI 操作方法
```go
// 基础操作
func (s *StepMobile) TapXY(x, y float64, opts ...option.ActionOption) *StepMobile
func (s *StepMobile) TapByOCR(ocrText string, opts ...option.ActionOption) *StepMobile
func (s *StepMobile) TapByCV(imagePath string, opts ...option.ActionOption) *StepMobile
func (s *StepMobile) AIAction(prompt string, opts ...option.ActionOption) *StepMobile
// 应用管理
func (s *StepMobile) AppLaunch(bundleId string) *StepMobile
func (s *StepMobile) AppTerminate(bundleId string) *StepMobile
func (s *StepMobile) InstallApp(path string) *StepMobile
// 滑动操作
func (s *StepMobile) Swipe(sx, sy, ex, ey float64, opts ...option.ActionOption) *StepMobile
func (s *StepMobile) SwipeUp(opts ...option.ActionOption) *StepMobile
func (s *StepMobile) SwipeDown(opts ...option.ActionOption) *StepMobile
// 输入操作
func (s *StepMobile) Input(text string, opts ...option.ActionOption) *StepMobile
// 等待操作
func (s *StepMobile) Sleep(nSeconds float64, startTime ...time.Time) *StepMobile
func (s *StepMobile) SleepRandom(params ...float64) *StepMobile
// 验证操作
func (s *StepMobile) Validate() *StepMobileUIValidation
```
### UI 验证方法
```go
// OCR 文本验证
func (s *StepMobileUIValidation) AssertOCRExists(expectedText string, msg ...string) *StepMobileUIValidation
func (s *StepMobileUIValidation) AssertOCRNotExists(expectedText string, msg ...string) *StepMobileUIValidation
// 图像验证
func (s *StepMobileUIValidation) AssertImageExists(expectedImagePath string, msg ...string) *StepMobileUIValidation
func (s *StepMobileUIValidation) AssertImageNotExists(expectedImagePath string, msg ...string) *StepMobileUIValidation
// AI 验证
func (s *StepMobileUIValidation) AssertAI(prompt string, msg ...string) *StepMobileUIValidation
// 应用状态验证
func (s *StepMobileUIValidation) AssertAppInForeground(packageName string, msg ...string) *StepMobileUIValidation
func (s *StepMobileUIValidation) AssertAppNotInForeground(packageName string, msg ...string) *StepMobileUIValidation
```
## 开发建议
### 1. 添加新的步骤类型
要添加新的步骤类型,需要:
1.`step.go` 中定义新的 `StepType` 常量
2. 创建实现 `IStep` 接口的结构体
3.`testcase.go``loadISteps` 方法中添加对应的处理逻辑
### 2. 扩展 UI 平台支持
要支持新的 UI 平台:
1.`uixt/` 目录下实现对应的驱动器
2.`StepMobile` 中添加新的平台字段
3.`obj()` 方法中添加对应的处理逻辑
### 3. AI 集成
### 3. AI 集成
HttpRunner v5 引入了完整的 AI 集成功能,支持多种大语言模型进行智能化测试自动化:
**支持的 AI 服务**
- **OpenAI GPT-4O**: 通过 OpenAI API 接口
- **豆包模型**: 豆包思维视觉专业版、豆包 UI-TARS 等
- **DeepSeek 模型**: DeepSeek V3 等
- **自定义模型**: 支持兼容 OpenAI API 的其他模型
**AI 功能模块**
- **规划器 (Planner)**: 基于屏幕截图和用户意图,生成操作计划
- **断言器 (Asserter)**: 智能验证界面状态和内容
- **查询器 (Querier)**: 处理自然语言查询,提取界面信息
**配置方式**
```go
// 环境变量配置
OPENAI_GPT_4O_API_KEY=your_api_key
DOUBAO_1_5_THINKING_VISION_PRO_250428_API_KEY=your_doubao_key
// 代码配置
aiOptions := []option.AIServiceOption{
option.WithAIService(option.OPENAI_GPT_4O),
option.WithLLMServiceConfig(&option.LLMServiceConfig{
PlannerModel: option.OPENAI_GPT_4O,
AsserterModel: option.DOUBAO_1_5_THINKING_VISION_PRO_250428,
QuerierModel: option.DEEPSEEK_V3,
}),
}
```
### 4. MCP (Model Context Protocol) 支持
v5 版本引入了 MCP 主机功能,支持与 AI 模型进行标准化交互:
**主要功能**
- MCP 服务器连接管理
- 工具注册和调用
- 标准化的 AI 模型交互协议
**使用方式**
```bash
# 启动 MCP 主机
hrp mcp-server --config mcp-config.yaml
# 在测试中使用 MCP
hrp run test.yaml --mcp-config mcp-config.yaml
```
### 5. 调试技巧
- 启用详细日志:`--log-level debug`
- 使用屏幕截图功能进行 UI 调试
- 利用 `--dry-run` 模式验证测试用例
- 通过 MCP 配置调试 AI 集成问题
**支持的 AI 服务**
- **OpenAI GPT-4O**: 通过 OpenAI API 接口
- **豆包模型**: 豆包思维视觉专业版、豆包 UI-TARS 等
- **DeepSeek 模型**: DeepSeek V3 等
- **自定义模型**: 支持兼容 OpenAI API 的其他模型
**AI 功能模块**
- **规划器 (Planner)**: 基于屏幕截图和用户意图,生成操作计划
- **断言器 (Asserter)**: 智能验证界面状态和内容
- **查询器 (Querier)**: 处理自然语言查询,提取界面信息
**配置方式**
```go
// 环境变量配置
OPENAI_GPT_4O_API_KEY=your_api_key
DOUBAO_1_5_THINKING_VISION_PRO_250428_API_KEY=your_doubao_key
// 代码配置
aiOptions := []option.AIServiceOption{
option.WithAIService(option.OPENAI_GPT_4O),
option.WithLLMServiceConfig(&option.LLMServiceConfig{
PlannerModel: option.OPENAI_GPT_4O,
AsserterModel: option.DOUBAO_1_5_THINKING_VISION_PRO_250428,
QuerierModel: option.DEEPSEEK_V3,
}),
}
```
### 4. MCP (Model Context Protocol) 支持
v5 版本引入了 MCP 主机功能,支持与 AI 模型进行标准化交互:
**主要功能**
- MCP 服务器连接管理
- 工具注册和调用
- 标准化的 AI 模型交互协议
**使用方式**
```bash
# 启动 MCP 主机
hrp mcp-server --config mcp-config.yaml
# 在测试中使用 MCP
hrp run test.yaml --mcp-config mcp-config.yaml
```
### 5. 增强的 UI 自动化
- 使用 `SetRequestsLogOn()` 开启详细的请求日志
- 使用 `SetPluginLogOn()` 开启插件日志
- 使用 `SetProxyUrl()` 配置代理进行抓包分析
- 查看生成的 HTML 报告了解执行详情