refactor: move LoadFile to hrp/loader

This commit is contained in:
lilong.129
2024-08-19 22:42:53 +08:00
parent a9b864dc96
commit 89d0d4bb96
13 changed files with 106 additions and 109 deletions
+1 -1
View File
@@ -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
-64
View File
@@ -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)
+70
View File
@@ -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
}
+26
View File
@@ -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()
}
}
+1 -2
View File
@@ -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")
} }
+1 -2
View File
@@ -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")
} }
+1 -2
View File
@@ -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")
} }
+1 -2
View File
@@ -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")
} }
+1 -2
View File
@@ -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")
} }
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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")
} }
-28
View 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