httprunner/hrp
lilong.129 804e69037a change: GenNameWithTimestamp 2023-04-17 22:45:58 +08:00
..
cmd change: GenNameWithTimestamp 2023-04-17 22:45:58 +08:00
internal change: GenNameWithTimestamp 2023-04-17 22:45:58 +08:00
pkg change: GenNameWithTimestamp 2023-04-17 22:45:58 +08:00
tests optimize websocket step 2022-07-19 11:21:33 +08:00
README.md refactor: CaseRunner and SessionRunner 2022-10-19 10:56:02 +08:00
boomer.go change: add exit code 2022-10-21 21:39:18 +08:00
boomer_test.go feat: support multi-machine collaborative distributed load testing #1193 2022-07-25 21:14:58 +08:00
build.go refactor: get current dir 2022-12-15 23:42:39 +08:00
build_test.go fix: check if debugtalk.go contains main() function 2022-06-14 23:17:34 +08:00
config.go refactor: move uixt from hrp internal to pkg 2022-10-10 22:12:36 +08:00
convert.go refactor: convert postman case 2022-12-23 12:28:29 +08:00
loader.go release v4.3.0 2022-10-21 22:22:00 +08:00
parameters.go feat: support multi-machine collaborative distributed load testing #1193 2022-07-25 21:14:58 +08:00
parameters_test.go fix: modify the format of data-driven parameters setting 2022-05-20 14:53:23 +08:00
parser.go change: add exit code 2022-10-21 21:39:18 +08:00
parser_test.go refactor: update summary in controller 2022-10-18 16:07:21 +08:00
plugin.go refactor: get current dir 2022-12-15 23:42:39 +08:00
plugin_test.go refactor: relocate build plugin 2022-05-29 12:32:39 +08:00
response.go refactor: move uixt from hrp internal to pkg 2022-10-10 22:12:36 +08:00
response_test.go change: update unittest for regex check 2022-06-22 17:17:37 +08:00
runner.go fix: stop logcat only when enabled 2023-02-13 23:34:09 +08:00
runner_test.go change: add exit code 2022-10-21 21:39:18 +08:00
server.go refactor: move boomer from hrp internal to pkg 2022-10-11 11:17:58 +08:00
step.go Merge pull request #1531 from httprunner/wcl 2022-12-14 14:54:58 +08:00
step_api.go refactor: update summary in controller 2022-10-18 16:07:21 +08:00
step_mobile_ui.go change: GenNameWithTimestamp 2023-04-17 22:45:58 +08:00
step_mobile_ui_test.go change: remove unused UI APIs 2022-12-26 00:15:43 +08:00
step_rendezvous.go refactor: CaseRunner and SessionRunner 2022-10-19 10:56:02 +08:00
step_rendezvous_test.go feat: support HTTP/2.0 2022-04-07 21:40:37 +08:00
step_request.go fix: ensure HTTP request method in uppper case 2022-12-23 16:46:39 +08:00
step_request_test.go refactor: CaseRunner and SessionRunner 2022-10-19 10:56:02 +08:00
step_testcase.go fix: logs 2022-10-23 16:41:23 +08:00
step_thinktime.go refactor: CaseRunner and SessionRunner 2022-10-19 10:56:02 +08:00
step_transaction.go docs: add docs for IStep 2022-03-30 16:56:31 +08:00
step_websocket.go refactor: CaseRunner and SessionRunner 2022-10-19 10:56:02 +08:00
summary.go refactor: results dir 2022-12-16 00:24:35 +08:00
summary_test.go change: convert StepResult Attachments to interface, for screenshots saving 2022-09-01 00:44:39 +08:00
testcase.go change: add exit code 2022-10-21 21:39:18 +08:00
testcase_test.go simplify jmespath compatibility conversion 2022-06-27 18:08:23 +08:00

README.md

代码阅读指南golang 部分)

核心数据结构

HttpRunner 以 TestCase 为核心,将任意测试场景抽象为有序步骤的集合。

type TestCase struct {
	Config    *TConfig
	TestSteps []IStep
}

其中,测试步骤 IStep 采用了 go interface 的设计理念,支持进行任意拓展;步骤内容统一在 Run 方法中进行实现。

type IStep interface {
	Name() string
	Type() StepType
	Struct() *TStep
	Run(*SessionRunner) (*StepResult, error)
}

我们只需遵循 IStep 的接口定义,即可实现各种类型的测试步骤类型。当前 hrp 已支持的步骤类型包括:

  • request:发起单次 HTTP 请求
  • api:引用执行其它 API 文件
  • testcase:引用执行其它测试用例文件
  • thinktime:思考时间,按照配置的逻辑进行等待
  • transaction:事务机制,用于压测
  • rendezvous:集合点机制,用于压测

基于该机制,我们可以扩展支持新的协议类型,例如 HTTP2/WebSocket/RPC 等;同时也可以支持新的测试类型,例如 UI 自动化。甚至我们还可以在一个测试用例中混合调用多种不同的 Step 类型,例如实现 HTTP/RPC/UI 混合场景。

运行主流程

整体控制器 HRPRunner

执行接口测试时,会初始化一个 HRPRunner,用于控制测试的执行策略。

type HRPRunner struct {
	t             *testing.T
	failfast      bool
	requestsLogOn bool
	pluginLogOn   bool
	saveTests     bool
	genHTMLReport bool
	client        *http.Client
}

func (r *HRPRunner) Run(testcases ...ITestCase) error
func (r *HRPRunner) NewCaseRunner(testcase *TestCase) (*CaseRunner, error)

重点关注两个方法:

  • Run测试执行的主入口支持运行一个或多个测试用例
  • NewCaseRunner针对给定的测试用例初始化一个 CaseRunner

用例执行器 CaseRunner

针对每个测试用例,采用 CaseRunner 存储其公共信息,包括 plugin/parser

type CaseRunner struct {
	testCase  *TestCase
	hrpRunner *HRPRunner
	parser    *Parser

	parsedConfig       *TConfig
	parametersIterator *ParametersIterator
	rootDir            string // project root dir
}

func (r *CaseRunner) NewSession() *SessionRunner {

重点关注一个方法:

  • NewSession测试用例的每一次执行对应一个 SessionRunner

SessionRunner

测试用例的具体执行都由 SessionRunner 完成,每个 session 实例中除了包含测试用例自身内容外,还会包含测试过程的 session 数据和最终测试结果 summary。

type SessionRunner struct {
	caseRunner       *CaseRunner
	sessionVariables map[string]interface{}
	transactions      map[string]map[transactionType]time.Time
	startTime         time.Time                  // record start time of the testcase
	summary           *TestCaseSummary           // record test case summary
}

func (r *SessionRunner) Start(givenVars map[string]interface{}) error

重点关注一个方法:

  • Start启动执行用例依次执行所有测试步骤
func (r *SessionRunner) Start(givenVars map[string]interface{}) error {
	...
	r.resetSession()

	r.InitWithParameters(givenVars)

	// run step in sequential order
	for _, step := range r.testCase.TestSteps {
		// parse step

		// run step
		stepResult, err := step.Run(r)

		// update summary
		r.summary.Records = append(r.summary.Records, stepResult)

		// update extracted variables
		for k, v := range stepResult.ExportVars {
			r.sessionVariables[k] = v
		}

		// check if failfast
		if err != nil && r.caseRunner.hrpRunner.failfast {
			return errors.Wrap(err, "abort running due to failfast setting")
		}
	}
	...
}

在主流程中SessionRunner 并不需要关注 step 的具体类型,统一都是调用 step.Run(r),具体实现逻辑都在对应 step 的 Run(*SessionRunner) 方法中。