mirror of
https://github.com/httprunner/httprunner.git
synced 2026-09-07 16:40:50 +08:00
refactor: convert postman case
This commit is contained in:
+67
-47
@@ -1,7 +1,6 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
@@ -13,65 +12,86 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var convertCmd = &cobra.Command{
|
var convertCmd = &cobra.Command{
|
||||||
Use: "convert $path...",
|
Use: "convert $path...",
|
||||||
Short: "convert to JSON/YAML/gotest/pytest testcases",
|
Short: "convert multiple source format to HttpRunner JSON/YAML/gotest/pytest cases",
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
SilenceUsage: false,
|
||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
setLogLevel(logLevel)
|
setLogLevel(logLevel)
|
||||||
},
|
},
|
||||||
RunE: convertRun,
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
caseConverter := convert.NewConverter(outputDir, profilePath)
|
||||||
|
|
||||||
|
var fromType convert.FromType
|
||||||
|
if fromYAMLFlag {
|
||||||
|
fromType = convert.FromTypeYAML
|
||||||
|
} else if fromPostmanFlag {
|
||||||
|
fromType = convert.FromTypePostman
|
||||||
|
} else if fromHARFlag {
|
||||||
|
fromType = convert.FromTypeHAR
|
||||||
|
} else {
|
||||||
|
fromType = convert.FromTypeJSON
|
||||||
|
log.Info().Str("fromType", fromType.String()).Msg("set default")
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputType convert.OutputType
|
||||||
|
if toYAMLFlag {
|
||||||
|
outputType = convert.OutputTypeYAML
|
||||||
|
} else if toPyTestFlag {
|
||||||
|
packages := []string{
|
||||||
|
fmt.Sprintf("httprunner==%s", version.HttpRunnerMinimumVersion),
|
||||||
|
}
|
||||||
|
_, err := myexec.EnsurePython3Venv(venv, packages...)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("python3 venv is not ready")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
outputType = convert.OutputTypePyTest
|
||||||
|
} else {
|
||||||
|
outputType = convert.OutputTypeJSON
|
||||||
|
log.Info().Str("outputType", outputType.String()).Msg("set default")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, arg := range args {
|
||||||
|
if err := caseConverter.Convert(arg, fromType, outputType); err != nil {
|
||||||
|
log.Error().Err(err).Str("path", arg).
|
||||||
|
Str("outputType", outputType.String()).
|
||||||
|
Msg("convert case failed")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
outputDir string
|
||||||
|
profilePath string
|
||||||
|
|
||||||
|
fromJSONFlag bool
|
||||||
|
fromYAMLFlag bool
|
||||||
|
fromPostmanFlag bool
|
||||||
|
fromHARFlag bool
|
||||||
|
|
||||||
toJSONFlag bool
|
toJSONFlag bool
|
||||||
toYAMLFlag bool
|
toYAMLFlag bool
|
||||||
toGoTestFlag bool
|
|
||||||
toPyTestFlag bool
|
toPyTestFlag bool
|
||||||
outputDir string
|
|
||||||
profilePath string
|
|
||||||
|
|
||||||
outputType convert.OutputType
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(convertCmd)
|
rootCmd.AddCommand(convertCmd)
|
||||||
|
|
||||||
|
convertCmd.Flags().BoolVar(&fromJSONFlag, "from-json", true, "load from json case format")
|
||||||
|
convertCmd.Flags().BoolVar(&fromYAMLFlag, "from-yaml", false, "load from yaml case format")
|
||||||
|
convertCmd.Flags().BoolVar(&fromHARFlag, "from-har", false, "load from HAR format")
|
||||||
|
convertCmd.Flags().BoolVar(&fromPostmanFlag, "from-postman", false, "load from postman format")
|
||||||
|
|
||||||
|
convertCmd.Flags().BoolVar(&toJSONFlag, "to-json", true, "convert to JSON case scripts")
|
||||||
|
convertCmd.Flags().BoolVar(&toYAMLFlag, "to-yaml", false, "convert to YAML case scripts")
|
||||||
convertCmd.Flags().BoolVar(&toPyTestFlag, "to-pytest", false, "convert to pytest scripts")
|
convertCmd.Flags().BoolVar(&toPyTestFlag, "to-pytest", false, "convert to pytest scripts")
|
||||||
convertCmd.Flags().BoolVar(&toGoTestFlag, "to-gotest", false, "convert to gotest scripts (TODO)")
|
|
||||||
convertCmd.Flags().BoolVar(&toJSONFlag, "to-json", false, "convert to JSON scripts (default)")
|
convertCmd.Flags().StringVarP(&outputDir, "output-dir", "d", "", "specify output directory")
|
||||||
convertCmd.Flags().BoolVar(&toYAMLFlag, "to-yaml", false, "convert to YAML scripts")
|
|
||||||
convertCmd.Flags().StringVarP(&outputDir, "output-dir", "d", "", "specify output directory, default to the same dir with har file")
|
|
||||||
convertCmd.Flags().StringVarP(&profilePath, "profile", "p", "", "specify profile path to override headers and cookies")
|
convertCmd.Flags().StringVarP(&profilePath, "profile", "p", "", "specify profile path to override headers and cookies")
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertRun(cmd *cobra.Command, args []string) error {
|
|
||||||
var flagCount int
|
|
||||||
if toJSONFlag {
|
|
||||||
flagCount++
|
|
||||||
}
|
|
||||||
if toYAMLFlag {
|
|
||||||
flagCount++
|
|
||||||
outputType = convert.OutputTypeYAML
|
|
||||||
}
|
|
||||||
if toGoTestFlag {
|
|
||||||
flagCount++
|
|
||||||
outputType = convert.OutputTypeGoTest
|
|
||||||
}
|
|
||||||
if toPyTestFlag {
|
|
||||||
flagCount++
|
|
||||||
outputType = convert.OutputTypePyTest
|
|
||||||
|
|
||||||
packages := []string{
|
|
||||||
fmt.Sprintf("httprunner==%s", version.HttpRunnerMinimumVersion),
|
|
||||||
}
|
|
||||||
_, err := myexec.EnsurePython3Venv(venv, packages...)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Msg("python3 venv is not ready")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if flagCount > 1 {
|
|
||||||
return errors.New("please specify at most one conversion flag")
|
|
||||||
}
|
|
||||||
convert.Run(outputType, outputDir, profilePath, args)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,98 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp"
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/env"
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/pkg/boomer"
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/pkg/convert"
|
|
||||||
)
|
|
||||||
|
|
||||||
var runCurlCmd = &cobra.Command{
|
|
||||||
Use: "curl URLs",
|
|
||||||
Short: "run API test with curl command",
|
|
||||||
Args: cobra.MinimumNArgs(1),
|
|
||||||
DisableFlagParsing: true,
|
|
||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
|
||||||
setLogLevel(logLevel)
|
|
||||||
},
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
runner := makeHRPRunner()
|
|
||||||
return runner.Run(makeCurlTestCase(args))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var boomCurlCmd = &cobra.Command{
|
|
||||||
Use: "curl URLs",
|
|
||||||
Short: "run load test with curl command",
|
|
||||||
Args: cobra.MinimumNArgs(1),
|
|
||||||
DisableFlagParsing: true,
|
|
||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
|
||||||
boomer.SetUlimit(10240)
|
|
||||||
if !strings.EqualFold(logLevel, "DEBUG") {
|
|
||||||
logLevel = "WARN" // disable info logs for load testing
|
|
||||||
}
|
|
||||||
setLogLevel(logLevel)
|
|
||||||
},
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
boomer, err := makeHRPBoomer()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
boomer.Run(makeCurlTestCase(args))
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var convertCurlCmd = &cobra.Command{
|
|
||||||
Use: "curl URLs",
|
|
||||||
Short: "convert curl command to httprunner testcase",
|
|
||||||
Args: cobra.MinimumNArgs(1),
|
|
||||||
DisableFlagParsing: true,
|
|
||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
|
||||||
setLogLevel(logLevel)
|
|
||||||
},
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
curlCommand := makeCurlCommand(args)
|
|
||||||
return convertRun(cmd, []string{curlCommand})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
runCmd.AddCommand(runCurlCmd)
|
|
||||||
boomCmd.AddCommand(boomCurlCmd)
|
|
||||||
convertCmd.AddCommand(convertCurlCmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeCurlTestCase(args []string) *hrp.TestCase {
|
|
||||||
curlCommand := makeCurlCommand(args)
|
|
||||||
tCase, err := convert.LoadSingleCurlCase(curlCommand)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Msg("convert curl command failed")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
testCase, err := tCase.ToTestCase(env.RootDir)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Msg("convert testcase to failed")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
return testCase
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeCurlCommand(args []string) string {
|
|
||||||
for i := 0; i < len(args); i++ {
|
|
||||||
if !strings.HasPrefix(args[i], "-") {
|
|
||||||
args[i] = fmt.Sprintf("\"%s\"", args[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var curlCmd []string
|
|
||||||
curlCmd = append(curlCmd, "curl")
|
|
||||||
curlCmd = append(curlCmd, args...)
|
|
||||||
return strings.Join(curlCmd, " ")
|
|
||||||
}
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
package hrp
|
||||||
+17
-14
@@ -4,32 +4,36 @@
|
|||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ hrp convert -h
|
$ hrp convert -h
|
||||||
convert to JSON/YAML/gotest/pytest testcases
|
convert multiple source format to HttpRunner JSON/YAML/gotest/pytest cases
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
hrp convert $path... [flags]
|
hrp convert $path... [flags]
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
|
--from-har load from HAR format
|
||||||
|
--from-json load from json case format (default true)
|
||||||
|
--from-postman load from postman format
|
||||||
|
--from-yaml load from yaml case format
|
||||||
-h, --help help for convert
|
-h, --help help for convert
|
||||||
-d, --output-dir string specify output directory, default to the same dir with har file
|
-d, --output-dir string specify output directory
|
||||||
-p, --profile string specify profile path to override headers (except for auto-generated headers) and cookies
|
-p, --profile string specify profile path to override headers and cookies
|
||||||
--to-gotest convert to gotest scripts (TODO)
|
--to-json convert to JSON case scripts (default true)
|
||||||
--to-json convert to JSON scripts (default true)
|
|
||||||
--to-pytest convert to pytest scripts
|
--to-pytest convert to pytest scripts
|
||||||
--to-yaml convert to YAML scripts
|
--to-yaml convert to YAML case scripts
|
||||||
|
|
||||||
Global Flags:
|
Global Flags:
|
||||||
--log-json set log to json format
|
--log-json set log to json format
|
||||||
-l, --log-level string set log level (default "INFO")
|
-l, --log-level string set log level (default "INFO")
|
||||||
|
--venv string specify python3 venv path
|
||||||
```
|
```
|
||||||
|
|
||||||
`hrp convert` 指令用于将 HAR/Postman/JMeter/Swagger 文件或 curl/Apache ab 指令转化为 JSON/YAML/gotest/pytest 形态的测试用例,同时也支持测试用例各个形态之间的相互转化。
|
`hrp convert` 指令用于将 HAR/Postman/JMeter/Swagger 文件或 curl/Apache ab 指令转化为 HttpRunner JSON/YAML/gotest/pytest 形态的测试用例,同时也支持 HttpRunner 测试用例各个形态之间的相互转化。
|
||||||
|
|
||||||
该指令所有选项的详细说明如下:
|
该指令所有选项的详细说明如下:
|
||||||
|
|
||||||
1. `--to-json / --to-yaml / --to-gotest / --to-pytest` 用于将输入转化为对应形态的测试用例,四个选项中最多只能指定一个,如果不指定则默认会将输入转化为 JSON 形态的测试用例
|
- `--to-json / --to-yaml / --to-gotest / --to-pytest` 用于将输入转化为对应形态的 HttpRunner 测试用例,四个选项中最多只能指定一个,如果不指定则默认会将输入转化为 JSON 形态的测试用例
|
||||||
2. `--output-dir` 后接测试用例的期望输出目录的路径,用于将转换生成的测试用例输出到对应的文件夹
|
- `--output-dir` 后接测试用例的期望输出目录的路径,用于将转换生成的测试用例输出到对应的文件夹;默认输出的文件夹为源文件所在的文件夹
|
||||||
3. `--profile` 后接 profile 配置文件的路径,目前支持替换(不存在则会创建)或者覆盖输入的外部脚本/测试用例中的 `Headers` 和 `Cookies` 信息,profile 文件的后缀可以为 `json/yaml/yml`,下面给出两类 profile 配置文件的示例:
|
- `--profile` 后接 profile 配置文件的路径,目前支持替换(不存在则会创建)或者覆盖输入的外部脚本/测试用例中的 `Headers` 和 `Cookies` 信息,profile 文件的后缀可以为 `json/yaml/yml`,下面给出两类 profile 配置文件的示例:
|
||||||
|
|
||||||
- 根据 profile 替换指定的 `Headers` 和 `Cookies` 信息
|
- 根据 profile 替换指定的 `Headers` 和 `Cookies` 信息
|
||||||
|
|
||||||
@@ -52,10 +56,9 @@ cookies:
|
|||||||
|
|
||||||
## 注意事项
|
## 注意事项
|
||||||
|
|
||||||
1. 输出的测试用例文件名格式为 `Postman 工程文件名称(不带拓展名)` + `_test` + `.json/.yaml/.go/.py 后缀`,如果该文件已经存在则会进行覆盖
|
1. 输出的测试用例文件名格式为 `源文件名称(不带拓展名)` + `_test` + `.json/.yaml/.go/.py 后缀`,如果该文件已经存在则会进行覆盖
|
||||||
2. `hrp convert` 可以自动识别输入类型,因此不需要通过选项来手动制定输入类型,如遇到无法识别、不支持或转换失败的情况,则会输出错误日志并跳过,不会影响其他转换过程的正常进行
|
2. 在 profile 文件中,指定 `override` 字段为 `false/true` 可以选择修改模式为替换/覆盖。需要注意的是,如果不指定该字段则 profile 的默认修改模式为替换模式
|
||||||
3. 在 profile 文件中,指定 `override` 字段为 `false/true` 可以选择修改模式为替换/覆盖。需要注意的是,如果不指定该字段则 profile 的默认修改模式为替换模式
|
3. 输入为 JSON/YAML 测试用例时,良好兼容 Golang/Python 双引擎的请求体、断言格式细微差异,输出的 JSON/YAML 则统一采用 Golang 引擎的风格
|
||||||
4. 输入为 JSON/YAML 测试用例时,良好兼容 Golang/Python 双引擎的请求体、断言格式细微差异,输出的 JSON/YAML 则统一采用 Golang 引擎的风格
|
|
||||||
|
|
||||||
|
|
||||||
## 转换流程图
|
## 转换流程图
|
||||||
|
|||||||
@@ -1,278 +0,0 @@
|
|||||||
package convert
|
|
||||||
|
|
||||||
import (
|
|
||||||
_ "embed"
|
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp"
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/env"
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/myexec"
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/sdk"
|
|
||||||
)
|
|
||||||
|
|
||||||
// target testcase format extensions
|
|
||||||
const (
|
|
||||||
suffixJSON = ".json"
|
|
||||||
suffixYAML = ".yaml"
|
|
||||||
suffixGoTest = ".go"
|
|
||||||
suffixPyTest = ".py"
|
|
||||||
)
|
|
||||||
|
|
||||||
type OutputType int
|
|
||||||
|
|
||||||
const (
|
|
||||||
OutputTypeJSON OutputType = iota // default output type: JSON
|
|
||||||
OutputTypeYAML
|
|
||||||
OutputTypeGoTest
|
|
||||||
OutputTypePyTest
|
|
||||||
)
|
|
||||||
|
|
||||||
func (outputType OutputType) String() string {
|
|
||||||
switch outputType {
|
|
||||||
case OutputTypeYAML:
|
|
||||||
return "yaml"
|
|
||||||
case OutputTypeGoTest:
|
|
||||||
return "gotest"
|
|
||||||
case OutputTypePyTest:
|
|
||||||
return "pytest"
|
|
||||||
default:
|
|
||||||
return "json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Profile is used to override or update(create if not existed) original headers and cookies
|
|
||||||
type Profile struct {
|
|
||||||
Override bool `json:"override" yaml:"override"`
|
|
||||||
Headers map[string]string `json:"headers" yaml:"headers"`
|
|
||||||
Cookies map[string]string `json:"cookies" yaml:"cookies"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func Run(outputType OutputType, outputDir, profilePath string, args []string) {
|
|
||||||
// report event
|
|
||||||
sdk.SendEvent(sdk.EventTracking{
|
|
||||||
Category: "ConvertTests",
|
|
||||||
Action: fmt.Sprintf("hrp convert --to-%s", outputType.String()),
|
|
||||||
})
|
|
||||||
|
|
||||||
var outputFiles []string
|
|
||||||
for _, inputSample := range args {
|
|
||||||
// loads source file and convert to TCase format
|
|
||||||
tCase, err := LoadTCase(inputSample)
|
|
||||||
if err != nil {
|
|
||||||
log.Warn().Err(err).Str("input sample", inputSample).Msg("convert input sample failed")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
caseConverter := &TCaseConverter{
|
|
||||||
InputSample: inputSample,
|
|
||||||
OutputDir: outputDir,
|
|
||||||
TCase: tCase,
|
|
||||||
}
|
|
||||||
|
|
||||||
// override TCase with profile
|
|
||||||
if profilePath != "" {
|
|
||||||
caseConverter.overrideWithProfile(profilePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert TCase format to target case format
|
|
||||||
var outputFile string
|
|
||||||
switch outputType {
|
|
||||||
case OutputTypeYAML:
|
|
||||||
outputFile, err = caseConverter.ToYAML()
|
|
||||||
case OutputTypeGoTest:
|
|
||||||
outputFile, err = caseConverter.ToGoTest()
|
|
||||||
case OutputTypePyTest:
|
|
||||||
outputFile, err = caseConverter.ToPyTest()
|
|
||||||
default:
|
|
||||||
outputFile, err = caseConverter.ToJSON()
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).
|
|
||||||
Str("input sample", caseConverter.InputSample).
|
|
||||||
Msg("convert case failed")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
outputFiles = append(outputFiles, outputFile)
|
|
||||||
}
|
|
||||||
log.Info().Strs("output files", outputFiles).Msg("conversion completed")
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadTCase loads source file and convert to TCase type
|
|
||||||
func LoadTCase(inputSample string) (*hrp.TCase, error) {
|
|
||||||
if strings.HasPrefix(inputSample, "curl ") {
|
|
||||||
// 'path' contains curl command
|
|
||||||
curlCase, err := LoadSingleCurlCase(inputSample)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return curlCase, nil
|
|
||||||
}
|
|
||||||
extName := filepath.Ext(inputSample)
|
|
||||||
if extName == "" {
|
|
||||||
return nil, errors.New("file extension is not specified")
|
|
||||||
}
|
|
||||||
switch extName {
|
|
||||||
case ".har":
|
|
||||||
tCase, err := LoadHARCase(inputSample)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return tCase, nil
|
|
||||||
case ".json":
|
|
||||||
// priority: hrp JSON case > postman > swagger
|
|
||||||
// check if hrp JSON case
|
|
||||||
tCase, err := LoadJSONCase(inputSample)
|
|
||||||
if err == nil {
|
|
||||||
return tCase, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if postman format
|
|
||||||
casePostman, err := LoadPostmanCase(inputSample)
|
|
||||||
if err == nil {
|
|
||||||
return casePostman, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if swagger format
|
|
||||||
caseSwagger, err := LoadSwaggerCase(inputSample)
|
|
||||||
if err == nil {
|
|
||||||
return caseSwagger, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errors.New("unexpected JSON format")
|
|
||||||
case ".yaml", ".yml":
|
|
||||||
// priority: hrp YAML case > swagger
|
|
||||||
// check if hrp YAML case
|
|
||||||
tCase, err := NewYAMLCase(inputSample)
|
|
||||||
if err == nil {
|
|
||||||
return tCase, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if swagger format
|
|
||||||
caseSwagger, err := LoadSwaggerCase(inputSample)
|
|
||||||
if err == nil {
|
|
||||||
return caseSwagger, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errors.New("unexpected YAML format")
|
|
||||||
case ".go": // TODO
|
|
||||||
return nil, errors.New("convert gotest is not implemented")
|
|
||||||
case ".py": // TODO
|
|
||||||
return nil, errors.New("convert pytest is not implemented")
|
|
||||||
case ".jmx": // TODO
|
|
||||||
return nil, errors.New("convert JMeter jmx is not implemented")
|
|
||||||
case ".txt":
|
|
||||||
curlCase, err := LoadCurlCase(inputSample)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return curlCase, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("unsupported file type: %v", extName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TCaseConverter holds the common properties of case converter
|
|
||||||
type TCaseConverter struct {
|
|
||||||
InputSample string
|
|
||||||
OutputDir string
|
|
||||||
TCase *hrp.TCase
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TCaseConverter) genOutputPath(suffix string) string {
|
|
||||||
var outFileFullName string
|
|
||||||
if curlCmd := strings.TrimSpace(c.InputSample); strings.HasPrefix(curlCmd, "curl ") {
|
|
||||||
outFileFullName = fmt.Sprintf("curl_%v_test%v", env.StartTimeStr, suffix)
|
|
||||||
if c.OutputDir != "" {
|
|
||||||
return filepath.Join(c.OutputDir, outFileFullName)
|
|
||||||
} else {
|
|
||||||
return filepath.Join(env.RootDir, outFileFullName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
outFileFullName = builtin.GetFileNameWithoutExtension(c.InputSample) + "_test" + suffix
|
|
||||||
if c.OutputDir != "" {
|
|
||||||
return filepath.Join(c.OutputDir, outFileFullName)
|
|
||||||
} else {
|
|
||||||
return filepath.Join(filepath.Dir(c.InputSample), outFileFullName)
|
|
||||||
}
|
|
||||||
// TODO avoid outFileFullName conflict?
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert TCase to pytest case
|
|
||||||
func (c *TCaseConverter) ToPyTest() (string, error) {
|
|
||||||
jsonPath, err := c.ToJSON()
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.Wrap(err, "convert to JSON case failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
args := append([]string{"make"}, jsonPath)
|
|
||||||
err = myexec.ExecPython3Command("httprunner", args...)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return c.genOutputPath(suffixPyTest), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: convert TCase to gotest case
|
|
||||||
func (c *TCaseConverter) ToGoTest() (string, error) {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert TCase to JSON case
|
|
||||||
func (c *TCaseConverter) ToJSON() (string, error) {
|
|
||||||
jsonPath := c.genOutputPath(suffixJSON)
|
|
||||||
err := builtin.Dump2JSON(c.TCase, jsonPath)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return jsonPath, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert TCase to YAML case
|
|
||||||
func (c *TCaseConverter) ToYAML() (string, error) {
|
|
||||||
yamlPath := c.genOutputPath(suffixYAML)
|
|
||||||
err := builtin.Dump2YAML(c.TCase, yamlPath)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return yamlPath, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *TCaseConverter) overrideWithProfile(path string) error {
|
|
||||||
log.Info().Str("path", path).Msg("load profile")
|
|
||||||
profile := new(Profile)
|
|
||||||
err := builtin.LoadFile(path, profile)
|
|
||||||
if err != nil {
|
|
||||||
log.Warn().Str("path", path).
|
|
||||||
Msg("failed to load profile, ignore!")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info().Interface("profile", profile).Msg("override with profile")
|
|
||||||
for _, step := range c.TCase.TestSteps {
|
|
||||||
// override original headers and cookies
|
|
||||||
if profile.Override {
|
|
||||||
step.Request.Headers = make(map[string]string)
|
|
||||||
step.Request.Cookies = make(map[string]string)
|
|
||||||
}
|
|
||||||
// update (create if not existed) original headers and cookies
|
|
||||||
if step.Request.Headers == nil {
|
|
||||||
step.Request.Headers = make(map[string]string)
|
|
||||||
}
|
|
||||||
if step.Request.Cookies == nil {
|
|
||||||
step.Request.Cookies = make(map[string]string)
|
|
||||||
}
|
|
||||||
for k, v := range profile.Headers {
|
|
||||||
step.Request.Headers[k] = v
|
|
||||||
}
|
|
||||||
for k, v := range profile.Cookies {
|
|
||||||
step.Request.Cookies[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
package convert
|
||||||
@@ -31,9 +31,9 @@ func convert2GoTestScripts(paths ...string) error {
|
|||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
tc := testCase.ToTCase()
|
tc := testCase.ToTCase()
|
||||||
converter := TCaseConverter{
|
converter := TCaseConverter{
|
||||||
TCase: tc,
|
tCase: tc,
|
||||||
}
|
}
|
||||||
pytestPath, err := converter.ToPyTest()
|
pytestPath, err := converter.toPyTest()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).
|
log.Error().Err(err).
|
||||||
Str("originPath", tc.Config.Path).
|
Str("originPath", tc.Config.Path).
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
package convert
|
||||||
@@ -2,13 +2,14 @@ package convert
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"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/builtin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func LoadJSONCase(path string) (*hrp.TCase, error) {
|
func LoadJSONCase(path string) (*hrp.TCase, error) {
|
||||||
// load json case file
|
log.Info().Str("path", path).Msg("load json case file")
|
||||||
caseJSON := new(hrp.TCase)
|
caseJSON := new(hrp.TCase)
|
||||||
err := builtin.LoadFile(path, caseJSON)
|
err := builtin.LoadFile(path, caseJSON)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ var contentTypeMap = map[string]string{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func LoadPostmanCase(path string) (*hrp.TCase, error) {
|
func LoadPostmanCase(path string) (*hrp.TCase, error) {
|
||||||
// load postman file
|
log.Info().Str("path", path).Msg("load postman case file")
|
||||||
casePostman, err := loadCasePostman(path)
|
casePostman, err := loadCasePostman(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
"github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewYAMLCase(path string) (*hrp.TCase, error) {
|
func LoadYAMLCase(path string) (*hrp.TCase, error) {
|
||||||
// load yaml case file
|
// load yaml case file
|
||||||
caseJSON := new(hrp.TCase)
|
caseJSON := new(hrp.TCase)
|
||||||
err := builtin.LoadFile(path, caseJSON)
|
err := builtin.LoadFile(path, caseJSON)
|
||||||
|
|||||||
@@ -0,0 +1,205 @@
|
|||||||
|
package convert
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
|
"github.com/httprunner/httprunner/v4/hrp"
|
||||||
|
"github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
||||||
|
"github.com/httprunner/httprunner/v4/hrp/internal/sdk"
|
||||||
|
)
|
||||||
|
|
||||||
|
// target testcase format extensions
|
||||||
|
const (
|
||||||
|
suffixJSON = ".json"
|
||||||
|
suffixYAML = ".yaml"
|
||||||
|
suffixGoTest = ".go"
|
||||||
|
suffixPyTest = ".py"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FromType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
FromTypeJSON FromType = iota
|
||||||
|
FromTypeYAML
|
||||||
|
FromTypeHAR
|
||||||
|
FromTypePostman
|
||||||
|
FromTypeCurl
|
||||||
|
FromTypeSwagger
|
||||||
|
FromTypePyest
|
||||||
|
FromTypeGotest
|
||||||
|
)
|
||||||
|
|
||||||
|
func (fromType FromType) String() string {
|
||||||
|
switch fromType {
|
||||||
|
case FromTypeYAML:
|
||||||
|
return "yaml"
|
||||||
|
case FromTypeHAR:
|
||||||
|
return "har"
|
||||||
|
case FromTypePostman:
|
||||||
|
return "postman"
|
||||||
|
case FromTypeSwagger:
|
||||||
|
return "swagger"
|
||||||
|
case FromTypeCurl:
|
||||||
|
return "curl"
|
||||||
|
case FromTypeGotest:
|
||||||
|
return "gotest"
|
||||||
|
case FromTypePyest:
|
||||||
|
return "pytest"
|
||||||
|
default:
|
||||||
|
return "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type OutputType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
OutputTypeJSON OutputType = iota // default output type: JSON
|
||||||
|
OutputTypeYAML
|
||||||
|
OutputTypeGoTest
|
||||||
|
OutputTypePyTest
|
||||||
|
)
|
||||||
|
|
||||||
|
func (outputType OutputType) String() string {
|
||||||
|
switch outputType {
|
||||||
|
case OutputTypeYAML:
|
||||||
|
return "yaml"
|
||||||
|
case OutputTypeGoTest:
|
||||||
|
return "gotest"
|
||||||
|
case OutputTypePyTest:
|
||||||
|
return "pytest"
|
||||||
|
default:
|
||||||
|
return "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Profile is used to override or update(create if not existed) original headers and cookies
|
||||||
|
type Profile struct {
|
||||||
|
Override bool `json:"override" yaml:"override"`
|
||||||
|
Headers map[string]string `json:"headers" yaml:"headers"`
|
||||||
|
Cookies map[string]string `json:"cookies" yaml:"cookies"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConverter(outputDir, profilePath string) *TCaseConverter {
|
||||||
|
return &TCaseConverter{
|
||||||
|
profilePath: profilePath,
|
||||||
|
outputDir: outputDir,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TCaseConverter holds the common properties of case converter
|
||||||
|
type TCaseConverter struct {
|
||||||
|
fromFile string
|
||||||
|
profilePath string
|
||||||
|
outputDir string
|
||||||
|
tCase *hrp.TCase
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadCase loads source file and convert to TCase type
|
||||||
|
func (c *TCaseConverter) loadCase(casePath string, fromType FromType) error {
|
||||||
|
c.fromFile = casePath
|
||||||
|
var err error
|
||||||
|
switch fromType {
|
||||||
|
case FromTypeJSON:
|
||||||
|
c.tCase, err = LoadJSONCase(casePath)
|
||||||
|
case FromTypeYAML:
|
||||||
|
c.tCase, err = LoadYAMLCase(casePath)
|
||||||
|
case FromTypeHAR:
|
||||||
|
c.tCase, err = LoadHARCase(casePath)
|
||||||
|
case FromTypePostman:
|
||||||
|
c.tCase, err = LoadPostmanCase(casePath)
|
||||||
|
case FromTypeSwagger:
|
||||||
|
c.tCase, err = LoadSwaggerCase(casePath)
|
||||||
|
case FromTypeCurl:
|
||||||
|
c.tCase, err = LoadCurlCase(casePath)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TCaseConverter) Convert(casePath string, fromType FromType, outputType OutputType) error {
|
||||||
|
// report event
|
||||||
|
sdk.SendEvent(sdk.EventTracking{
|
||||||
|
Category: "ConvertTests",
|
||||||
|
Action: fmt.Sprintf("hrp convert --to-%s", outputType.String()),
|
||||||
|
})
|
||||||
|
log.Info().Str("path", casePath).
|
||||||
|
Str("fromType", fromType.String()).
|
||||||
|
Str("outputType", outputType.String()).
|
||||||
|
Msg("convert testcase")
|
||||||
|
|
||||||
|
// load source file
|
||||||
|
err := c.loadCase(casePath, fromType)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// override TCase with profile
|
||||||
|
if c.profilePath != "" {
|
||||||
|
c.overrideWithProfile(c.profilePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert to target format
|
||||||
|
var outputFile string
|
||||||
|
switch outputType {
|
||||||
|
case OutputTypeYAML:
|
||||||
|
outputFile, err = c.toYAML()
|
||||||
|
case OutputTypeGoTest:
|
||||||
|
outputFile, err = c.toGoTest()
|
||||||
|
case OutputTypePyTest:
|
||||||
|
outputFile, err = c.toPyTest()
|
||||||
|
default:
|
||||||
|
outputFile, err = c.toJSON()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info().Str("outputFile", outputFile).Msg("conversion completed")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TCaseConverter) genOutputPath(suffix string) string {
|
||||||
|
outFileFullName := builtin.GetFileNameWithoutExtension(c.fromFile) + "_test" + suffix
|
||||||
|
if c.outputDir != "" {
|
||||||
|
return filepath.Join(c.outputDir, outFileFullName)
|
||||||
|
} else {
|
||||||
|
return filepath.Join(filepath.Dir(c.fromFile), outFileFullName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TCaseConverter) overrideWithProfile(path string) error {
|
||||||
|
log.Info().Str("path", path).Msg("load profile")
|
||||||
|
profile := new(Profile)
|
||||||
|
err := builtin.LoadFile(path, profile)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn().Str("path", path).
|
||||||
|
Msg("failed to load profile, ignore!")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info().Interface("profile", profile).Msg("override with profile")
|
||||||
|
for _, step := range c.tCase.TestSteps {
|
||||||
|
// override original headers and cookies
|
||||||
|
if profile.Override {
|
||||||
|
step.Request.Headers = make(map[string]string)
|
||||||
|
step.Request.Cookies = make(map[string]string)
|
||||||
|
}
|
||||||
|
// update (create if not existed) original headers and cookies
|
||||||
|
if step.Request.Headers == nil {
|
||||||
|
step.Request.Headers = make(map[string]string)
|
||||||
|
}
|
||||||
|
if step.Request.Cookies == nil {
|
||||||
|
step.Request.Cookies = make(map[string]string)
|
||||||
|
}
|
||||||
|
for k, v := range profile.Headers {
|
||||||
|
step.Request.Headers[k] = v
|
||||||
|
}
|
||||||
|
for k, v := range profile.Cookies {
|
||||||
|
step.Request.Cookies[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -13,31 +13,33 @@ const (
|
|||||||
profileOverridePath = "../../../examples/data/profile_override.yml"
|
profileOverridePath = "../../../examples/data/profile_override.yml"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var converter *TCaseConverter
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
converter = NewConverter("", "")
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoadTCase(t *testing.T) {
|
func TestLoadTCase(t *testing.T) {
|
||||||
tCase, err := LoadTCase(harPath)
|
err := converter.loadCase(harPath, FromTypeHAR)
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
if !assert.NotEmpty(t, tCase) {
|
if !assert.NotEmpty(t, converter.tCase) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoadHARWithProfileOverride(t *testing.T) {
|
func TestLoadHARWithProfileOverride(t *testing.T) {
|
||||||
tCase, err := LoadTCase(harPath)
|
err := converter.loadCase(harPath, FromTypeHAR)
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
if !assert.NotEmpty(t, tCase) {
|
if !assert.NotEmpty(t, converter.tCase) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
|
|
||||||
caseConverter := &TCaseConverter{
|
|
||||||
TCase: tCase,
|
|
||||||
}
|
|
||||||
|
|
||||||
// override TCase with profile
|
// override TCase with profile
|
||||||
err = caseConverter.overrideWithProfile(profileOverridePath)
|
err = converter.overrideWithProfile(profileOverridePath)
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@@ -45,12 +47,12 @@ func TestLoadHARWithProfileOverride(t *testing.T) {
|
|||||||
for i := 0; i < 3; i++ {
|
for i := 0; i < 3; i++ {
|
||||||
if !assert.Equal(t,
|
if !assert.Equal(t,
|
||||||
map[string]string{"Content-Type": "application/x-www-form-urlencoded"},
|
map[string]string{"Content-Type": "application/x-www-form-urlencoded"},
|
||||||
caseConverter.TCase.TestSteps[i].Request.Headers) {
|
converter.tCase.TestSteps[i].Request.Headers) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
if !assert.Equal(t,
|
if !assert.Equal(t,
|
||||||
map[string]string{"UserName": "debugtalk"},
|
map[string]string{"UserName": "debugtalk"},
|
||||||
caseConverter.TCase.TestSteps[i].Request.Cookies) {
|
converter.tCase.TestSteps[i].Request.Cookies) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,7 +60,7 @@ func TestLoadHARWithProfileOverride(t *testing.T) {
|
|||||||
|
|
||||||
func TestMakeRequestWithProfile(t *testing.T) {
|
func TestMakeRequestWithProfile(t *testing.T) {
|
||||||
caseConverter := &TCaseConverter{
|
caseConverter := &TCaseConverter{
|
||||||
TCase: &hrp.TCase{
|
tCase: &hrp.TCase{
|
||||||
TestSteps: []*hrp.TStep{
|
TestSteps: []*hrp.TStep{
|
||||||
{
|
{
|
||||||
Request: &hrp.Request{
|
Request: &hrp.Request{
|
||||||
@@ -87,19 +89,19 @@ func TestMakeRequestWithProfile(t *testing.T) {
|
|||||||
|
|
||||||
if !assert.Equal(t, map[string]string{
|
if !assert.Equal(t, map[string]string{
|
||||||
"Content-Type": "application/x-www-form-urlencoded", "User-Agent": "hrp",
|
"Content-Type": "application/x-www-form-urlencoded", "User-Agent": "hrp",
|
||||||
}, caseConverter.TCase.TestSteps[0].Request.Headers) {
|
}, caseConverter.tCase.TestSteps[0].Request.Headers) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
if !assert.Equal(t, map[string]string{
|
if !assert.Equal(t, map[string]string{
|
||||||
"UserName": "debugtalk", "abc": "123",
|
"UserName": "debugtalk", "abc": "123",
|
||||||
}, caseConverter.TCase.TestSteps[0].Request.Cookies) {
|
}, caseConverter.tCase.TestSteps[0].Request.Cookies) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeRequestWithProfileOverride(t *testing.T) {
|
func TestMakeRequestWithProfileOverride(t *testing.T) {
|
||||||
caseConverter := &TCaseConverter{
|
caseConverter := &TCaseConverter{
|
||||||
TCase: &hrp.TCase{
|
tCase: &hrp.TCase{
|
||||||
TestSteps: []*hrp.TStep{
|
TestSteps: []*hrp.TStep{
|
||||||
{
|
{
|
||||||
Request: &hrp.Request{
|
Request: &hrp.Request{
|
||||||
@@ -129,12 +131,12 @@ func TestMakeRequestWithProfileOverride(t *testing.T) {
|
|||||||
|
|
||||||
if !assert.Equal(t, map[string]string{
|
if !assert.Equal(t, map[string]string{
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
}, caseConverter.TCase.TestSteps[0].Request.Headers) {
|
}, caseConverter.tCase.TestSteps[0].Request.Headers) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
if !assert.Equal(t, map[string]string{
|
if !assert.Equal(t, map[string]string{
|
||||||
"UserName": "debugtalk",
|
"UserName": "debugtalk",
|
||||||
}, caseConverter.TCase.TestSteps[0].Request.Cookies) {
|
}, caseConverter.tCase.TestSteps[0].Request.Cookies) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package convert
|
||||||
|
|
||||||
|
// TODO: convert TCase to gotest case
|
||||||
|
func (c *TCaseConverter) toGoTest() (string, error) {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package convert
|
||||||
|
|
||||||
|
import "github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
||||||
|
|
||||||
|
// convert TCase to JSON case
|
||||||
|
func (c *TCaseConverter) toJSON() (string, error) {
|
||||||
|
jsonPath := c.genOutputPath(suffixJSON)
|
||||||
|
err := builtin.Dump2JSON(c.tCase, jsonPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return jsonPath, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package convert
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/httprunner/httprunner/v4/hrp/internal/myexec"
|
||||||
|
)
|
||||||
|
|
||||||
|
// convert TCase to pytest case
|
||||||
|
func (c *TCaseConverter) toPyTest() (string, error) {
|
||||||
|
jsonPath, err := c.toJSON()
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, "convert to JSON case failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
args := append([]string{"make"}, jsonPath)
|
||||||
|
err = myexec.ExecPython3Command("httprunner", args...)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return c.genOutputPath(suffixPyTest), nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package convert
|
||||||
|
|
||||||
|
import "github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
||||||
|
|
||||||
|
// convert TCase to YAML case
|
||||||
|
func (c *TCaseConverter) toYAML() (string, error) {
|
||||||
|
yamlPath := c.genOutputPath(suffixYAML)
|
||||||
|
err := builtin.Dump2YAML(c.tCase, yamlPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return yamlPath, nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user