refactor: NewConfig

This commit is contained in:
debugtalk
2021-12-08 13:07:39 +08:00
parent 9689201d29
commit a55f523fd7
10 changed files with 67 additions and 44 deletions

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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) {

View File

@@ -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
}

View File

@@ -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
}

50
step.go
View File

@@ -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 {