mirror of
https://github.com/httprunner/httprunner.git
synced 2026-09-08 00:47:36 +08:00
refactor: move LoadFile to hrp/loader
This commit is contained in:
@@ -30,6 +30,7 @@ require (
|
|||||||
golang.org/x/oauth2 v0.8.0
|
golang.org/x/oauth2 v0.8.0
|
||||||
google.golang.org/grpc v1.57.0
|
google.golang.org/grpc v1.57.0
|
||||||
google.golang.org/protobuf v1.32.0
|
google.golang.org/protobuf v1.32.0
|
||||||
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
howett.net/plist v1.0.0
|
howett.net/plist v1.0.0
|
||||||
)
|
)
|
||||||
@@ -77,7 +78,6 @@ require (
|
|||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
google.golang.org/appengine v1.6.8 // indirect
|
google.golang.org/appengine v1.6.8 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// replace github.com/httprunner/funplugin => ../funplugin
|
// replace github.com/httprunner/funplugin => ../funplugin
|
||||||
|
|||||||
@@ -235,70 +235,6 @@ func InterfaceType(raw interface{}) string {
|
|||||||
return reflect.TypeOf(raw).String()
|
return reflect.TypeOf(raw).String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadFile loads file content with file extension and assigns to structObj
|
|
||||||
func LoadFile(path string, structObj interface{}) (err error) {
|
|
||||||
log.Info().Str("path", path).Msg("load file")
|
|
||||||
file, err := ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "read file failed")
|
|
||||||
}
|
|
||||||
// remove BOM at the beginning of file
|
|
||||||
file = bytes.TrimLeft(file, "\xef\xbb\xbf")
|
|
||||||
ext := filepath.Ext(path)
|
|
||||||
switch ext {
|
|
||||||
case ".json", ".har":
|
|
||||||
decoder := json.NewDecoder(bytes.NewReader(file))
|
|
||||||
decoder.UseNumber()
|
|
||||||
err = decoder.Decode(structObj)
|
|
||||||
if err != nil {
|
|
||||||
err = errors.Wrap(code.LoadJSONError, err.Error())
|
|
||||||
}
|
|
||||||
case ".yaml", ".yml":
|
|
||||||
err = yaml.Unmarshal(file, structObj)
|
|
||||||
if err != nil {
|
|
||||||
err = errors.Wrap(code.LoadYAMLError, err.Error())
|
|
||||||
}
|
|
||||||
case ".env":
|
|
||||||
err = parseEnvContent(file, structObj)
|
|
||||||
if err != nil {
|
|
||||||
err = errors.Wrap(code.LoadEnvError, err.Error())
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
err = code.UnsupportedFileExtension
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseEnvContent(file []byte, obj interface{}) error {
|
|
||||||
envMap := obj.(map[string]string)
|
|
||||||
lines := strings.Split(string(file), "\n")
|
|
||||||
for _, line := range lines {
|
|
||||||
line = strings.TrimSpace(line)
|
|
||||||
if line == "" || strings.HasPrefix(line, "#") {
|
|
||||||
// empty line or comment line
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var kv []string
|
|
||||||
if strings.Contains(line, "=") {
|
|
||||||
kv = strings.SplitN(line, "=", 2)
|
|
||||||
} else if strings.Contains(line, ":") {
|
|
||||||
kv = strings.SplitN(line, ":", 2)
|
|
||||||
}
|
|
||||||
if len(kv) != 2 {
|
|
||||||
return errors.New(".env format error")
|
|
||||||
}
|
|
||||||
|
|
||||||
key := strings.TrimSpace(kv[0])
|
|
||||||
value := strings.TrimSpace(kv[1])
|
|
||||||
envMap[key] = value
|
|
||||||
|
|
||||||
// set env
|
|
||||||
log.Info().Str("key", key).Msg("set env")
|
|
||||||
os.Setenv(key, value)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadFromCSV(path string) []map[string]interface{} {
|
func loadFromCSV(path string) []map[string]interface{} {
|
||||||
log.Info().Str("path", path).Msg("load csv file")
|
log.Info().Str("path", path).Msg("load csv file")
|
||||||
file, err := ReadFile(path)
|
file, err := ReadFile(path)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package hrp
|
package hrp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -8,6 +9,11 @@ import (
|
|||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
|
"github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
||||||
|
"github.com/httprunner/httprunner/v4/hrp/internal/code"
|
||||||
|
"github.com/httprunner/httprunner/v4/hrp/internal/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
// LoadTestCases load testcases from TestCasePath or TestCase
|
// LoadTestCases load testcases from TestCasePath or TestCase
|
||||||
@@ -63,3 +69,67 @@ func LoadTestCases(tests ...ITestCase) ([]*TestCase, error) {
|
|||||||
log.Info().Int("count", len(testCases)).Msg("load testcases successfully")
|
log.Info().Int("count", len(testCases)).Msg("load testcases successfully")
|
||||||
return testCases, nil
|
return testCases, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadFile loads file content with file extension and assigns to structObj
|
||||||
|
func LoadFile(path string, structObj interface{}) (err error) {
|
||||||
|
log.Info().Str("path", path).Msg("load file")
|
||||||
|
file, err := builtin.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "read file failed")
|
||||||
|
}
|
||||||
|
// remove BOM at the beginning of file
|
||||||
|
file = bytes.TrimLeft(file, "\xef\xbb\xbf")
|
||||||
|
ext := filepath.Ext(path)
|
||||||
|
switch ext {
|
||||||
|
case ".json", ".har":
|
||||||
|
decoder := json.NewDecoder(bytes.NewReader(file))
|
||||||
|
decoder.UseNumber()
|
||||||
|
err = decoder.Decode(structObj)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.Wrap(code.LoadJSONError, err.Error())
|
||||||
|
}
|
||||||
|
case ".yaml", ".yml":
|
||||||
|
err = yaml.Unmarshal(file, structObj)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.Wrap(code.LoadYAMLError, err.Error())
|
||||||
|
}
|
||||||
|
case ".env":
|
||||||
|
err = parseEnvContent(file, structObj)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.Wrap(code.LoadEnvError, err.Error())
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
err = code.UnsupportedFileExtension
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseEnvContent(file []byte, obj interface{}) error {
|
||||||
|
envMap := obj.(map[string]string)
|
||||||
|
lines := strings.Split(string(file), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
if line == "" || strings.HasPrefix(line, "#") {
|
||||||
|
// empty line or comment line
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var kv []string
|
||||||
|
if strings.Contains(line, "=") {
|
||||||
|
kv = strings.SplitN(line, "=", 2)
|
||||||
|
} else if strings.Contains(line, ":") {
|
||||||
|
kv = strings.SplitN(line, ":", 2)
|
||||||
|
}
|
||||||
|
if len(kv) != 2 {
|
||||||
|
return errors.New(".env format error")
|
||||||
|
}
|
||||||
|
|
||||||
|
key := strings.TrimSpace(kv[0])
|
||||||
|
value := strings.TrimSpace(kv[1])
|
||||||
|
envMap[key] = value
|
||||||
|
|
||||||
|
// set env
|
||||||
|
log.Info().Str("key", key).Msg("set env")
|
||||||
|
os.Setenv(key, value)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -49,3 +49,29 @@ func TestLoadTestCases(t *testing.T) {
|
|||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLoadCase(t *testing.T) {
|
||||||
|
tcJSON := &TestCase{}
|
||||||
|
tcYAML := &TestCase{}
|
||||||
|
err := LoadFile(demoTestCaseWithPluginJSONPath, tcJSON)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
err = LoadFile(demoTestCaseWithPluginYAMLPath, tcYAML)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !assert.Equal(t, tcJSON.Config.Name, tcYAML.Config.Name) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, tcJSON.Config.BaseURL, tcYAML.Config.BaseURL) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, tcJSON.Steps[1].Name, tcYAML.Steps[1].Name) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, tcJSON.Steps[1].Request, tcYAML.Steps[1].Request) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import (
|
|||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp"
|
"github.com/httprunner/httprunner/v4/hrp"
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/json"
|
"github.com/httprunner/httprunner/v4/hrp/internal/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -371,7 +370,7 @@ func LoadHARCase(path string) (*hrp.TestCase, error) {
|
|||||||
|
|
||||||
func loadCaseHAR(path string) (*CaseHar, error) {
|
func loadCaseHAR(path string) (*CaseHar, error) {
|
||||||
caseHAR := new(CaseHar)
|
caseHAR := new(CaseHar)
|
||||||
err := builtin.LoadFile(path, caseHAR)
|
err := hrp.LoadFile(path, caseHAR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "load har file failed")
|
return nil, errors.Wrap(err, "load har file failed")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,12 @@ import (
|
|||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp"
|
"github.com/httprunner/httprunner/v4/hrp"
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func LoadJSONCase(path string) (*hrp.TestCase, error) {
|
func LoadJSONCase(path string) (*hrp.TestCase, error) {
|
||||||
log.Info().Str("path", path).Msg("load json case file")
|
log.Info().Str("path", path).Msg("load json case file")
|
||||||
caseJSON := new(hrp.TestCase)
|
caseJSON := new(hrp.TestCase)
|
||||||
err := builtin.LoadFile(path, caseJSON)
|
err := hrp.LoadFile(path, caseJSON)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "load json file failed")
|
return nil, errors.Wrap(err, "load json file failed")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp"
|
"github.com/httprunner/httprunner/v4/hrp"
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/json"
|
"github.com/httprunner/httprunner/v4/hrp/internal/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -125,7 +124,7 @@ func LoadPostmanCase(path string) (*hrp.TestCase, error) {
|
|||||||
|
|
||||||
func loadCasePostman(path string) (*CasePostman, error) {
|
func loadCasePostman(path string) (*CasePostman, error) {
|
||||||
casePostman := new(CasePostman)
|
casePostman := new(CasePostman)
|
||||||
err := builtin.LoadFile(path, casePostman)
|
err := hrp.LoadFile(path, casePostman)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "load postman file failed")
|
return nil, errors.Wrap(err, "load postman file failed")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,12 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp"
|
"github.com/httprunner/httprunner/v4/hrp"
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func LoadSwaggerCase(path string) (*hrp.TestCase, error) {
|
func LoadSwaggerCase(path string) (*hrp.TestCase, error) {
|
||||||
// load swagger file
|
// load swagger file
|
||||||
caseSwagger := new(spec.Swagger)
|
caseSwagger := new(spec.Swagger)
|
||||||
err := builtin.LoadFile(path, caseSwagger)
|
err := hrp.LoadFile(path, caseSwagger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "load swagger file failed")
|
return nil, errors.Wrap(err, "load swagger file failed")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,12 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp"
|
"github.com/httprunner/httprunner/v4/hrp"
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func LoadYAMLCase(path string) (*hrp.TestCase, error) {
|
func LoadYAMLCase(path string) (*hrp.TestCase, error) {
|
||||||
// load yaml case file
|
// load yaml case file
|
||||||
caseJSON := new(hrp.TestCase)
|
caseJSON := new(hrp.TestCase)
|
||||||
err := builtin.LoadFile(path, caseJSON)
|
err := hrp.LoadFile(path, caseJSON)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "load yaml file failed")
|
return nil, errors.Wrap(err, "load yaml file failed")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ func (c *TCaseConverter) genOutputPath(suffix string) string {
|
|||||||
func (c *TCaseConverter) overrideWithProfile(path string) error {
|
func (c *TCaseConverter) overrideWithProfile(path string) error {
|
||||||
log.Info().Str("path", path).Msg("load profile")
|
log.Info().Str("path", path).Msg("load profile")
|
||||||
profile := new(Profile)
|
profile := new(Profile)
|
||||||
err := builtin.LoadFile(path, profile)
|
err := hrp.LoadFile(path, profile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn().Str("path", path).
|
log.Warn().Str("path", path).
|
||||||
Msg("failed to load profile, ignore!")
|
Msg("failed to load profile, ignore!")
|
||||||
|
|||||||
+1
-3
@@ -5,8 +5,6 @@ import (
|
|||||||
|
|
||||||
"github.com/jinzhu/copier"
|
"github.com/jinzhu/copier"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// IAPI represents interface for api,
|
// IAPI represents interface for api,
|
||||||
@@ -46,7 +44,7 @@ func (path *APIPath) GetPath() string {
|
|||||||
func (path *APIPath) ToAPI() (*API, error) {
|
func (path *APIPath) ToAPI() (*API, error) {
|
||||||
api := &API{}
|
api := &API{}
|
||||||
apiPath := path.GetPath()
|
apiPath := path.GetPath()
|
||||||
err := builtin.LoadFile(apiPath, api)
|
err := LoadFile(apiPath, api)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -27,7 +27,7 @@ type TestCasePath string
|
|||||||
func (path *TestCasePath) GetTestCase() (*TestCase, error) {
|
func (path *TestCasePath) GetTestCase() (*TestCase, error) {
|
||||||
tc := &TestCase{}
|
tc := &TestCase{}
|
||||||
casePath := string(*path)
|
casePath := string(*path)
|
||||||
err := builtin.LoadFile(casePath, tc)
|
err := LoadFile(casePath, tc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -137,7 +137,7 @@ func (tc *TestCase) loadISteps() (*TestCase, error) {
|
|||||||
dotEnvPath := filepath.Join(projectRootDir, ".env")
|
dotEnvPath := filepath.Join(projectRootDir, ".env")
|
||||||
if builtin.IsFilePathExists(dotEnvPath) {
|
if builtin.IsFilePathExists(dotEnvPath) {
|
||||||
envVars := make(map[string]string)
|
envVars := make(map[string]string)
|
||||||
err = builtin.LoadFile(dotEnvPath, envVars)
|
err = LoadFile(dotEnvPath, envVars)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to load .env file")
|
return nil, errors.Wrap(err, "failed to load .env file")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -175,32 +173,6 @@ func TestGenDemoTestCase(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoadCase(t *testing.T) {
|
|
||||||
tcJSON := &TestCase{}
|
|
||||||
tcYAML := &TestCase{}
|
|
||||||
err := builtin.LoadFile(demoTestCaseWithPluginJSONPath, tcJSON)
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
err = builtin.LoadFile(demoTestCaseWithPluginYAMLPath, tcYAML)
|
|
||||||
if !assert.NoError(t, err) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
|
|
||||||
if !assert.Equal(t, tcJSON.Config.Name, tcYAML.Config.Name) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
if !assert.Equal(t, tcJSON.Config.BaseURL, tcYAML.Config.BaseURL) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
if !assert.Equal(t, tcJSON.Steps[1].Name, tcYAML.Steps[1].Name) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
if !assert.Equal(t, tcJSON.Steps[1].Request, tcYAML.Steps[1].Request) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConvertCheckExpr(t *testing.T) {
|
func TestConvertCheckExpr(t *testing.T) {
|
||||||
exprs := []struct {
|
exprs := []struct {
|
||||||
before string
|
before string
|
||||||
|
|||||||
Reference in New Issue
Block a user