diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 3c7931d9..5c522f56 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -7,7 +7,7 @@ **go version** - feat: add `--profile` flag for har2case to support overwrite headers/cookies with specified yaml/json profile file -- feat: support run testcases in specified folder path +- feat: support run testcases in specified folder path, including testcases in sub folders - change: integrate [sentry sdk][sentry sdk] for panic reporting and analysis - change: lock funplugin version when creating scaffold project - fix: call referenced api/testcase with relative path diff --git a/hrp/runner.go b/hrp/runner.go index b0e50c7c..4219e88e 100644 --- a/hrp/runner.go +++ b/hrp/runner.go @@ -10,7 +10,7 @@ import ( "fmt" "html/template" "io" - "io/ioutil" + "io/fs" "net" "net/http" "net/http/httputil" @@ -219,40 +219,42 @@ func loadTestCases(iTestCases ...ITestCase) ([]*TestCase, error) { } // iTestCase should be a TestCasePath, file path or folder path - testCasePath, ok := iTestCase.(*TestCasePath) + tcPath, ok := iTestCase.(*TestCasePath) if !ok { return nil, errors.New("invalid iTestCase type") } - casePaths := make([]*TestCasePath, 0) - casePath := iTestCase.GetPath() - if builtin.IsFolderPathExists(casePath) { - // folder path - files, err := ioutil.ReadDir(casePath) - if err != nil { - return nil, errors.Wrap(err, "read dir failed") + casePath := tcPath.GetPath() + err := fs.WalkDir(os.DirFS(casePath), ".", func(path string, dir fs.DirEntry, e error) error { + if dir == nil { + // casePath is a file other than a dir + path = casePath + } else if dir.IsDir() && path != "." && strings.HasPrefix(path, ".") { + // skip hidden folders + return fs.SkipDir + } else { + // casePath is a dir + path = filepath.Join(casePath, path) } - for _, f := range files { - ext := filepath.Ext(f.Name()) - if ext != ".yml" && ext != ".yaml" && ext != ".json" { - // ignore non-testcase files - continue - } - path := TestCasePath(filepath.Join(casePath, f.Name())) - casePaths = append(casePaths, &path) - } - } else { - // file path - casePaths = append(casePaths, testCasePath) - } - for _, path := range casePaths { - tc, err := path.ToTestCase() + // ignore non-testcase files + ext := filepath.Ext(path) + if ext != ".yml" && ext != ".yaml" && ext != ".json" { + return nil + } + + // filtered testcases + testCasePath := TestCasePath(path) + tc, err := testCasePath.ToTestCase() if err != nil { - log.Error().Err(err).Str("path", path.GetPath()).Msg("load testcase failed") - return nil, errors.Wrap(err, "load testcase failed") + log.Error().Err(err).Str("path", path).Msg("load testcase failed") + return errors.Wrap(err, "load testcase failed") } testCases = append(testCases, tc) + return nil + }) + if err != nil { + return nil, errors.Wrap(err, "read dir failed") } } diff --git a/hrp/runner_test.go b/hrp/runner_test.go index 85216814..98060d7a 100644 --- a/hrp/runner_test.go +++ b/hrp/runner_test.go @@ -296,13 +296,23 @@ func TestLoadTestCases(t *testing.T) { t.Fail() } + // load test cases from folder path, including sub folders + tc = TestCasePath("../examples/demo-with-py-plugin/") + testCases, err = loadTestCases(&tc) + if !assert.Nil(t, err) { + t.Fail() + } + if !assert.Equal(t, len(testCases), 3) { + t.Fail() + } + // load test cases from single file path tc = demoTestCaseWithPluginJSONPath testCases, err = loadTestCases(&tc) if !assert.Nil(t, err) { t.Fail() } - if !assert.Equal(t, len(testCases), 1) { + if !assert.Equal(t, 1, len(testCases)) { t.Fail() } diff --git a/httprunner/utils.py b/httprunner/utils.py index 27b0b876..41895e49 100644 --- a/httprunner/utils.py +++ b/httprunner/utils.py @@ -33,7 +33,7 @@ class GAClient(object): def __init__(self, tracking_id: Text): self.http_client = requests.Session() - self.label = str(__version__) + self.label = f"v{__version__}" self.common_params = { 'v': self.version, 'tid': tracking_id, # Tracking ID / Property ID, XX-XXXXXXX-X