diff --git a/docs/cmd/hrp.md b/docs/cmd/hrp.md index 7b19c12c..1a3960a4 100644 --- a/docs/cmd/hrp.md +++ b/docs/cmd/hrp.md @@ -35,4 +35,4 @@ Copyright 2021 debugtalk * [hrp run](hrp_run.md) - run API test with go engine * [hrp startproject](hrp_startproject.md) - create a scaffold project -###### Auto generated by spf13/cobra on 16-Apr-2022 +###### Auto generated by spf13/cobra on 17-Apr-2022 diff --git a/docs/cmd/hrp_boom.md b/docs/cmd/hrp_boom.md index 0315dece..7be66d74 100644 --- a/docs/cmd/hrp_boom.md +++ b/docs/cmd/hrp_boom.md @@ -41,4 +41,4 @@ hrp boom [flags] * [hrp](hrp.md) - Next-Generation API Testing Solution. -###### Auto generated by spf13/cobra on 16-Apr-2022 +###### Auto generated by spf13/cobra on 17-Apr-2022 diff --git a/docs/cmd/hrp_har2case.md b/docs/cmd/hrp_har2case.md index 5fd11b46..729b1226 100644 --- a/docs/cmd/hrp_har2case.md +++ b/docs/cmd/hrp_har2case.md @@ -24,4 +24,4 @@ hrp har2case $har_path... [flags] * [hrp](hrp.md) - Next-Generation API Testing Solution. -###### Auto generated by spf13/cobra on 16-Apr-2022 +###### Auto generated by spf13/cobra on 17-Apr-2022 diff --git a/docs/cmd/hrp_pytest.md b/docs/cmd/hrp_pytest.md index 3f181b01..5a2363be 100644 --- a/docs/cmd/hrp_pytest.md +++ b/docs/cmd/hrp_pytest.md @@ -16,4 +16,4 @@ hrp pytest $path ... [flags] * [hrp](hrp.md) - Next-Generation API Testing Solution. -###### Auto generated by spf13/cobra on 16-Apr-2022 +###### Auto generated by spf13/cobra on 17-Apr-2022 diff --git a/docs/cmd/hrp_run.md b/docs/cmd/hrp_run.md index 3576c306..7ad8d4d4 100644 --- a/docs/cmd/hrp_run.md +++ b/docs/cmd/hrp_run.md @@ -34,4 +34,4 @@ hrp run $path... [flags] * [hrp](hrp.md) - Next-Generation API Testing Solution. -###### Auto generated by spf13/cobra on 16-Apr-2022 +###### Auto generated by spf13/cobra on 17-Apr-2022 diff --git a/docs/cmd/hrp_startproject.md b/docs/cmd/hrp_startproject.md index d1c109bd..e33d46d6 100644 --- a/docs/cmd/hrp_startproject.md +++ b/docs/cmd/hrp_startproject.md @@ -19,4 +19,4 @@ hrp startproject $project_name [flags] * [hrp](hrp.md) - Next-Generation API Testing Solution. -###### Auto generated by spf13/cobra on 16-Apr-2022 +###### Auto generated by spf13/cobra on 17-Apr-2022 diff --git a/hrp/plugin.go b/hrp/plugin.go index a4beb671..a8144797 100644 --- a/hrp/plugin.go +++ b/hrp/plugin.go @@ -19,15 +19,17 @@ const ( hashicorpPyPluginFile = "debugtalk.py" // used for hashicorp python plugin ) -func initPlugin(path string, logOn bool) (plugin funplugin.IPlugin, err error) { +func initPlugin(path string, logOn bool) (plugin funplugin.IPlugin, pluginDir string, err error) { // plugin file not found if path == "" { - return nil, nil + return nil, "", nil } pluginPath, err := locatePlugin(path) if err != nil { - return nil, nil + return nil, "", nil } + // TODO: move pluginDir to funplugin + pluginDir = filepath.Dir(pluginPath) // found plugin file plugin, err = funplugin.Init(pluginPath, funplugin.WithLogOn(logOn)) diff --git a/hrp/runner.go b/hrp/runner.go index acdda315..fcc2cfe7 100644 --- a/hrp/runner.go +++ b/hrp/runner.go @@ -2,11 +2,9 @@ package hrp import ( "crypto/tls" - "fmt" "net" "net/http" "net/url" - "path/filepath" "testing" "time" @@ -15,7 +13,6 @@ import ( "github.com/rs/zerolog/log" "golang.org/x/net/http2" - "github.com/httprunner/httprunner/hrp/internal/builtin" "github.com/httprunner/httprunner/hrp/internal/sdk" ) @@ -175,22 +172,9 @@ func (r *HRPRunner) Run(testcases ...ITestCase) error { } s.Time.Duration = time.Since(s.Time.StartAt).Seconds() - // update the report output path - pluginPath, err := locatePlugin(testcases[0].GetPath()) - if err == nil { - outputPath, _ := filepath.Split(pluginPath) - summaryPath = filepath.Join(outputPath, summaryPath) - reportPath = filepath.Join(outputPath, reportPath) - } - // save summary if r.saveTests { - dir, _ := filepath.Split(summaryPath) - err := builtin.EnsureFolderExists(dir) - if err != nil { - return err - } - err = builtin.Dump2JSON(s, fmt.Sprintf(summaryPath, s.Time.StartAt.Unix())) + err := s.genSummary() if err != nil { return err } @@ -229,11 +213,12 @@ func (r *HRPRunner) newCaseRunner(testcase *TestCase) (*testCaseRunner, error) { } // init parser plugin - plugin, err := initPlugin(testcase.Config.Path, r.pluginLogOn) + plugin, pluginDir, err := initPlugin(testcase.Config.Path, r.pluginLogOn) if err != nil { return nil, errors.Wrap(err, "init plugin failed") } runner.parser.plugin = plugin + runner.rootDir = pluginDir // parse testcase config if err := runner.parseConfig(); err != nil { @@ -249,6 +234,7 @@ type testCaseRunner struct { parser *Parser parsedConfig *TConfig parametersIterator *ParametersIterator + rootDir string // project root dir } // parseConfig parses testcase config, stores to parsedConfig. diff --git a/hrp/summary.go b/hrp/summary.go index 569c79a6..42dc37d7 100644 --- a/hrp/summary.go +++ b/hrp/summary.go @@ -38,6 +38,7 @@ type Summary struct { Time *TestCaseTime `json:"time" yaml:"time"` Platform *Platform `json:"platform" yaml:"platform"` Details []*TestCaseSummary `json:"details" yaml:"details"` + rootDir string } func (s *Summary) appendCaseSummary(caseSummary *TestCaseSummary) { @@ -53,15 +54,24 @@ func (s *Summary) appendCaseSummary(caseSummary *TestCaseSummary) { s.Stat.TestSteps.Failures += caseSummary.Stat.Failures s.Details = append(s.Details, caseSummary) s.Success = s.Success && caseSummary.Success + + // specify output reports dir + if len(s.Details) == 1 { + s.rootDir = caseSummary.RootDir + } else if s.rootDir != caseSummary.RootDir { + // if multiple testcases have different root path, use current working dir + s.rootDir, _ = os.Getwd() + } } func (s *Summary) genHTMLReport() error { - dir, _ := filepath.Split(reportPath) - err := builtin.EnsureFolderExists(dir) + reportsDir := filepath.Join(s.rootDir, resultsDir) + err := builtin.EnsureFolderExists(reportsDir) if err != nil { return err } - reportPath := fmt.Sprintf(reportPath, s.Time.StartAt.Unix()) + + reportPath := filepath.Join(reportsDir, fmt.Sprintf("report-%v.html", s.Time.StartAt.Unix())) file, err := os.OpenFile(reportPath, os.O_WRONLY|os.O_CREATE, 0666) if err != nil { log.Error().Err(err).Msg("open file failed") @@ -84,13 +94,25 @@ func (s *Summary) genHTMLReport() error { return err } +func (s *Summary) genSummary() error { + reportsDir := filepath.Join(s.rootDir, resultsDir) + err := builtin.EnsureFolderExists(reportsDir) + if err != nil { + return err + } + + summaryPath := filepath.Join(reportsDir, fmt.Sprintf("summary-%v.json", s.Time.StartAt.Unix())) + err = builtin.Dump2JSON(s, summaryPath) + if err != nil { + return err + } + return nil +} + //go:embed internal/scaffold/templates/report/template.html var reportTemplate string -var ( - reportPath = "reports/report-%v.html" - summaryPath = "reports/summary-%v.json" -) +const resultsDir = "reports" type Stat struct { TestCases TestCaseStat `json:"testcases" yaml:"test_cases"` @@ -130,6 +152,7 @@ type TestCaseSummary struct { InOut *TestCaseInOut `json:"in_out" yaml:"in_out"` Log string `json:"log,omitempty" yaml:"log,omitempty"` // TODO Records []*StepResult `json:"records" yaml:"records"` + RootDir string `json:"root_dir" yaml:"root_dir"` } type TestCaseInOut struct {