mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-11 18:11:21 +08:00
refactor: NewConfig
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
30
runner.go
30
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
|
||||
}
|
||||
|
||||
50
step.go
50
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 {
|
||||
|
||||
Reference in New Issue
Block a user