From a55f523fd71b25ff8dbb88c4dea05ddac5cadaa6 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Wed, 8 Dec 2021 13:07:39 +0800 Subject: [PATCH] refactor: NewConfig --- boomer.go | 7 +++--- convert.go | 4 ++-- docs/cmd/hrp.md | 4 ++-- docs/cmd/hrp_boom.md | 2 +- docs/cmd/hrp_har2case.md | 2 +- docs/cmd/hrp_run.md | 2 +- har2case/core.go | 2 +- models.go | 8 ++++++- runner.go | 30 +++++++++++++----------- step.go | 50 ++++++++++++++++++++++++++-------------- 10 files changed, 67 insertions(+), 44 deletions(-) diff --git a/boomer.go b/boomer.go index 4b7da8a3..cfcd096e 100644 --- a/boomer.go +++ b/boomer.go @@ -57,15 +57,14 @@ func (b *hrpBoomer) Quit() { func (b *hrpBoomer) convertBoomerTask(testcase *TestCase) *boomer.Task { return &boomer.Task{ - Name: testcase.Config.Name, - Weight: testcase.Config.Weight, + Name: testcase.Config.ToStruct().Name, + Weight: testcase.Config.ToStruct().Weight, Fn: func() { runner := NewRunner(nil).SetDebug(b.debug) - config := testcase.Config for _, step := range testcase.TestSteps { var err error start := time.Now() - stepData, err := runner.runStep(step, config) + stepData, err := runner.runStep(step, testcase.Config) elapsed := time.Since(start).Nanoseconds() / int64(time.Millisecond) if err == nil { b.RecordSuccess(step.Type(), step.Name(), elapsed, stepData.responseLength) diff --git a/convert.go b/convert.go index 22ca17ec..94eb0b6d 100644 --- a/convert.go +++ b/convert.go @@ -12,7 +12,7 @@ import ( func (tc *TestCase) ToTCase() (*TCase, error) { tCase := TCase{ - Config: tc.Config, + Config: tc.Config.ToStruct(), } for _, step := range tc.TestSteps { tCase.TestSteps = append(tCase.TestSteps, step.ToStruct()) @@ -105,7 +105,7 @@ func loadFromYAML(path string) (*TCase, error) { func (tc *TCase) ToTestCase() (*TestCase, error) { testCase := &TestCase{ - Config: tc.Config, + Config: &Config{cfg: tc.Config}, } for _, step := range tc.TestSteps { if step.Request != nil { diff --git a/docs/cmd/hrp.md b/docs/cmd/hrp.md index 21663901..c404fa12 100644 --- a/docs/cmd/hrp.md +++ b/docs/cmd/hrp.md @@ -4,7 +4,7 @@ One-stop solution for HTTP(S) testing. ### Synopsis -hrp (HttpRunner+) is the next generation for HttpRunner. Enjoy! ✨ 🚀 ✨ +hrp (HttpRunner+) is the one-stop solution for HTTP(S) testing. Enjoy! ✨ 🚀 ✨ License: Apache-2.0 Github: https://github.com/httprunner/hrp @@ -22,4 +22,4 @@ Copyright 2021 debugtalk * [hrp har2case](hrp_har2case.md) - Convert HAR to json/yaml testcase files * [hrp run](hrp_run.md) - run API test -###### Auto generated by spf13/cobra on 7-Dec-2021 +###### Auto generated by spf13/cobra on 8-Dec-2021 diff --git a/docs/cmd/hrp_boom.md b/docs/cmd/hrp_boom.md index 8c906a3a..b64285fa 100644 --- a/docs/cmd/hrp_boom.md +++ b/docs/cmd/hrp_boom.md @@ -39,4 +39,4 @@ hrp boom [flags] * [hrp](hrp.md) - One-stop solution for HTTP(S) testing. -###### Auto generated by spf13/cobra on 7-Dec-2021 +###### Auto generated by spf13/cobra on 8-Dec-2021 diff --git a/docs/cmd/hrp_har2case.md b/docs/cmd/hrp_har2case.md index 0932d403..7c19a593 100644 --- a/docs/cmd/hrp_har2case.md +++ b/docs/cmd/hrp_har2case.md @@ -23,4 +23,4 @@ hrp har2case harPath... [flags] * [hrp](hrp.md) - One-stop solution for HTTP(S) testing. -###### Auto generated by spf13/cobra on 7-Dec-2021 +###### Auto generated by spf13/cobra on 8-Dec-2021 diff --git a/docs/cmd/hrp_run.md b/docs/cmd/hrp_run.md index 18ba8a02..78ddca61 100644 --- a/docs/cmd/hrp_run.md +++ b/docs/cmd/hrp_run.md @@ -30,4 +30,4 @@ hrp run path... [flags] * [hrp](hrp.md) - One-stop solution for HTTP(S) testing. -###### Auto generated by spf13/cobra on 7-Dec-2021 +###### Auto generated by spf13/cobra on 8-Dec-2021 diff --git a/har2case/core.go b/har2case/core.go index 5271fc15..9cb11989 100644 --- a/har2case/core.go +++ b/har2case/core.go @@ -117,7 +117,7 @@ func (h *har) load() (*Har, error) { func (h *har) prepareConfig() *hrp.TConfig { return hrp.NewConfig("testcase description"). - SetVerifySSL(false) + SetVerifySSL(false).ToStruct() } func (h *har) prepareTestSteps() ([]*hrp.TStep, error) { diff --git a/models.go b/models.go index 94ccd45c..5b1306d7 100644 --- a/models.go +++ b/models.go @@ -78,6 +78,12 @@ type TCase struct { TestSteps []*TStep `json:"teststeps" yaml:"teststeps"` } +// IConfig represents interface for testcase config. +type IConfig interface { + Name() string + ToStruct() *TConfig +} + // IStep represents interface for all types for teststeps. type IStep interface { Name() string @@ -94,7 +100,7 @@ type ITestCase interface { // TestCase is a container for one testcase. // used for testcase runner type TestCase struct { - Config *TConfig + Config IConfig TestSteps []IStep } diff --git a/runner.go b/runner.go index 5dc91051..9812a803 100644 --- a/runner.go +++ b/runner.go @@ -104,7 +104,7 @@ func (r *hrpRunner) runCase(testcase *TestCase) error { return err } - log.Info().Str("testcase", config.Name).Msg("run testcase start") + log.Info().Str("testcase", config.Name()).Msg("run testcase start") for _, step := range testcase.TestSteps { _, err := r.runStep(step, config) @@ -113,11 +113,11 @@ func (r *hrpRunner) runCase(testcase *TestCase) error { } } - log.Info().Str("testcase", config.Name).Msg("run testcase end") + log.Info().Str("testcase", config.Name()).Msg("run testcase end") return nil } -func (r *hrpRunner) runStep(step IStep, config *TConfig) (stepResult *stepData, err error) { +func (r *hrpRunner) runStep(step IStep, config IConfig) (stepResult *stepData, err error) { // step type priority order: transaction > rendezvous > testcase > request if stepTran, ok := step.(*stepTransaction); ok { // transaction @@ -146,17 +146,18 @@ func (r *hrpRunner) runStep(step IStep, config *TConfig) (stepResult *stepData, return } + cfg := config.ToStruct() stepVariables := copiedStep.Variables // override variables // step variables > session variables (extracted variables from previous steps) stepVariables = mergeVariables(stepVariables, r.sessionVariables) // step variables > testcase config variables - stepVariables = mergeVariables(stepVariables, config.Variables) + stepVariables = mergeVariables(stepVariables, cfg.Variables) // parse step variables parsedVariables, err := parseVariables(stepVariables) if err != nil { - log.Error().Interface("variables", config.Variables).Err(err).Msg("parse step variables failed") + log.Error().Interface("variables", cfg.Variables).Err(err).Msg("parse step variables failed") return } copiedStep.Variables = parsedVariables // avoid data racing @@ -172,7 +173,7 @@ func (r *hrpRunner) runStep(step IStep, config *TConfig) (stepResult *stepData, } } else { // run request - copiedStep.Request.URL = buildURL(config.BaseURL, copiedStep.Request.URL) // avoid data racing + copiedStep.Request.URL = buildURL(cfg.BaseURL, copiedStep.Request.URL) // avoid data racing stepResult, err = r.runStepRequest(copiedStep) if err != nil { log.Error().Err(err).Msg("run request step failed") @@ -368,28 +369,29 @@ func (r *hrpRunner) runStepTestCase(step *TStep) (stepResult *stepData, err erro return } -func (r *hrpRunner) parseConfig(config *TConfig) error { +func (r *hrpRunner) parseConfig(config IConfig) error { + cfg := config.ToStruct() // parse config variables - parsedVariables, err := parseVariables(config.Variables) + parsedVariables, err := parseVariables(cfg.Variables) if err != nil { - log.Error().Interface("variables", config.Variables).Err(err).Msg("parse config variables failed") + log.Error().Interface("variables", cfg.Variables).Err(err).Msg("parse config variables failed") return err } - config.Variables = parsedVariables + cfg.Variables = parsedVariables // parse config name - parsedName, err := parseString(config.Name, config.Variables) + parsedName, err := parseString(cfg.Name, cfg.Variables) if err != nil { return err } - config.Name = convertString(parsedName) + cfg.Name = convertString(parsedName) // parse config base url - parsedBaseURL, err := parseString(config.BaseURL, config.Variables) + parsedBaseURL, err := parseString(cfg.BaseURL, cfg.Variables) if err != nil { return err } - config.BaseURL = convertString(parsedBaseURL) + cfg.BaseURL = convertString(parsedBaseURL) return nil } diff --git a/step.go b/step.go index a2804053..82b29daf 100644 --- a/step.go +++ b/step.go @@ -3,49 +3,65 @@ package hrp import "fmt" // NewConfig returns a new constructed testcase config with specified testcase name. -func NewConfig(name string) *TConfig { - return &TConfig{ - Name: name, - Variables: make(map[string]interface{}), +func NewConfig(name string) *Config { + return &Config{ + cfg: &TConfig{ + Name: name, + Variables: make(map[string]interface{}), + }, } } +type Config struct { + cfg *TConfig +} + // WithVariables sets variables for current testcase. -func (c *TConfig) WithVariables(variables map[string]interface{}) *TConfig { - c.Variables = variables +func (c *Config) WithVariables(variables map[string]interface{}) *Config { + c.cfg.Variables = variables return c } // SetBaseURL sets base URL for current testcase. -func (c *TConfig) SetBaseURL(baseURL string) *TConfig { - c.BaseURL = baseURL +func (c *Config) SetBaseURL(baseURL string) *Config { + c.cfg.BaseURL = baseURL return c } // SetVerifySSL sets whether to verify SSL for current testcase. -func (c *TConfig) SetVerifySSL(verify bool) *TConfig { - c.Verify = verify +func (c *Config) SetVerifySSL(verify bool) *Config { + c.cfg.Verify = verify return c } // WithParameters sets parameters for current testcase. -func (c *TConfig) WithParameters(parameters map[string]interface{}) *TConfig { - c.Parameters = parameters +func (c *Config) WithParameters(parameters map[string]interface{}) *Config { + c.cfg.Parameters = parameters return c } // ExportVars specifies variable names to export for current testcase. -func (c *TConfig) ExportVars(vars ...string) *TConfig { - c.Export = vars +func (c *Config) ExportVars(vars ...string) *Config { + c.cfg.Export = vars return c } // SetWeight sets weight for current testcase, which is used in load testing. -func (c *TConfig) SetWeight(weight int) *TConfig { - c.Weight = weight +func (c *Config) SetWeight(weight int) *Config { + c.cfg.Weight = weight return c } +// Name returns config name, this implements IConfig interface. +func (c *Config) Name() string { + return c.cfg.Name +} + +// ToStruct returns *TConfig, this implements IConfig interface. +func (c *Config) ToStruct() *TConfig { + return c.cfg +} + // NewStep returns a new constructed teststep with specified step name. func NewStep(name string) *TStep { return &TStep{ @@ -267,7 +283,7 @@ func (s *stepTestCaseWithOptionalArgs) Name() string { if s.step.Name != "" { return s.step.Name } - return s.step.TestCase.Config.Name + return s.step.TestCase.Config.Name() } func (s *stepTestCaseWithOptionalArgs) Type() string {