From 57a1daf105ff018aac50a6fc46d31ada7735a399 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Wed, 22 Sep 2021 17:55:39 +0800 Subject: [PATCH] refactor: run step with runner --- extract.go | 25 ++-- request.go | 145 ---------------------- runner.go | 27 ++-- runner_test.go | 6 +- step.go | 211 ++++++++++++++++++++++++++++++++ request_test.go => step_test.go | 32 ++--- testcase.go | 29 ----- validate.go | 19 +-- 8 files changed, 266 insertions(+), 228 deletions(-) delete mode 100644 request.go create mode 100644 step.go rename request_test.go => step_test.go (71%) delete mode 100644 testcase.go diff --git a/extract.go b/extract.go index d28be19..d30f7de 100644 --- a/extract.go +++ b/extract.go @@ -1,25 +1,26 @@ package httpboomer // implements IStep interface -type StepRequestExtraction struct { - *TStep +type stepRequestExtraction struct { + runner *Runner + step *TStep } -func (step *StepRequestExtraction) WithJmesPath(jmesPath string, varName string) *StepRequestExtraction { - step.TStep.Extract[varName] = jmesPath - return step +func (s *stepRequestExtraction) WithJmesPath(jmesPath string, varName string) *stepRequestExtraction { + s.step.Extract[varName] = jmesPath + return s } -func (step *StepRequestExtraction) Validate() *StepRequestValidation { - return &StepRequestValidation{ - TStep: step.TStep, +func (s *stepRequestExtraction) Validate() *stepRequestValidation { + return &stepRequestValidation{ + TStep: s.step, } } -func (step *StepRequestExtraction) ToStruct() *TStep { - return step.TStep +func (s *stepRequestExtraction) ToStruct() *TStep { + return s.step } -func (step *StepRequestExtraction) Run() error { - return step.TStep.Run() +func (s *stepRequestExtraction) Run() error { + return s.runner.runStep(s.step) } diff --git a/request.go b/request.go deleted file mode 100644 index d171828..0000000 --- a/request.go +++ /dev/null @@ -1,145 +0,0 @@ -package httpboomer - -func RunRequest(name string) *Request { - return &Request{ - TStep: &TStep{ - Name: name, - Request: &TRequest{}, - Variables: make(Variables), - }, - } -} - -type Request struct { - *TStep -} - -func (r *Request) WithVariables(variables Variables) *Request { - r.TStep.Variables = variables - return r -} - -func (r *Request) GET(url string) *RequestWithOptionalArgs { - r.TStep.Request.Method = GET - r.TStep.Request.URL = url - return &RequestWithOptionalArgs{ - TStep: r.TStep, - } -} - -func (r *Request) HEAD(url string) *RequestWithOptionalArgs { - r.TStep.Request.Method = HEAD - r.TStep.Request.URL = url - return &RequestWithOptionalArgs{ - TStep: r.TStep, - } -} - -func (r *Request) POST(url string) *RequestWithOptionalArgs { - r.TStep.Request.Method = POST - r.TStep.Request.URL = url - return &RequestWithOptionalArgs{ - TStep: r.TStep, - } -} - -func (r *Request) PUT(url string) *RequestWithOptionalArgs { - r.TStep.Request.Method = PUT - r.TStep.Request.URL = url - return &RequestWithOptionalArgs{ - TStep: r.TStep, - } -} - -func (r *Request) DELETE(url string) *RequestWithOptionalArgs { - r.TStep.Request.Method = DELETE - r.TStep.Request.URL = url - return &RequestWithOptionalArgs{ - TStep: r.TStep, - } -} - -func (r *Request) OPTIONS(url string) *RequestWithOptionalArgs { - r.TStep.Request.Method = OPTIONS - r.TStep.Request.URL = url - return &RequestWithOptionalArgs{ - TStep: r.TStep, - } -} - -func (r *Request) PATCH(url string) *RequestWithOptionalArgs { - r.TStep.Request.Method = PATCH - r.TStep.Request.URL = url - return &RequestWithOptionalArgs{ - TStep: r.TStep, - } -} - -// implements IStep interface -type RequestWithOptionalArgs struct { - *TStep -} - -func (r *RequestWithOptionalArgs) SetVerify(verify bool) *RequestWithOptionalArgs { - r.TStep.Request.Verify = verify - return r -} - -func (r *RequestWithOptionalArgs) SetTimeout(timeout float32) *RequestWithOptionalArgs { - r.TStep.Request.Timeout = timeout - return r -} - -func (r *RequestWithOptionalArgs) SetProxies(proxies map[string]string) *RequestWithOptionalArgs { - // TODO - return r -} - -func (r *RequestWithOptionalArgs) SetAllowRedirects(allowRedirects bool) *RequestWithOptionalArgs { - r.TStep.Request.AllowRedirects = allowRedirects - return r -} - -func (r *RequestWithOptionalArgs) SetAuth(auth map[string]string) *RequestWithOptionalArgs { - // TODO - return r -} - -func (r *RequestWithOptionalArgs) WithParams(params Params) *RequestWithOptionalArgs { - r.TStep.Request.Params = params - return r -} - -func (r *RequestWithOptionalArgs) WithHeaders(headers Headers) *RequestWithOptionalArgs { - r.TStep.Request.Headers = headers - return r -} - -func (r *RequestWithOptionalArgs) WithCookies(cookies Cookies) *RequestWithOptionalArgs { - r.TStep.Request.Cookies = cookies - return r -} - -func (r *RequestWithOptionalArgs) WithData(data interface{}) *RequestWithOptionalArgs { - r.TStep.Request.Data = data - return r -} - -func (r *RequestWithOptionalArgs) WithJSON(json interface{}) *RequestWithOptionalArgs { - r.TStep.Request.JSON = json - return r -} - -func (r *RequestWithOptionalArgs) Validate() *StepRequestValidation { - return &StepRequestValidation{ - TStep: r.TStep, - } -} - -func (r *RequestWithOptionalArgs) ToStruct() *TStep { - return r.TStep -} - -func (r *RequestWithOptionalArgs) Run() error { - return r.TStep.Run() -} diff --git a/runner.go b/runner.go index a054cf1..5cc44bb 100644 --- a/runner.go +++ b/runner.go @@ -6,11 +6,16 @@ import ( "github.com/imroc/req" ) +var defaultRunner = HttpRunner() + func HttpRunner() *Runner { - return &Runner{} + return &Runner{ + Client: req.New(), + } } type Runner struct { + Client *req.Req } func (r *Runner) Run(testcases ...*TestCase) error { @@ -25,23 +30,14 @@ func (r *Runner) Run(testcases ...*TestCase) error { func (r *Runner) runCase(testcase *TestCase) error { // config := testcase.Config for _, step := range testcase.TestSteps { - if err := r.runStep(step); err != nil { + if err := step.Run(); err != nil { return err } } return nil } -func (r *Runner) runStep(req IStep) error { - return req.Run() -} - -func (r *Runner) GetSummary() *TestCaseSummary { - return &TestCaseSummary{} -} - -func (step *TStep) Run() error { - +func (r *Runner) runStep(step *TStep) error { var v []interface{} v = append(v, req.Header(step.Request.Headers)) v = append(v, req.Param(step.Request.Params)) @@ -53,11 +49,14 @@ func (step *TStep) Run() error { }) } - req.Debug = true - resp, err := req.Do(string(step.Request.Method), step.Request.URL, v...) + resp, err := r.Client.Do(string(step.Request.Method), step.Request.URL, v...) if err != nil { return err } resp.Response().Body.Close() return nil } + +func (r *Runner) GetSummary() *TestCaseSummary { + return &TestCaseSummary{} +} diff --git a/runner_test.go b/runner_test.go index eba1565..acb969c 100644 --- a/runner_test.go +++ b/runner_test.go @@ -11,17 +11,17 @@ func TestHttpRunner(t *testing.T) { BaseURL: "http://httpbin.org", }, TestSteps: []IStep{ - RunRequest("headers"). + Step("headers"). GET("/headers"). Validate(). AssertEqual("status_code", 200, "check status code"). AssertEqual("headers.Host", "httpbin.org", "check http response host"), - RunRequest("user-agent"). + Step("user-agent"). GET("/user-agent"). Validate(). AssertEqual("status_code", 200, "check status code"). AssertEqual("body.\"user-agent\"", "python-requests", "check User-Agent"), - RunTestCase("TestCase3").WithVariables(Variables{"var1": "value1"}), + Step("TestCase3").CallRefCase(&TestCase{}), }, } testcase2 := &TestCase{ diff --git a/step.go b/step.go new file mode 100644 index 0000000..5a0c277 --- /dev/null +++ b/step.go @@ -0,0 +1,211 @@ +package httpboomer + +func Step(name string) *step { + return &step{ + runner: defaultRunner, + TStep: &TStep{ + Name: name, + Request: &TRequest{}, + Variables: make(Variables), + }, + } +} + +type step struct { + runner *Runner + *TStep +} + +func (s *step) WithRunner(runner *Runner) *step { + s.runner = runner + return s +} + +func (s *step) WithVariables(variables Variables) *step { + s.TStep.Variables = variables + return s +} + +func (s *step) SetupHook(hook string) *step { + s.TStep.SetupHooks = append(s.TStep.SetupHooks, hook) + return s +} + +func (s *step) GET(url string) *requestWithOptionalArgs { + s.TStep.Request.Method = GET + s.TStep.Request.URL = url + return &requestWithOptionalArgs{ + runner: s.runner, + step: s.TStep, + } +} + +func (s *step) HEAD(url string) *requestWithOptionalArgs { + s.TStep.Request.Method = HEAD + s.TStep.Request.URL = url + return &requestWithOptionalArgs{ + runner: s.runner, + step: s.TStep, + } +} + +func (s *step) POST(url string) *requestWithOptionalArgs { + s.TStep.Request.Method = POST + s.TStep.Request.URL = url + return &requestWithOptionalArgs{ + runner: s.runner, + step: s.TStep, + } +} + +func (s *step) PUT(url string) *requestWithOptionalArgs { + s.TStep.Request.Method = PUT + s.TStep.Request.URL = url + return &requestWithOptionalArgs{ + runner: s.runner, + step: s.TStep, + } +} + +func (s *step) DELETE(url string) *requestWithOptionalArgs { + s.TStep.Request.Method = DELETE + s.TStep.Request.URL = url + return &requestWithOptionalArgs{ + runner: s.runner, + step: s.TStep, + } +} + +func (s *step) OPTIONS(url string) *requestWithOptionalArgs { + s.TStep.Request.Method = OPTIONS + s.TStep.Request.URL = url + return &requestWithOptionalArgs{ + runner: s.runner, + step: s.TStep, + } +} + +func (s *step) PATCH(url string) *requestWithOptionalArgs { + s.TStep.Request.Method = PATCH + s.TStep.Request.URL = url + return &requestWithOptionalArgs{ + runner: s.runner, + step: s.TStep, + } +} + +// call referenced testcase +func (s *step) CallRefCase(tc *TestCase) *testcaseWithOptionalArgs { + s.TStep.TestCase = tc + return &testcaseWithOptionalArgs{ + runner: s.runner, + step: s.TStep, + } +} + +// implements IStep interface +type requestWithOptionalArgs struct { + runner *Runner + step *TStep +} + +func (s *requestWithOptionalArgs) SetVerify(verify bool) *requestWithOptionalArgs { + s.step.Request.Verify = verify + return s +} + +func (s *requestWithOptionalArgs) SetTimeout(timeout float32) *requestWithOptionalArgs { + s.step.Request.Timeout = timeout + return s +} + +func (s *requestWithOptionalArgs) SetProxies(proxies map[string]string) *requestWithOptionalArgs { + // TODO + return s +} + +func (s *requestWithOptionalArgs) SetAllowRedirects(allowRedirects bool) *requestWithOptionalArgs { + s.step.Request.AllowRedirects = allowRedirects + return s +} + +func (s *requestWithOptionalArgs) SetAuth(auth map[string]string) *requestWithOptionalArgs { + // TODO + return s +} + +func (s *requestWithOptionalArgs) WithParams(params Params) *requestWithOptionalArgs { + s.step.Request.Params = params + return s +} + +func (s *requestWithOptionalArgs) WithHeaders(headers Headers) *requestWithOptionalArgs { + s.step.Request.Headers = headers + return s +} + +func (s *requestWithOptionalArgs) WithCookies(cookies Cookies) *requestWithOptionalArgs { + s.step.Request.Cookies = cookies + return s +} + +func (s *requestWithOptionalArgs) WithData(data interface{}) *requestWithOptionalArgs { + s.step.Request.Data = data + return s +} + +func (s *requestWithOptionalArgs) WithJSON(json interface{}) *requestWithOptionalArgs { + s.step.Request.JSON = json + return s +} + +func (s *requestWithOptionalArgs) TeardownHook(hook string) *requestWithOptionalArgs { + s.step.TeardownHooks = append(s.step.TeardownHooks, hook) + return s +} + +func (s *requestWithOptionalArgs) Validate() *stepRequestValidation { + return &stepRequestValidation{ + runner: s.runner, + TStep: s.step, + } +} + +func (s *requestWithOptionalArgs) Extract() *stepRequestExtraction { + return &stepRequestExtraction{ + runner: s.runner, + step: s.step, + } +} + +func (s *requestWithOptionalArgs) ToStruct() *TStep { + return s.step +} + +func (s *requestWithOptionalArgs) Run() error { + return s.runner.runStep(s.step) +} + +// implements IStep interface +type testcaseWithOptionalArgs struct { + runner *Runner + step *TStep +} + +func (s *testcaseWithOptionalArgs) TeardownHook(hook string) *testcaseWithOptionalArgs { + s.step.TeardownHooks = append(s.step.TeardownHooks, hook) + return s +} + +func (s *testcaseWithOptionalArgs) Export(names ...string) *testcaseWithOptionalArgs { + s.step.Export = append(s.step.Export, names...) + return s +} + +func (s *testcaseWithOptionalArgs) ToStruct() *TStep { + return s.step +} + +func (s *testcaseWithOptionalArgs) Run() error { + return s.runner.runCase(s.step.TestCase) +} diff --git a/request_test.go b/step_test.go similarity index 71% rename from request_test.go rename to step_test.go index 7d66508..9d64380 100644 --- a/request_test.go +++ b/step_test.go @@ -5,14 +5,14 @@ import ( ) var ( - tStepGET = RunRequest("get with params"). - GET("https://postman-echo.com/get"). - WithParams(Params{"foo1": "bar1", "foo2": "bar2"}). - WithHeaders(Headers{"User-Agent": "HttpBoomer"}). - WithCookies(Cookies{"user": "debugtalk"}). - Validate(). - AssertEqual("status_code", 200, "check status code") - tStepPOSTData = RunRequest("post form data"). + stepGET = Step("get with params"). + GET("https://postman-echo.com/get"). + WithParams(Params{"foo1": "bar1", "foo2": "bar2"}). + WithHeaders(Headers{"User-Agent": "HttpBoomer"}). + WithCookies(Cookies{"user": "debugtalk"}). + Validate(). + AssertEqual("status_code", 200, "check status code") + stepPOSTData = Step("post form data"). POST("https://postman-echo.com/post"). WithParams(Params{"foo1": "bar1", "foo2": "bar2"}). WithHeaders(Headers{"User-Agent": "HttpBoomer", "Content-Type": "application/x-www-form-urlencoded"}). @@ -23,12 +23,12 @@ var ( ) func TestRunRequestGetToStruct(t *testing.T) { - tStep := tStepGET.ToStruct() + tStep := stepGET.ToStruct() if tStep.Request.Method != GET { t.Fatalf("tStep.Request.Method != GET") } - if tStep.Request.URL != "/get" { - t.Fatalf("tStep.Request.URL != '/get'") + if tStep.Request.URL != "https://postman-echo.com/get" { + t.Fatalf("tStep.Request.URL != 'https://postman-echo.com/get'") } if tStep.Request.Params["foo1"] != "bar1" || tStep.Request.Params["foo2"] != "bar2" { t.Fatalf("tStep.Request.Params mismatch") @@ -45,12 +45,12 @@ func TestRunRequestGetToStruct(t *testing.T) { } func TestRunRequestPostDataToStruct(t *testing.T) { - tStep := tStepPOSTData.ToStruct() + tStep := stepPOSTData.ToStruct() if tStep.Request.Method != POST { t.Fatalf("tStep.Request.Method != POST") } - if tStep.Request.URL != "/post" { - t.Fatalf("tStep.Request.URL != '/post'") + if tStep.Request.URL != "https://postman-echo.com/post" { + t.Fatalf("tStep.Request.URL != 'https://postman-echo.com/post'") } if tStep.Request.Params["foo1"] != "bar1" || tStep.Request.Params["foo2"] != "bar2" { t.Fatalf("tStep.Request.Params mismatch") @@ -70,10 +70,10 @@ func TestRunRequestPostDataToStruct(t *testing.T) { } func TestRunRequestRun(t *testing.T) { - if err := tStepGET.Run(); err != nil { + if err := stepGET.Run(); err != nil { t.Fatalf("tStep.Run() error: %s", err) } - if err := tStepPOSTData.Run(); err != nil { + if err := stepPOSTData.Run(); err != nil { t.Fatalf("tStepPOSTData.Run() error: %s", err) } } diff --git a/testcase.go b/testcase.go deleted file mode 100644 index 894ef6f..0000000 --- a/testcase.go +++ /dev/null @@ -1,29 +0,0 @@ -package httpboomer - -func RunTestCase(name string) *TestCase { - return &TestCase{ - Config: TConfig{ - Name: name, - }, - } -} - -func (tc *TestCase) WithVariables(variables Variables) *TestCase { - tc.Config.Variables = variables - return tc -} - -func (tc *TestCase) ToStruct() *TStep { - return &TStep{ - TestCase: tc, - } -} - -func (tc *TestCase) Run() error { - for _, step := range tc.TestSteps { - if err := step.Run(); err != nil { - return err - } - } - return nil -} diff --git a/validate.go b/validate.go index 4824376..065266f 100644 --- a/validate.go +++ b/validate.go @@ -1,25 +1,26 @@ package httpboomer // implements IStep interface -type StepRequestValidation struct { - *TStep +type stepRequestValidation struct { + runner *Runner + TStep *TStep } -func (step *StepRequestValidation) AssertEqual(jmesPath string, expected interface{}, msg string) *StepRequestValidation { +func (s *stepRequestValidation) AssertEqual(jmesPath string, expected interface{}, msg string) *stepRequestValidation { validator := TValidator{ Check: jmesPath, Comparator: "equals", Expect: expected, Message: msg, } - step.TStep.Validators = append(step.TStep.Validators, validator) - return step + s.TStep.Validators = append(s.TStep.Validators, validator) + return s } -func (step *StepRequestValidation) ToStruct() *TStep { - return step.TStep +func (s *stepRequestValidation) ToStruct() *TStep { + return s.TStep } -func (step *StepRequestValidation) Run() error { - return step.TStep.Run() +func (s *stepRequestValidation) Run() error { + return s.runner.runStep(s.TStep) }