mirror of
https://github.com/httprunner/httprunner.git
synced 2026-07-09 06:23:52 +08:00
feat: add --output command in hrp build
This commit is contained in:
@@ -12,15 +12,19 @@ var buildCmd = &cobra.Command{
|
|||||||
Long: `build python/go plugin for testing`,
|
Long: `build python/go plugin for testing`,
|
||||||
Example: ` $ hrp build plugin/debugtalk.go
|
Example: ` $ hrp build plugin/debugtalk.go
|
||||||
$ hrp build plugin/debugtalk.py`,
|
$ hrp build plugin/debugtalk.py`,
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
setLogLevel(logLevel)
|
setLogLevel(logLevel)
|
||||||
},
|
},
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return build.Run(args)
|
return build.Run(args[0], output)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var output string
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(buildCmd)
|
rootCmd.AddCommand(buildCmd)
|
||||||
|
|
||||||
|
buildCmd.Flags().StringVarP(&output, "output", "o", "", "funplugin product output path, default: cwd")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
func SumTwoInt(a, b int) int {
|
func SumTwoInt(a, b int) int {
|
||||||
return a + b
|
return a + b
|
||||||
}
|
}
|
||||||
@@ -38,3 +40,7 @@ func SetupHookExample(args string) string {
|
|||||||
func TeardownHookExample(args string) string {
|
func TeardownHookExample(args string) string {
|
||||||
return fmt.Sprintf("step name: %v, teardown...", args)
|
return fmt.Sprintf("step name: %v, teardown...", args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
_, _ = os.Getwd()
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,8 +23,9 @@ const (
|
|||||||
funppy = `import funppy`
|
funppy = `import funppy`
|
||||||
fungo = `"github.com/httprunner/funplugin/fungo"`
|
fungo = `"github.com/httprunner/funplugin/fungo"`
|
||||||
regexPythonFunctionName = `def ([a-zA-Z_]\w*)\(.*\)`
|
regexPythonFunctionName = `def ([a-zA-Z_]\w*)\(.*\)`
|
||||||
regexGoImport = `import\s*\(\n([\s\S]*)\n\)`
|
regexGoImports = `import\s*\(\n([\s\S]*)\n\)`
|
||||||
regexGoFunctionName = `func ([a-zA-Z_]\w*)\(.*\)`
|
regexGoImport = `import\s*(\"[\s\S]*\")\n`
|
||||||
|
regexGoFunctionName = `func ([A-Z][a-zA-Z_]\w*)\(.*\)`
|
||||||
regexGoFunctionContent = `func [\s\S]*?\n}\n`
|
regexGoFunctionContent = `func [\s\S]*?\n}\n`
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -35,17 +36,17 @@ var pyTemplate string
|
|||||||
var goTemplate string
|
var goTemplate string
|
||||||
|
|
||||||
type TemplateContent struct {
|
type TemplateContent struct {
|
||||||
Fun string // funplugin package
|
Fun string // funplugin package
|
||||||
Regexps *Regexps // match import/function
|
Regexps *Regexps // match import/function
|
||||||
Imports []string // python/go import
|
Imports []string // python/go import
|
||||||
FromImports []string // python from...import...
|
FromImports []string // python from...import...
|
||||||
Functions []string // python/go function
|
Functions []string // python/go function
|
||||||
FunctionNames []string // function name set by user
|
FunctionNames []string // function name set by user
|
||||||
FunctionSnakeNames []string // function snake name converts by function name for registering plugin
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Regexps struct {
|
type Regexps struct {
|
||||||
Import *regexp.Regexp
|
Import *regexp.Regexp
|
||||||
|
Imports *regexp.Regexp
|
||||||
FunctionName *regexp.Regexp
|
FunctionName *regexp.Regexp
|
||||||
FunctionContent *regexp.Regexp // including function define and body
|
FunctionContent *regexp.Regexp // including function define and body
|
||||||
}
|
}
|
||||||
@@ -65,11 +66,14 @@ func (t *TemplateContent) parseGoContent(path string) error {
|
|||||||
if len(importSlice) != 0 {
|
if len(importSlice) != 0 {
|
||||||
imports := strings.Replace(importSlice[0][1], "\t", "", -1)
|
imports := strings.Replace(importSlice[0][1], "\t", "", -1)
|
||||||
for _, elem := range strings.Split(imports, "\n") {
|
for _, elem := range strings.Split(imports, "\n") {
|
||||||
t.Imports = append(t.Imports, elem)
|
t.Imports = append(t.Imports, strings.TrimSpace(elem))
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
if strings.Contains(originalContent, "\nimport ") {
|
// parse import
|
||||||
return errors.New(`import style error, expected import ( ... )`)
|
importSlice = t.Regexps.Imports.FindAllStringSubmatch(originalContent, -1)
|
||||||
|
if len(importSlice) != 0 {
|
||||||
|
for _, elem := range importSlice {
|
||||||
|
t.Imports = append(t.Imports, strings.TrimSpace(elem[1]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// import fungo package
|
// import fungo package
|
||||||
@@ -85,7 +89,6 @@ func (t *TemplateContent) parseGoContent(path string) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
t.FunctionNames = append(t.FunctionNames, name)
|
t.FunctionNames = append(t.FunctionNames, name)
|
||||||
t.FunctionSnakeNames = append(t.FunctionSnakeNames, convertSnakeName(name))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse function content
|
// parse function content
|
||||||
@@ -135,7 +138,6 @@ func (t *TemplateContent) parsePyContent(path string) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
t.FunctionNames = append(t.FunctionNames, functionNameSlice[0][1])
|
t.FunctionNames = append(t.FunctionNames, functionNameSlice[0][1])
|
||||||
t.FunctionSnakeNames = append(t.FunctionSnakeNames, convertSnakeName(functionNameSlice[0][1]))
|
|
||||||
}
|
}
|
||||||
content += line + "\n"
|
content += line + "\n"
|
||||||
}
|
}
|
||||||
@@ -174,16 +176,16 @@ func (t *TemplateContent) genDebugTalk(path string, templ string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// buildGo builds debugtalk.go to debugtalk.bin
|
// buildGo builds debugtalk.go to debugtalk.bin
|
||||||
func buildGo(path string) error {
|
func buildGo(path string, output string) error {
|
||||||
templateContent := &TemplateContent{
|
templateContent := &TemplateContent{
|
||||||
Fun: fungo,
|
Fun: fungo,
|
||||||
Regexps: &Regexps{
|
Regexps: &Regexps{
|
||||||
Import: regexp.MustCompile(regexGoImport),
|
Import: regexp.MustCompile(regexGoImport),
|
||||||
|
Imports: regexp.MustCompile(regexGoImports),
|
||||||
FunctionName: regexp.MustCompile(regexGoFunctionName),
|
FunctionName: regexp.MustCompile(regexGoFunctionName),
|
||||||
FunctionContent: regexp.MustCompile(regexGoFunctionContent),
|
FunctionContent: regexp.MustCompile(regexGoFunctionContent),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
dir, _ := filepath.Split(path)
|
|
||||||
|
|
||||||
// create temp dir for building
|
// create temp dir for building
|
||||||
tempDir, err := ioutil.TempDir("", "hrp_build")
|
tempDir, err := ioutil.TempDir("", "hrp_build")
|
||||||
@@ -224,7 +226,13 @@ func buildGo(path string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
outputPath, err := filepath.Abs(filepath.Join(dir, "../debugtalk.bin"))
|
if output == "" {
|
||||||
|
dir, _ := os.Getwd()
|
||||||
|
output = filepath.Join(dir, "debugtalk.bin")
|
||||||
|
} else if builtin.IsFolderPathExists(output) {
|
||||||
|
output = filepath.Join(output, "debugtalk.bin")
|
||||||
|
}
|
||||||
|
outputPath, err := filepath.Abs(output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -238,7 +246,7 @@ func buildGo(path string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// buildPy completes funppy information in debugtalk.py
|
// buildPy completes funppy information in debugtalk.py
|
||||||
func buildPy(path string) error {
|
func buildPy(path string, output string) error {
|
||||||
templateContent := &TemplateContent{
|
templateContent := &TemplateContent{
|
||||||
Fun: funppy,
|
Fun: funppy,
|
||||||
Regexps: &Regexps{
|
Regexps: &Regexps{
|
||||||
@@ -251,8 +259,13 @@ func buildPy(path string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// generate debugtalk.py
|
// generate debugtalk.py
|
||||||
dir, _ := filepath.Split(path)
|
if output == "" {
|
||||||
err = templateContent.genDebugTalk(filepath.Join(dir, "../debugtalk.py"), pyTemplate)
|
dir, _ := os.Getwd()
|
||||||
|
output = filepath.Join(dir, "debugtalk.py")
|
||||||
|
} else if builtin.IsFolderPathExists(output) {
|
||||||
|
output = filepath.Join(output, "debugtalk.py")
|
||||||
|
}
|
||||||
|
err = templateContent.genDebugTalk(output, pyTemplate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -266,39 +279,19 @@ func buildPy(path string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Run(args []string) (err error) {
|
func Run(arg string, output string) (err error) {
|
||||||
for _, arg := range args {
|
ext := filepath.Ext(arg)
|
||||||
ext := filepath.Ext(arg)
|
switch ext {
|
||||||
switch ext {
|
case ".py":
|
||||||
case ".py":
|
err = buildPy(arg, output)
|
||||||
err = buildPy(arg)
|
case ".go":
|
||||||
case ".go":
|
err = buildGo(arg, output)
|
||||||
err = buildGo(arg)
|
default:
|
||||||
default:
|
return errors.New("type error, expected .py or .go")
|
||||||
return errors.New("type error, expected .py or .go")
|
}
|
||||||
}
|
if err != nil {
|
||||||
if err != nil {
|
log.Error().Err(err).Msg(fmt.Sprintf("failed to build %s", arg))
|
||||||
log.Error().Err(err).Msg(fmt.Sprintf("failed to build %s", arg))
|
os.Exit(1)
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// convertSnakeName converts name to snake name
|
|
||||||
func convertSnakeName(originalName string) string {
|
|
||||||
snakeName := make([]byte, 0, len(originalName)*2)
|
|
||||||
flag := false
|
|
||||||
num := len(originalName)
|
|
||||||
for i := 0; i < num; i++ {
|
|
||||||
ch := originalName[i]
|
|
||||||
if i > 0 && ch >= 'A' && ch <= 'Z' && flag {
|
|
||||||
snakeName = append(snakeName, '_')
|
|
||||||
}
|
|
||||||
if ch != '_' {
|
|
||||||
flag = true
|
|
||||||
}
|
|
||||||
snakeName = append(snakeName, ch)
|
|
||||||
}
|
|
||||||
return strings.ToLower(string(snakeName))
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -7,38 +7,23 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestRun(t *testing.T) {
|
func TestRun(t *testing.T) {
|
||||||
err := Run([]string{"examples/debugtalk_no_funppy.py", "examples/debugtalk_no_fungo.go"})
|
err := Run("examples/debugtalk_no_funppy.py", "")
|
||||||
|
if !assert.Nil(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
|
||||||
|
err = Run("examples/debugtalk_no_fungo.go", "")
|
||||||
|
if !assert.Nil(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
|
||||||
|
err = Run("examples/debugtalk_no_funppy.py", "./debugtalk_gen.py")
|
||||||
|
if !assert.Nil(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
|
||||||
|
err = Run("examples/debugtalk_no_fungo.go", "./debugtalk_gen.bin")
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConvertSnakeName(t *testing.T) {
|
|
||||||
testData := []struct {
|
|
||||||
expectedValue string
|
|
||||||
originalValue string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
expectedValue: "test_name",
|
|
||||||
originalValue: "testName",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
expectedValue: "test",
|
|
||||||
originalValue: "test",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
expectedValue: "test_name",
|
|
||||||
originalValue: "TestName",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
expectedValue: "test_name",
|
|
||||||
originalValue: "test_name",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, data := range testData {
|
|
||||||
name := convertSnakeName(data.originalValue)
|
|
||||||
if !assert.Equal(t, data.expectedValue, name) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import (
|
|||||||
{{ $function }}
|
{{ $function }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
func main() {
|
func main() {
|
||||||
{{- range $idx, $name := .FunctionNames }}
|
{{- range $idx, $functionName := .FunctionNames }}
|
||||||
fungo.Register("{{ index $.FunctionSnakeNames $idx }}", {{ $name }})
|
fungo.Register("{{ $functionName }}", {{ $functionName }})
|
||||||
{{- end }}
|
{{- end }}
|
||||||
fungo.Serve()
|
fungo.Serve()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
{{- range $mainRegSnake := .FunctionSnakeNames }}
|
{{- range $functionName := .FunctionNames }}
|
||||||
funppy.register("{{ $mainRegSnake }}", {{ $mainRegSnake }})
|
funppy.register("{{ $functionName }}", {{ $functionName }})
|
||||||
{{- end }}
|
{{- end }}
|
||||||
funppy.serve()
|
funppy.serve()
|
||||||
|
|||||||
Reference in New Issue
Block a user