refactor: NewStep

This commit is contained in:
debugtalk
2021-12-08 13:26:12 +08:00
parent 99972064ab
commit a301266227
6 changed files with 110 additions and 102 deletions
+4 -4
View File
@@ -109,19 +109,19 @@ func (tc *TCase) ToTestCase() (*TestCase, error) {
} }
for _, step := range tc.TestSteps { for _, step := range tc.TestSteps {
if step.Request != nil { if step.Request != nil {
testCase.TestSteps = append(testCase.TestSteps, &stepRequestWithOptionalArgs{ testCase.TestSteps = append(testCase.TestSteps, &StepRequestWithOptionalArgs{
step: step, step: step,
}) })
} else if step.TestCase != nil { } else if step.TestCase != nil {
testCase.TestSteps = append(testCase.TestSteps, &stepTestCaseWithOptionalArgs{ testCase.TestSteps = append(testCase.TestSteps, &StepTestCaseWithOptionalArgs{
step: step, step: step,
}) })
} else if step.Transaction != nil { } else if step.Transaction != nil {
testCase.TestSteps = append(testCase.TestSteps, &stepTransaction{ testCase.TestSteps = append(testCase.TestSteps, &StepTransaction{
step: step, step: step,
}) })
} else if step.Rendezvous != nil { } else if step.Rendezvous != nil {
testCase.TestSteps = append(testCase.TestSteps, &stepRendezvous{ testCase.TestSteps = append(testCase.TestSteps, &StepRendezvous{
step: step, step: step,
}) })
} else { } else {
+8 -8
View File
@@ -2,32 +2,32 @@ package hrp
import "fmt" import "fmt"
// implements IStep interface // StepRequestExtraction implements IStep interface.
type stepRequestExtraction struct { type StepRequestExtraction struct {
step *TStep step *TStep
} }
// WithJmesPath sets the JMESPath expression to extract from the response. // WithJmesPath sets the JMESPath expression to extract from the response.
func (s *stepRequestExtraction) WithJmesPath(jmesPath string, varName string) *stepRequestExtraction { func (s *StepRequestExtraction) WithJmesPath(jmesPath string, varName string) *StepRequestExtraction {
s.step.Extract[varName] = jmesPath s.step.Extract[varName] = jmesPath
return s return s
} }
// Validate switches to step validation. // Validate switches to step validation.
func (s *stepRequestExtraction) Validate() *stepRequestValidation { func (s *StepRequestExtraction) Validate() *StepRequestValidation {
return &stepRequestValidation{ return &StepRequestValidation{
step: s.step, step: s.step,
} }
} }
func (s *stepRequestExtraction) Name() string { func (s *StepRequestExtraction) Name() string {
return s.step.Name return s.step.Name
} }
func (s *stepRequestExtraction) Type() string { func (s *StepRequestExtraction) Type() string {
return fmt.Sprintf("request-%v", s.step.Request.Method) return fmt.Sprintf("request-%v", s.step.Request.Method)
} }
func (s *stepRequestExtraction) ToStruct() *TStep { func (s *StepRequestExtraction) ToStruct() *TStep {
return s.step return s.step
} }
+3 -2
View File
@@ -97,8 +97,8 @@ type ITestCase interface {
ToTCase() (*TCase, error) ToTCase() (*TCase, error)
} }
// TestCase is a container for one testcase. // TestCase is a container for one testcase, which is used for testcase runner.
// used for testcase runner // TestCase implements ITestCase interface.
type TestCase struct { type TestCase struct {
Config IConfig Config IConfig
TestSteps []IStep TestSteps []IStep
@@ -108,6 +108,7 @@ func (tc *TestCase) ToTestCase() (*TestCase, error) {
return tc, nil return tc, nil
} }
// TestCasePath implements ITestCase interface.
type TestCasePath struct { type TestCasePath struct {
Path string Path string
} }
+3 -3
View File
@@ -119,14 +119,14 @@ func (r *hrpRunner) runCase(testcase *TestCase) error {
func (r *hrpRunner) runStep(step IStep, config IConfig) (stepResult *stepData, err error) { func (r *hrpRunner) runStep(step IStep, config IConfig) (stepResult *stepData, err error) {
// step type priority order: transaction > rendezvous > testcase > request // step type priority order: transaction > rendezvous > testcase > request
if stepTran, ok := step.(*stepTransaction); ok { if stepTran, ok := step.(*StepTransaction); ok {
// transaction // transaction
log.Info(). log.Info().
Str("name", stepTran.step.Transaction.Name). Str("name", stepTran.step.Transaction.Name).
Str("type", stepTran.step.Transaction.Type). Str("type", stepTran.step.Transaction.Type).
Msg("transaction") Msg("transaction")
return nil, nil return nil, nil
} else if stepRend, ok := step.(*stepRendezvous); ok { } else if stepRend, ok := step.(*StepRendezvous); ok {
// rendezvous // rendezvous
log.Info(). log.Info().
Str("name", stepRend.step.Rendezvous.Name). Str("name", stepRend.step.Rendezvous.Name).
@@ -162,7 +162,7 @@ func (r *hrpRunner) runStep(step IStep, config IConfig) (stepResult *stepData, e
} }
copiedStep.Variables = parsedVariables // avoid data racing copiedStep.Variables = parsedVariables // avoid data racing
if _, ok := step.(*stepTestCaseWithOptionalArgs); ok { if _, ok := step.(*StepTestCaseWithOptionalArgs); ok {
// run referenced testcase // run referenced testcase
log.Info().Str("testcase", copiedStep.Name).Msg("run referenced testcase") log.Info().Str("testcase", copiedStep.Name).Msg("run referenced testcase")
// TODO: override testcase config // TODO: override testcase config
+81 -74
View File
@@ -12,6 +12,7 @@ func NewConfig(name string) *Config {
} }
} }
// Config implements IConfig interface.
type Config struct { type Config struct {
cfg *TConfig cfg *TConfig
} }
@@ -63,273 +64,279 @@ func (c *Config) ToStruct() *TConfig {
} }
// NewStep returns a new constructed teststep with specified step name. // NewStep returns a new constructed teststep with specified step name.
func NewStep(name string) *TStep { func NewStep(name string) *StepRequest {
return &TStep{ return &StepRequest{
step: &TStep{
Name: name, Name: name,
Variables: make(map[string]interface{}), Variables: make(map[string]interface{}),
},
} }
} }
type StepRequest struct {
step *TStep
}
// WithVariables sets variables for current teststep. // WithVariables sets variables for current teststep.
func (s *TStep) WithVariables(variables map[string]interface{}) *TStep { func (s *StepRequest) WithVariables(variables map[string]interface{}) *StepRequest {
s.Variables = variables s.step.Variables = variables
return s return s
} }
// SetupHook adds a setup hook for current teststep. // SetupHook adds a setup hook for current teststep.
func (s *TStep) SetupHook(hook string) *TStep { func (s *StepRequest) SetupHook(hook string) *StepRequest {
s.SetupHooks = append(s.SetupHooks, hook) s.step.SetupHooks = append(s.step.SetupHooks, hook)
return s return s
} }
// GET makes a HTTP GET request. // GET makes a HTTP GET request.
func (s *TStep) GET(url string) *stepRequestWithOptionalArgs { func (s *StepRequest) GET(url string) *StepRequestWithOptionalArgs {
s.Request = &Request{ s.step.Request = &Request{
Method: httpGET, Method: httpGET,
URL: url, URL: url,
} }
return &stepRequestWithOptionalArgs{ return &StepRequestWithOptionalArgs{
step: s, step: s.step,
} }
} }
// HEAD makes a HTTP HEAD request. // HEAD makes a HTTP HEAD request.
func (s *TStep) HEAD(url string) *stepRequestWithOptionalArgs { func (s *StepRequest) HEAD(url string) *StepRequestWithOptionalArgs {
s.Request = &Request{ s.step.Request = &Request{
Method: httpHEAD, Method: httpHEAD,
URL: url, URL: url,
} }
return &stepRequestWithOptionalArgs{ return &StepRequestWithOptionalArgs{
step: s, step: s.step,
} }
} }
// POST makes a HTTP POST request. // POST makes a HTTP POST request.
func (s *TStep) POST(url string) *stepRequestWithOptionalArgs { func (s *StepRequest) POST(url string) *StepRequestWithOptionalArgs {
s.Request = &Request{ s.step.Request = &Request{
Method: httpPOST, Method: httpPOST,
URL: url, URL: url,
} }
return &stepRequestWithOptionalArgs{ return &StepRequestWithOptionalArgs{
step: s, step: s.step,
} }
} }
// PUT makes a HTTP PUT request. // PUT makes a HTTP PUT request.
func (s *TStep) PUT(url string) *stepRequestWithOptionalArgs { func (s *StepRequest) PUT(url string) *StepRequestWithOptionalArgs {
s.Request = &Request{ s.step.Request = &Request{
Method: httpPUT, Method: httpPUT,
URL: url, URL: url,
} }
return &stepRequestWithOptionalArgs{ return &StepRequestWithOptionalArgs{
step: s, step: s.step,
} }
} }
// DELETE makes a HTTP DELETE request. // DELETE makes a HTTP DELETE request.
func (s *TStep) DELETE(url string) *stepRequestWithOptionalArgs { func (s *StepRequest) DELETE(url string) *StepRequestWithOptionalArgs {
s.Request = &Request{ s.step.Request = &Request{
Method: httpDELETE, Method: httpDELETE,
URL: url, URL: url,
} }
return &stepRequestWithOptionalArgs{ return &StepRequestWithOptionalArgs{
step: s, step: s.step,
} }
} }
// OPTIONS makes a HTTP OPTIONS request. // OPTIONS makes a HTTP OPTIONS request.
func (s *TStep) OPTIONS(url string) *stepRequestWithOptionalArgs { func (s *StepRequest) OPTIONS(url string) *StepRequestWithOptionalArgs {
s.Request = &Request{ s.step.Request = &Request{
Method: httpOPTIONS, Method: httpOPTIONS,
URL: url, URL: url,
} }
return &stepRequestWithOptionalArgs{ return &StepRequestWithOptionalArgs{
step: s, step: s.step,
} }
} }
// PATCH makes a HTTP PATCH request. // PATCH makes a HTTP PATCH request.
func (s *TStep) PATCH(url string) *stepRequestWithOptionalArgs { func (s *StepRequest) PATCH(url string) *StepRequestWithOptionalArgs {
s.Request = &Request{ s.step.Request = &Request{
Method: httpPATCH, Method: httpPATCH,
URL: url, URL: url,
} }
return &stepRequestWithOptionalArgs{ return &StepRequestWithOptionalArgs{
step: s, step: s.step,
} }
} }
// CallRefCase calls a referenced testcase. // CallRefCase calls a referenced testcase.
func (s *TStep) CallRefCase(tc *TestCase) *stepTestCaseWithOptionalArgs { func (s *StepRequest) CallRefCase(tc *TestCase) *StepTestCaseWithOptionalArgs {
s.TestCase = tc s.step.TestCase = tc
return &stepTestCaseWithOptionalArgs{ return &StepTestCaseWithOptionalArgs{
step: s, step: s.step,
} }
} }
// implements IStep interface // StepRequestWithOptionalArgs implements IStep interface.
type stepRequestWithOptionalArgs struct { type StepRequestWithOptionalArgs struct {
step *TStep step *TStep
} }
// SetVerify sets whether to verify SSL for current HTTP request. // SetVerify sets whether to verify SSL for current HTTP request.
func (s *stepRequestWithOptionalArgs) SetVerify(verify bool) *stepRequestWithOptionalArgs { func (s *StepRequestWithOptionalArgs) SetVerify(verify bool) *StepRequestWithOptionalArgs {
s.step.Request.Verify = verify s.step.Request.Verify = verify
return s return s
} }
// SetTimeout sets timeout for current HTTP request. // SetTimeout sets timeout for current HTTP request.
func (s *stepRequestWithOptionalArgs) SetTimeout(timeout float32) *stepRequestWithOptionalArgs { func (s *StepRequestWithOptionalArgs) SetTimeout(timeout float32) *StepRequestWithOptionalArgs {
s.step.Request.Timeout = timeout s.step.Request.Timeout = timeout
return s return s
} }
// SetProxies sets proxies for current HTTP request. // SetProxies sets proxies for current HTTP request.
func (s *stepRequestWithOptionalArgs) SetProxies(proxies map[string]string) *stepRequestWithOptionalArgs { func (s *StepRequestWithOptionalArgs) SetProxies(proxies map[string]string) *StepRequestWithOptionalArgs {
// TODO // TODO
return s return s
} }
// SetAllowRedirects sets whether to allow redirects for current HTTP request. // SetAllowRedirects sets whether to allow redirects for current HTTP request.
func (s *stepRequestWithOptionalArgs) SetAllowRedirects(allowRedirects bool) *stepRequestWithOptionalArgs { func (s *StepRequestWithOptionalArgs) SetAllowRedirects(allowRedirects bool) *StepRequestWithOptionalArgs {
s.step.Request.AllowRedirects = allowRedirects s.step.Request.AllowRedirects = allowRedirects
return s return s
} }
// SetAuth sets auth for current HTTP request. // SetAuth sets auth for current HTTP request.
func (s *stepRequestWithOptionalArgs) SetAuth(auth map[string]string) *stepRequestWithOptionalArgs { func (s *StepRequestWithOptionalArgs) SetAuth(auth map[string]string) *StepRequestWithOptionalArgs {
// TODO // TODO
return s return s
} }
// WithParams sets HTTP request params for current step. // WithParams sets HTTP request params for current step.
func (s *stepRequestWithOptionalArgs) WithParams(params map[string]interface{}) *stepRequestWithOptionalArgs { func (s *StepRequestWithOptionalArgs) WithParams(params map[string]interface{}) *StepRequestWithOptionalArgs {
s.step.Request.Params = params s.step.Request.Params = params
return s return s
} }
// WithHeaders sets HTTP request headers for current step. // WithHeaders sets HTTP request headers for current step.
func (s *stepRequestWithOptionalArgs) WithHeaders(headers map[string]string) *stepRequestWithOptionalArgs { func (s *StepRequestWithOptionalArgs) WithHeaders(headers map[string]string) *StepRequestWithOptionalArgs {
s.step.Request.Headers = headers s.step.Request.Headers = headers
return s return s
} }
// WithCookies sets HTTP request cookies for current step. // WithCookies sets HTTP request cookies for current step.
func (s *stepRequestWithOptionalArgs) WithCookies(cookies map[string]string) *stepRequestWithOptionalArgs { func (s *StepRequestWithOptionalArgs) WithCookies(cookies map[string]string) *StepRequestWithOptionalArgs {
s.step.Request.Cookies = cookies s.step.Request.Cookies = cookies
return s return s
} }
// WithBody sets HTTP request body for current step. // WithBody sets HTTP request body for current step.
func (s *stepRequestWithOptionalArgs) WithBody(body interface{}) *stepRequestWithOptionalArgs { func (s *StepRequestWithOptionalArgs) WithBody(body interface{}) *StepRequestWithOptionalArgs {
s.step.Request.Body = body s.step.Request.Body = body
return s return s
} }
// TeardownHook adds a teardown hook for current teststep. // TeardownHook adds a teardown hook for current teststep.
func (s *stepRequestWithOptionalArgs) TeardownHook(hook string) *stepRequestWithOptionalArgs { func (s *StepRequestWithOptionalArgs) TeardownHook(hook string) *StepRequestWithOptionalArgs {
s.step.TeardownHooks = append(s.step.TeardownHooks, hook) s.step.TeardownHooks = append(s.step.TeardownHooks, hook)
return s return s
} }
// Validate switches to step validation. // Validate switches to step validation.
func (s *stepRequestWithOptionalArgs) Validate() *stepRequestValidation { func (s *StepRequestWithOptionalArgs) Validate() *StepRequestValidation {
return &stepRequestValidation{ return &StepRequestValidation{
step: s.step, step: s.step,
} }
} }
// Extract switches to step extraction. // Extract switches to step extraction.
func (s *stepRequestWithOptionalArgs) Extract() *stepRequestExtraction { func (s *StepRequestWithOptionalArgs) Extract() *StepRequestExtraction {
s.step.Extract = make(map[string]string) s.step.Extract = make(map[string]string)
return &stepRequestExtraction{ return &StepRequestExtraction{
step: s.step, step: s.step,
} }
} }
func (s *stepRequestWithOptionalArgs) Name() string { func (s *StepRequestWithOptionalArgs) Name() string {
if s.step.Name != "" { if s.step.Name != "" {
return s.step.Name return s.step.Name
} }
return fmt.Sprintf("%s %s", s.step.Request.Method, s.step.Request.URL) return fmt.Sprintf("%s %s", s.step.Request.Method, s.step.Request.URL)
} }
func (s *stepRequestWithOptionalArgs) Type() string { func (s *StepRequestWithOptionalArgs) Type() string {
return fmt.Sprintf("request-%v", s.step.Request.Method) return fmt.Sprintf("request-%v", s.step.Request.Method)
} }
func (s *stepRequestWithOptionalArgs) ToStruct() *TStep { func (s *StepRequestWithOptionalArgs) ToStruct() *TStep {
return s.step return s.step
} }
// implements IStep interface // StepTestCaseWithOptionalArgs implements IStep interface.
type stepTestCaseWithOptionalArgs struct { type StepTestCaseWithOptionalArgs struct {
step *TStep step *TStep
} }
// TeardownHook adds a teardown hook for current teststep. // TeardownHook adds a teardown hook for current teststep.
func (s *stepTestCaseWithOptionalArgs) TeardownHook(hook string) *stepTestCaseWithOptionalArgs { func (s *StepTestCaseWithOptionalArgs) TeardownHook(hook string) *StepTestCaseWithOptionalArgs {
s.step.TeardownHooks = append(s.step.TeardownHooks, hook) s.step.TeardownHooks = append(s.step.TeardownHooks, hook)
return s return s
} }
// Export specifies variable names to export from referenced testcase for current step. // Export specifies variable names to export from referenced testcase for current step.
func (s *stepTestCaseWithOptionalArgs) Export(names ...string) *stepTestCaseWithOptionalArgs { func (s *StepTestCaseWithOptionalArgs) Export(names ...string) *StepTestCaseWithOptionalArgs {
s.step.Export = append(s.step.Export, names...) s.step.Export = append(s.step.Export, names...)
return s return s
} }
func (s *stepTestCaseWithOptionalArgs) Name() string { func (s *StepTestCaseWithOptionalArgs) Name() string {
if s.step.Name != "" { if s.step.Name != "" {
return s.step.Name return s.step.Name
} }
return s.step.TestCase.Config.Name() return s.step.TestCase.Config.Name()
} }
func (s *stepTestCaseWithOptionalArgs) Type() string { func (s *StepTestCaseWithOptionalArgs) Type() string {
return "testcase" return "testcase"
} }
func (s *stepTestCaseWithOptionalArgs) ToStruct() *TStep { func (s *StepTestCaseWithOptionalArgs) ToStruct() *TStep {
return s.step return s.step
} }
// implements IStep interface // StepTransaction implements IStep interface.
type stepTransaction struct { type StepTransaction struct {
step *TStep step *TStep
} }
func (s *stepTransaction) Name() string { func (s *StepTransaction) Name() string {
if s.step.Name != "" { if s.step.Name != "" {
return s.step.Name return s.step.Name
} }
return fmt.Sprintf("transaction %s %s", s.step.Transaction.Name, s.step.Transaction.Type) return fmt.Sprintf("transaction %s %s", s.step.Transaction.Name, s.step.Transaction.Type)
} }
func (s *stepTransaction) Type() string { func (s *StepTransaction) Type() string {
return "transaction" return "transaction"
} }
func (s *stepTransaction) ToStruct() *TStep { func (s *StepTransaction) ToStruct() *TStep {
return s.step return s.step
} }
// implements IStep interface // StepRendezvous implements IStep interface.
type stepRendezvous struct { type StepRendezvous struct {
step *TStep step *TStep
} }
func (s *stepRendezvous) Name() string { func (s *StepRendezvous) Name() string {
if s.step.Name != "" { if s.step.Name != "" {
return s.step.Name return s.step.Name
} }
return s.step.Rendezvous.Name return s.step.Rendezvous.Name
} }
func (s *stepRendezvous) Type() string { func (s *StepRendezvous) Type() string {
return "rendezvous" return "rendezvous"
} }
func (s *stepRendezvous) ToStruct() *TStep { func (s *StepRendezvous) ToStruct() *TStep {
return s.step return s.step
} }
+9 -9
View File
@@ -4,27 +4,27 @@ import (
"fmt" "fmt"
) )
// implements IStep interface // StepRequestValidation implements IStep interface.
type stepRequestValidation struct { type StepRequestValidation struct {
step *TStep step *TStep
} }
func (s *stepRequestValidation) Name() string { func (s *StepRequestValidation) Name() string {
if s.step.Name != "" { if s.step.Name != "" {
return s.step.Name return s.step.Name
} }
return fmt.Sprintf("%s %s", s.step.Request.Method, s.step.Request.URL) return fmt.Sprintf("%s %s", s.step.Request.Method, s.step.Request.URL)
} }
func (s *stepRequestValidation) Type() string { func (s *StepRequestValidation) Type() string {
return fmt.Sprintf("request-%v", s.step.Request.Method) return fmt.Sprintf("request-%v", s.step.Request.Method)
} }
func (s *stepRequestValidation) ToStruct() *TStep { func (s *StepRequestValidation) ToStruct() *TStep {
return s.step return s.step
} }
func (s *stepRequestValidation) AssertEqual(jmesPath string, expected interface{}, msg string) *stepRequestValidation { func (s *StepRequestValidation) AssertEqual(jmesPath string, expected interface{}, msg string) *StepRequestValidation {
v := Validator{ v := Validator{
Check: jmesPath, Check: jmesPath,
Assert: "equals", Assert: "equals",
@@ -35,7 +35,7 @@ func (s *stepRequestValidation) AssertEqual(jmesPath string, expected interface{
return s return s
} }
func (s *stepRequestValidation) AssertStartsWith(jmesPath string, expected interface{}, msg string) *stepRequestValidation { func (s *StepRequestValidation) AssertStartsWith(jmesPath string, expected interface{}, msg string) *StepRequestValidation {
v := Validator{ v := Validator{
Check: jmesPath, Check: jmesPath,
Assert: "startswith", Assert: "startswith",
@@ -46,7 +46,7 @@ func (s *stepRequestValidation) AssertStartsWith(jmesPath string, expected inter
return s return s
} }
func (s *stepRequestValidation) AssertEndsWith(jmesPath string, expected interface{}, msg string) *stepRequestValidation { func (s *StepRequestValidation) AssertEndsWith(jmesPath string, expected interface{}, msg string) *StepRequestValidation {
v := Validator{ v := Validator{
Check: jmesPath, Check: jmesPath,
Assert: "endswith", Assert: "endswith",
@@ -57,7 +57,7 @@ func (s *stepRequestValidation) AssertEndsWith(jmesPath string, expected interfa
return s return s
} }
func (s *stepRequestValidation) AssertLengthEqual(jmesPath string, expected interface{}, msg string) *stepRequestValidation { func (s *StepRequestValidation) AssertLengthEqual(jmesPath string, expected interface{}, msg string) *StepRequestValidation {
v := Validator{ v := Validator{
Check: jmesPath, Check: jmesPath,
Assert: "length_equals", Assert: "length_equals",