demo 账号:admin,密码:123456
我们通过调用HRPRunner.Run
来执行测试用例。在执行之前,让我们先了解一下HRPRunner
所包含的内容,因为这些内容将用于后续的运行配置。大多数参数在运行前需要进行确认。
HRPRunner
是一个执行器,它封装了用例的运行过程。在运行测试用例之前,我们需要确认并设置许多参数,这些参数将影响测试的执行。这些参数可以包括用例的路径、配置、运行模式等。通过在HRPRunner
中设置这些参数,我们可以在运行过程中按照预期配置和执行测试用例,从而得到正确的结果和报告。
理解HRPRunner
的内容和参数设置,是保证测试用例按照预期执行的关键。因此,在执行测试用例之前,我们需要仔细了解这些参数,并进行必要的设置,以确保测试的准确性和可靠性。
type HRPRunner struct {
t *testing.T // testing.T的引用,用于报告测试失败和管理测试状态
failfast bool // 是否在第一个测试失败后立即停止测试的标志。如果设置为true,则在第一个失败后测试停止,否则会继续执行所有测试。
httpStatOn bool // 是否启用HTTP统计跟踪的标志。如果设置为true,则在测试执行期间收集并显示与HTTP请求相关的统计信息。
requestsLogOn bool // 是否启用HTTP请求日志的标志。如果设置为true,则在测试执行期间记录每个HTTP请求的详细信息。
pluginLogOn bool // 是否启用插件日志的标志。如果设置为true,则在测试执行期间记录与插件相关的信息。
venv string // 虚拟环境路径的字符串。用于指定测试将在其中执行的虚拟环境的路径。
saveTests bool // 是否保存测试结果的标志。如果设置为true,则将保存测试结果。
genHTMLReport bool // 是否生成测试执行的HTML报告的标志。如果设置为true,则会生成总结测试结果的HTML报告。
httpClient *http.Client // 指向HTTP客户端实例的指针。用于在测试执行期间进行HTTP请求。
http2Client *http.Client // 指向HTTP/2客户端实例的指针。用于在测试执行期间进行HTTP/2请求。
wsDialer *websocket.Dialer // 指向WebSocket拨号器实例的指针。用于在测试执行期间建立WebSocket连接。
uiClients map[string]*uixt.DriverExt // UI客户端的映射。用于管理具有唯一键作为标识符的UI测试驱动程序。
}
这部分内容实际上也属于配置,不同之处在于这里配置的是整个测试的运行环境。相比之下,config
更侧重于每个测试用例的个别配置。由于我们可以同时运行多个测试用例,因此将整体的配置分为运行配置和用例配置两个部分。
在实际运行时,我们首先会创建一个HRPRunner
对象,然后通过调用其Run
方法来开始执行测试用例。下面我们将重点介绍测试用例的运行过程。这个过程中,HRPRunner
会根据之前设置的运行配置和各个测试用例的个别配置,按照既定方式执行测试,并生成相应的结果报告。这个过程是整个自动化测试框架的核心,它确保了测试用例能够在正确的环境中运行,并输出准确的结果,为测试提供了稳定可靠的支持。
// Run starts to execute one or multiple testcases.
// 运行开始执行一个或多个测试用例。
func (r *HRPRunner) Run(testcases ...ITestCase) error {
// 输出HRP版本号
log.Info().Str("hrp_version", version.VERSION).Msg("start running")
// 初始化事件跟踪对象,用于统计执行过程中的事件
event := sdk.EventTracking{
Category: "RunAPITests",
Action: "hrp run",
}
go sdk.SendEvent(event)
defer sdk.SendEvent(event.StartTiming("execution"))
// 记录执行数据到总结对象中
s := newOutSummary()
// 加载所有测试用例
testCases, err := LoadTestCases(testcases...)
if err != nil {
log.Error().Err(err).Msg("failed to load testcases")
return err
}
// 退出所有函数插件
defer func() {
pluginMap.Range(func(key, value interface{}) bool {
if plugin, ok := value.(funplugin.IPlugin); ok {
plugin.Quit()
}
return true
})
}()
var runErr error
// 遍历所有用例
for _, testcase := range testCases {
// 每个测试用例都有自己的用例运行器,把用例转换成可迭代的用例
caseRunner, err := r.NewCaseRunner(testcase)
if err != nil {
log.Error().Err(err).Msg("[Run] init case runner failed")
return err
}
// 释放UI驱动程序的会话
defer func() {
for _, client := range r.uiClients {
client.Driver.DeleteSession()
}
}()
// 使用参数迭代器执行用例多次,每次执行有不同的参数
for it := caseRunner.parametersIterator; it.HasNext(); {
// 每次运行都有自己的会话运行器
sessionRunner := caseRunner.NewSession()
err1 := sessionRunner.Start(it.Next())
if err1 != nil {
log.Error().Err(err1).Msg("[Run] run testcase failed")
runErr = err1
}
// 获取用例的执行结果
caseSummary, err2 := sessionRunner.GetSummary()
s.appendCaseSummary(caseSummary)
if err2 != nil {
log.Error().Err(err2).Msg("[Run] get summary failed")
if err1 != nil {
runErr = errors.Wrap(err1, err2.Error())
} else {
runErr = err2
}
}
// 如果发生错误且设置了failfast标志,则终止运行
// 实际操作一般都会执行所有用例后,最后获取用例执行情况
if runErr != nil && r.failfast {
break
}
}
}
// 计算执行时间
s.Time.Duration = time.Since(s.Time.StartAt).Seconds()
// 保存测试报告
if r.saveTests {
err := s.genSummary()
if err != nil {
return err
}
}
// 生成HTML报告
if r.genHTMLReport {
err := s.genHTMLReport()
if err != nil {
return err
}
}
return runErr
}
整个运行过程可以分为以下五个主要部分:
这五个部分共同构成了整个测试框架的执行流程,确保测试用例能够在正确的环境中执行,并为用户提供准确、详尽的测试报告。