diff --git a/README.md b/README.md index 851d0efa..452722d2 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ HttpBoomer is a golang implementation of [HttpRunner]. Ideally, HttpBoomer will ![flow chart](docs/flow.jpg) - [x] Full support for HTTP(S) requests, more protocols are also in the plan. -- [ ] Testcases can be described in multiple formats, `YAML`/`JSON`/`Golang`, and they are interchangeable. +- [x] Testcases can be described in multiple formats, `YAML`/`JSON`/`Golang`, and they are interchangeable. - [ ] With [`HAR`][HAR] support, you can use Charles/Fiddler/Chrome/etc as a script recording generator. - [x] Supports `variables`/`extract`/`validate`/`hooks` mechanisms to create extremely complex test scenarios. - [ ] Built-in integration of rich functions, and you can also use [`go plugin`][plugin] to create and call custom functions. diff --git a/convert.go b/convert.go index 80280226..c99d2bb7 100644 --- a/convert.go +++ b/convert.go @@ -3,6 +3,7 @@ package httpboomer import ( "bytes" "encoding/json" + "fmt" "io/ioutil" "log" "path/filepath" @@ -124,3 +125,29 @@ func convertTestCase(tc *TCase) (*TestCase, error) { } return testCase, nil } + +var ErrUnsupportedFileExt = fmt.Errorf("unsupported testcase file extension") + +func loadTestFile(path *TestCasePath) (*TestCase, error) { + var tc *TCase + var err error + + casePath := path.string + ext := filepath.Ext(casePath) + switch ext { + case ".json": + tc, err = loadFromJSON(casePath) + case ".yaml", ".yml": + tc, err = loadFromYAML(casePath) + default: + err = ErrUnsupportedFileExt + } + if err != nil { + return nil, err + } + testcase, err := convertTestCase(tc) + if err != nil { + return nil, err + } + return testcase, nil +} diff --git a/convert_test.go b/convert_test.go index 8b9dbb9e..9abd788c 100644 --- a/convert_test.go +++ b/convert_test.go @@ -50,7 +50,7 @@ var demoTestCase = &TestCase{ } func TestDumpAndLoadJSON(t *testing.T) { - jsonPath := "demo.json" + jsonPath := demoTestCaseJSONPath err := demoTestCase.dump2JSON(jsonPath) if !assert.NoError(t, err) { t.Fail() @@ -94,13 +94,11 @@ func TestDumpAndLoadYAML(t *testing.T) { } } +var demoTestCaseJSONPath = "demo.json" + func TestLoadJSONAndRun(t *testing.T) { - jsonPath := "demo.json" - tc, err := loadFromJSON(jsonPath) - if !assert.NoError(t, err) { - t.Fail() - } - testcase, err := convertTestCase(tc) + jsonPath := &TestCasePath{demoTestCaseJSONPath} + testcase, err := loadTestFile(jsonPath) if !assert.NoError(t, err) { t.Fail() } diff --git a/models.go b/models.go index 8b0e8e75..87e67f29 100644 --- a/models.go +++ b/models.go @@ -67,12 +67,32 @@ type IStep interface { ToStruct() *TStep } +type ITestCase interface { + ToStruct() (*TestCase, error) +} + // used for testcase runner type TestCase struct { Config TConfig TestSteps []IStep } +func (tc *TestCase) ToStruct() (*TestCase, error) { + return tc, nil +} + +type TestCasePath struct { + string +} + +func (path *TestCasePath) ToStruct() (*TestCase, error) { + testcase, err := loadTestFile(path) + if err != nil { + return nil, err + } + return testcase, nil +} + type TestCaseSummary struct{} type StepData struct { diff --git a/runner.go b/runner.go index 6565f120..43a99005 100644 --- a/runner.go +++ b/runner.go @@ -8,7 +8,7 @@ import ( "github.com/imroc/req" ) -func Test(t *testing.T, testcases ...*TestCase) error { +func Test(t *testing.T, testcases ...ITestCase) error { return NewRunner().WithTestingT(t).SetDebug(true).Run(testcases...) } @@ -36,9 +36,15 @@ func (r *Runner) SetDebug(debug bool) *Runner { return r } -func (r *Runner) Run(testcases ...*TestCase) error { +func (r *Runner) Run(testcases ...ITestCase) error { for _, testcase := range testcases { - if err := r.runCase(testcase); err != nil { + tcStruct, err := testcase.ToStruct() + if err != nil { + log.Printf("[Run] testcase.ToStruct() error: %v", err) + return err + } + if err := r.runCase(tcStruct); err != nil { + log.Printf("[Run] runCase error: %v", err) return err } } diff --git a/runner_test.go b/runner_test.go index 8a490e23..fbd180e8 100644 --- a/runner_test.go +++ b/runner_test.go @@ -1,6 +1,7 @@ package httpboomer import ( + "os" "testing" ) @@ -30,9 +31,29 @@ func TestHttpRunner(t *testing.T) { Weight: 3, }, } + testcase3 := &TestCasePath{demoTestCaseJSONPath} - err := Test(t, testcase1, testcase2) + err := Test(t, testcase1, testcase2, testcase3) if err != nil { t.Fatalf("run testcase error: %v", err) } } + +func TestMain(m *testing.M) { + // setup, prepare demo json testcase file path + jsonPath := demoTestCaseJSONPath + err := demoTestCase.dump2JSON(jsonPath) + if err != nil { + os.Exit(1) + } + + // run all tests + code := m.Run() + defer os.Exit(code) + + // teardown + err = os.Remove(jsonPath) + if err != nil { + os.Exit(1) + } +}