cheetah测试平台 并发运行测试用例
「原创声明:保留所有权利,禁止转载」
测试平台现有的运行方案
- api: 运行时通过和前置条件组成一个测试用例运行
- 测试套件:运行时通过和前置条件组成一个测试用例运行;每个测试套件数据可以互通,根据实际情况配置
- 测试用例:用例下引用测试套件,并与前置套件组成一个测试用例运行;每个测试用例数据独立,不依赖与其他用例
- 定时任务:定时任务下引用多个测试用例
从上面的方案看,测试套件没办法完全做到独立运行,每个测试用例都是相对独立的,所以可以从定时任务执行时增加对应的逻辑
实现并发运行
思路
- 实现多线程执行需要用到
goroutine
,好在 go 协程实现非常简单,只要在函数前面增加go
就可以了,如:go func()
- 加入线程阻塞,保证测试报告不丢失
- 控制线程数,防止线程过多导致的资源占用过高
- 单例运行 plugin,否则每个用例会运行一个 plugin,导致内存占用过高,可参考性能问题排查及解决
代码
修改 hrp.Run 函数
func (r *HRPRunner) Run(testcases ...ITestCase) (interfacecase.ApiReport, error) {
// 省略部分代码
var runErr error
// run testcase one by one
var wg sync.WaitGroup
// 通过channel的缓冲区设置协程数,最小2,最大为cpu线程数-2
cpu := 2
if runtime.NumCPU() >= 4 {
cpu = runtime.NumCPU() - 2
}
intChan := make(chan int, cpu)
defer close(intChan)
// 添加计数器为用例个数
wg.Add(len(testcases))
for _, testCase := range testCases {
// each testcase has its own case runner
go func(testcase *TestCase) {
defer wg.Done()
intChan <- 1
defer func() {
<-intChan
}()
caseRunner, err := r.NewCaseRunner(testcase)
if err != nil {
log.Error().Err(err).Msg("[Run] init case runner failed")
return
}
// release UI driver session
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()
caseSummary.CaseID = testcase.ID
//for k, _ := range caseSummary.Records {
// caseSummary.Records[k].ValidatorsNumber = testcase.TestSteps[k].Struct().ValidatorsNumber
//}
//把header、Extract导出到上一级配置(caseRunner.testCase.Config)中
//caseRunner.testCase.Config
caseSummary.Name = testcase.Name
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
}
}
}
}(testCase)
}
// 阻塞,等待运行结束
wg.Wait()
s.Time.Duration = time.Since(s.Time.StartAt).Seconds()
// save summary
if r.saveTests {
err := s.genSummary()
if err != nil {
return interfacecase.ApiReport{}, err
}
}
// 省略部分代码
}
效果
按照 cpu 线程数 (i7 10700 8 核 16 线程)-2 进行执行,比单个运行时间节省了接近 90%,如果是全量回归,可以节省比较多的时间
往期文档
- cheetah 自动化测试平台开源项目
- 了解如何接入 httprunner
- 测试平台接入 HttpRunner V4(一)基本功能接入
- 测试平台接入 HttpRunner V4(二)使用 config 实现用例之间的参数传递
- 测试平台接入 HttpRunner V4(三)详细功能介绍
TesterHome 为用户提供「保留所有权利,禁止转载」的选项。
除非获得原作者的单独授权,任何第三方不得转载标注了「原创声明:保留所有权利,禁止转载」的内容,否则均视为侵权。
具体请参见TesterHome 知识产权保护协议。
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!