mirror of
https://github.com/httprunner/httprunner.git
synced 2026-07-07 23:41:22 +08:00
change: add unittest for override
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -1,498 +0,0 @@
|
|||||||
{
|
|
||||||
"info": {
|
|
||||||
"_postman_id": "0417a445-b206-4ea2-b1d2-5441afd6c6b9",
|
|
||||||
"name": "postman collection demo",
|
|
||||||
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
|
||||||
},
|
|
||||||
"item": [
|
|
||||||
{
|
|
||||||
"name": "folder1",
|
|
||||||
"item": [
|
|
||||||
{
|
|
||||||
"name": "folder2",
|
|
||||||
"item": [
|
|
||||||
{
|
|
||||||
"name": "Get with params",
|
|
||||||
"request": {
|
|
||||||
"method": "GET",
|
|
||||||
"header": [],
|
|
||||||
"url": {
|
|
||||||
"raw": "https://postman-echo.com/:path?k1=v1&k2=v2",
|
|
||||||
"protocol": "https",
|
|
||||||
"host": [
|
|
||||||
"postman-echo",
|
|
||||||
"com"
|
|
||||||
],
|
|
||||||
"path": [
|
|
||||||
":path"
|
|
||||||
],
|
|
||||||
"query": [
|
|
||||||
{
|
|
||||||
"key": "k1",
|
|
||||||
"value": "v1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "k2",
|
|
||||||
"value": "v2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "k3",
|
|
||||||
"value": "v3",
|
|
||||||
"disabled": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"variable": [
|
|
||||||
{
|
|
||||||
"key": "path",
|
|
||||||
"value": "get"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"response": [
|
|
||||||
{
|
|
||||||
"name": "Get with params case1",
|
|
||||||
"originalRequest": {
|
|
||||||
"method": "GET",
|
|
||||||
"header": [],
|
|
||||||
"url": {
|
|
||||||
"raw": "https://postman-echo.com/:path?k1=v1&k2=v2",
|
|
||||||
"protocol": "https",
|
|
||||||
"host": [
|
|
||||||
"postman-echo",
|
|
||||||
"com"
|
|
||||||
],
|
|
||||||
"path": [
|
|
||||||
":path"
|
|
||||||
],
|
|
||||||
"query": [
|
|
||||||
{
|
|
||||||
"key": "k1",
|
|
||||||
"value": "v1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "k2",
|
|
||||||
"value": "v2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "k3",
|
|
||||||
"value": "v3",
|
|
||||||
"disabled": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"variable": [
|
|
||||||
{
|
|
||||||
"key": "path",
|
|
||||||
"value": "get"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"status": "OK",
|
|
||||||
"code": 200,
|
|
||||||
"_postman_previewlanguage": "json",
|
|
||||||
"header": [
|
|
||||||
{
|
|
||||||
"key": "Date",
|
|
||||||
"value": "Mon, 16 May 2022 12:12:28 GMT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "Content-Type",
|
|
||||||
"value": "application/json; charset=utf-8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "Content-Length",
|
|
||||||
"value": "508"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "Connection",
|
|
||||||
"value": "keep-alive"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "ETag",
|
|
||||||
"value": "W/\"1fc-x4EIPFQzoLX0HenCFPx6HNfG0lc\""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "Vary",
|
|
||||||
"value": "Accept-Encoding"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "set-cookie",
|
|
||||||
"value": "sails.sid=s%3AX2aa_Z7gbcUqIWAjlBkytBRmQ4WCvc3D.pX9Qxh8aO9Ict0BL4CrRhdDJmz81UVmwFsV5Nx30Ils; Path=/; HttpOnly"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"cookie": [],
|
|
||||||
"body": "{\n \"args\": {\n \"k1\": \"v1\",\n \"k2\": \"v2\"\n },\n \"headers\": {\n \"x-forwarded-proto\": \"https\",\n \"x-forwarded-port\": \"443\",\n \"host\": \"postman-echo.com\",\n \"user-agent\": \"PostmanRuntime/7.29.0\",\n \"accept\": \"*/*\",\n \"accept-encoding\": \"gzip, deflate, br\",\n \"cookie\": \"Cookie_1=c1; Cookie_2=c2; sails.sid=s%3AGX6aS9b_phvUSUk66w7ZBgWuOPI7IIKT.ayEGTaW4U35eAWyPz%2Fh6Q74DonNcbqw3H5Q5Zv%2BfKMY\"\n },\n \"url\": \"https://postman-echo.com/get?k1=v1&k2=v2\"\n}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Get with params case2",
|
|
||||||
"originalRequest": {
|
|
||||||
"method": "GET",
|
|
||||||
"header": [],
|
|
||||||
"url": {
|
|
||||||
"raw": "https://postman-echo.com/:path?k1=v1&k3=v3",
|
|
||||||
"protocol": "https",
|
|
||||||
"host": [
|
|
||||||
"postman-echo",
|
|
||||||
"com"
|
|
||||||
],
|
|
||||||
"path": [
|
|
||||||
":path"
|
|
||||||
],
|
|
||||||
"query": [
|
|
||||||
{
|
|
||||||
"key": "k1",
|
|
||||||
"value": "v1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "k2",
|
|
||||||
"value": "v2",
|
|
||||||
"disabled": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "k3",
|
|
||||||
"value": "v3"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"variable": [
|
|
||||||
{
|
|
||||||
"key": "path",
|
|
||||||
"value": "get"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"status": "OK",
|
|
||||||
"code": 200,
|
|
||||||
"_postman_previewlanguage": "json",
|
|
||||||
"header": [
|
|
||||||
{
|
|
||||||
"key": "Date",
|
|
||||||
"value": "Mon, 16 May 2022 12:14:04 GMT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "Content-Type",
|
|
||||||
"value": "application/json; charset=utf-8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "Content-Length",
|
|
||||||
"value": "504"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "Connection",
|
|
||||||
"value": "keep-alive"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "ETag",
|
|
||||||
"value": "W/\"1f8-tMaKs4xmwr+3su3I8mcgR0p+ucw\""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "Vary",
|
|
||||||
"value": "Accept-Encoding"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "set-cookie",
|
|
||||||
"value": "sails.sid=s%3AMNuX_i0KgaP_KuuMpYB8RtCNipCGJWVw.4ETfPHxE81Omqb6Yli%2FezUU8CXyYBcN3%2Bxkx5htwh8Y; Path=/; HttpOnly"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"cookie": [],
|
|
||||||
"body": "{\n \"args\": {\n \"k1\": \"v1\",\n \"k3\": \"v3\"\n },\n \"headers\": {\n \"x-forwarded-proto\": \"https\",\n \"x-forwarded-port\": \"443\",\n \"host\": \"postman-echo.com\",\n \"user-agent\": \"PostmanRuntime/7.29.0\",\n \"accept\": \"*/*\",\n \"accept-encoding\": \"gzip, deflate, br\",\n \"cookie\": \"Cookie_1=c1; Cookie_2=c2; sails.sid=s%3AX2aa_Z7gbcUqIWAjlBkytBRmQ4WCvc3D.pX9Qxh8aO9Ict0BL4CrRhdDJmz81UVmwFsV5Nx30Ils\"\n },\n \"url\": \"https://postman-echo.com/get?k1=v1&k3=v3\"\n}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "folder3",
|
|
||||||
"item": [
|
|
||||||
{
|
|
||||||
"name": "Post form-data",
|
|
||||||
"request": {
|
|
||||||
"method": "POST",
|
|
||||||
"header": [],
|
|
||||||
"body": {
|
|
||||||
"mode": "formdata",
|
|
||||||
"formdata": [
|
|
||||||
{
|
|
||||||
"key": "k1",
|
|
||||||
"value": "v1",
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "k2",
|
|
||||||
"value": "v2",
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "k3",
|
|
||||||
"value": "v3",
|
|
||||||
"type": "text",
|
|
||||||
"disabled": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "intro_key",
|
|
||||||
"type": "file",
|
|
||||||
"src": "intro.txt"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "logo_key",
|
|
||||||
"type": "file",
|
|
||||||
"src": "logo.jpeg"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"raw": "https://postman-echo.com/:path",
|
|
||||||
"protocol": "https",
|
|
||||||
"host": [
|
|
||||||
"postman-echo",
|
|
||||||
"com"
|
|
||||||
],
|
|
||||||
"path": [
|
|
||||||
":path"
|
|
||||||
],
|
|
||||||
"variable": [
|
|
||||||
{
|
|
||||||
"key": "path",
|
|
||||||
"value": "post"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"response": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Post x-www-form-urlencoded",
|
|
||||||
"request": {
|
|
||||||
"method": "POST",
|
|
||||||
"header": [],
|
|
||||||
"body": {
|
|
||||||
"mode": "urlencoded",
|
|
||||||
"urlencoded": [
|
|
||||||
{
|
|
||||||
"key": "k1",
|
|
||||||
"value": "v1",
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "k2",
|
|
||||||
"value": "v2",
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "k3",
|
|
||||||
"value": "v3",
|
|
||||||
"type": "text",
|
|
||||||
"disabled": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"raw": "https://postman-echo.com/:path",
|
|
||||||
"protocol": "https",
|
|
||||||
"host": [
|
|
||||||
"postman-echo",
|
|
||||||
"com"
|
|
||||||
],
|
|
||||||
"path": [
|
|
||||||
":path"
|
|
||||||
],
|
|
||||||
"variable": [
|
|
||||||
{
|
|
||||||
"key": "path",
|
|
||||||
"value": "post"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"response": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Post raw json",
|
|
||||||
"request": {
|
|
||||||
"method": "POST",
|
|
||||||
"header": [],
|
|
||||||
"body": {
|
|
||||||
"mode": "raw",
|
|
||||||
"raw": "{\n \"k1\": \"v1\",\n \"k2\": \"v2\"\n}",
|
|
||||||
"options": {
|
|
||||||
"raw": {
|
|
||||||
"language": "json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"raw": "https://postman-echo.com/:path",
|
|
||||||
"protocol": "https",
|
|
||||||
"host": [
|
|
||||||
"postman-echo",
|
|
||||||
"com"
|
|
||||||
],
|
|
||||||
"path": [
|
|
||||||
":path"
|
|
||||||
],
|
|
||||||
"variable": [
|
|
||||||
{
|
|
||||||
"key": "path",
|
|
||||||
"value": "post"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"response": []
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Post raw text",
|
|
||||||
"request": {
|
|
||||||
"method": "POST",
|
|
||||||
"header": [],
|
|
||||||
"body": {
|
|
||||||
"mode": "raw",
|
|
||||||
"raw": "have a nice day",
|
|
||||||
"options": {
|
|
||||||
"raw": {
|
|
||||||
"language": "text"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"raw": "https://postman-echo.com/:path",
|
|
||||||
"protocol": "https",
|
|
||||||
"host": [
|
|
||||||
"postman-echo",
|
|
||||||
"com"
|
|
||||||
],
|
|
||||||
"path": [
|
|
||||||
":path"
|
|
||||||
],
|
|
||||||
"variable": [
|
|
||||||
{
|
|
||||||
"key": "path",
|
|
||||||
"value": "post"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"response": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Get request headers",
|
|
||||||
"request": {
|
|
||||||
"method": "GET",
|
|
||||||
"header": [
|
|
||||||
{
|
|
||||||
"key": "User-Agent",
|
|
||||||
"value": "HttpRunner",
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "User-Name",
|
|
||||||
"value": "bbx",
|
|
||||||
"type": "text",
|
|
||||||
"disabled": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "Connection",
|
|
||||||
"value": "close",
|
|
||||||
"type": "text"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"url": {
|
|
||||||
"raw": "https://postman-echo.com/:path",
|
|
||||||
"protocol": "https",
|
|
||||||
"host": [
|
|
||||||
"postman-echo",
|
|
||||||
"com"
|
|
||||||
],
|
|
||||||
"path": [
|
|
||||||
":path"
|
|
||||||
],
|
|
||||||
"variable": [
|
|
||||||
{
|
|
||||||
"key": "path",
|
|
||||||
"value": "headers"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"response": [
|
|
||||||
{
|
|
||||||
"name": "Get request headers case1",
|
|
||||||
"originalRequest": {
|
|
||||||
"method": "GET",
|
|
||||||
"header": [
|
|
||||||
{
|
|
||||||
"key": "User-Agent",
|
|
||||||
"value": "HttpRunner",
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "User-Name",
|
|
||||||
"value": "bbx",
|
|
||||||
"type": "text",
|
|
||||||
"disabled": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "Cookie",
|
|
||||||
"value": "Cookie_1=c1; Cookie_2=c2; sails.sid=s%3AGX6aS9b_phvUSUk66w7ZBgWuOPI7IIKT.ayEGTaW4U35eAWyPz%2Fh6Q74DonNcbqw3H5Q5Zv%2BfKMY",
|
|
||||||
"type": "text"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"url": {
|
|
||||||
"raw": "https://postman-echo.com/:path",
|
|
||||||
"protocol": "https",
|
|
||||||
"host": [
|
|
||||||
"postman-echo",
|
|
||||||
"com"
|
|
||||||
],
|
|
||||||
"path": [
|
|
||||||
":path"
|
|
||||||
],
|
|
||||||
"variable": [
|
|
||||||
{
|
|
||||||
"key": "path",
|
|
||||||
"value": "headers"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"status": "OK",
|
|
||||||
"code": 200,
|
|
||||||
"_postman_previewlanguage": "json",
|
|
||||||
"header": [
|
|
||||||
{
|
|
||||||
"key": "Date",
|
|
||||||
"value": "Mon, 16 May 2022 12:14:25 GMT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "Content-Type",
|
|
||||||
"value": "application/json; charset=utf-8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "Content-Length",
|
|
||||||
"value": "541"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "Connection",
|
|
||||||
"value": "keep-alive"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "ETag",
|
|
||||||
"value": "W/\"21d-ld5UvFTaRM6lihVnvCj6mZm5Of0\""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "Vary",
|
|
||||||
"value": "Accept-Encoding"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"cookie": [],
|
|
||||||
"body": "{\n \"headers\": {\n \"x-forwarded-proto\": \"https\",\n \"x-forwarded-port\": \"443\",\n \"host\": \"postman-echo.com\",\n \"user-agent\": \"HttpRunner\",\n \"cookie\": \"Cookie_1=c1; Cookie_2=c2; sails.sid=s%3AGX6aS9b_phvUSUk66w7ZBgWuOPI7IIKT.ayEGTaW4U35eAWyPz%2Fh6Q74DonNcbqw3H5Q5Zv%2BfKMY\",\n \"accept\": \"*/*\",\n \"accept-encoding\": \"gzip, deflate, br\"\n }\n}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
headers:
|
|
||||||
User-Agent: "this header will be created or updated"
|
|
||||||
cookies:
|
|
||||||
Cookie1: "this cookie will be created or updated"
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
override: true
|
|
||||||
headers:
|
|
||||||
Header1: "all original headers will be overridden"
|
|
||||||
cookies:
|
|
||||||
Cookie1: "all original cookies will be overridden"
|
|
||||||
4
examples/data/profile.yml
Normal file
4
examples/data/profile.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
headers:
|
||||||
|
Content-Type: "application/x-www-form-urlencoded"
|
||||||
|
cookies:
|
||||||
|
UserName: "debugtalk"
|
||||||
@@ -30,14 +30,18 @@ Global Flags:
|
|||||||
1. `--to-json / --to-yaml / --to-gotest / --to-pytest` 用于将输入转化为对应形态的测试用例,四个选项中最多只能指定一个,如果不指定则默认会将输入转化为 JSON 形态的测试用例
|
1. `--to-json / --to-yaml / --to-gotest / --to-pytest` 用于将输入转化为对应形态的测试用例,四个选项中最多只能指定一个,如果不指定则默认会将输入转化为 JSON 形态的测试用例
|
||||||
2. `--output-dir` 后接测试用例的期望输出目录的路径,用于将转换生成的测试用例输出到对应的文件夹
|
2. `--output-dir` 后接测试用例的期望输出目录的路径,用于将转换生成的测试用例输出到对应的文件夹
|
||||||
3. `--profile` 后接 profile 配置文件的路径,目前支持替换(不存在则会创建)或者覆盖输入的外部脚本/测试用例中的 `Headers` 和 `Cookies` 信息,profile 文件的后缀可以为 `json/yaml/yml`,下面给出两类 profile 配置文件的示例:
|
3. `--profile` 后接 profile 配置文件的路径,目前支持替换(不存在则会创建)或者覆盖输入的外部脚本/测试用例中的 `Headers` 和 `Cookies` 信息,profile 文件的后缀可以为 `json/yaml/yml`,下面给出两类 profile 配置文件的示例:
|
||||||
|
|
||||||
- 根据 profile 替换指定的 `Headers` 和 `Cookies` 信息
|
- 根据 profile 替换指定的 `Headers` 和 `Cookies` 信息
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
headers:
|
headers:
|
||||||
Header1: "this header will be created or updated"
|
Header1: "this header will be created or updated"
|
||||||
cookies:
|
cookies:
|
||||||
Cookie1: "this cookie will be created or updated"
|
Cookie1: "this cookie will be created or updated"
|
||||||
```
|
```
|
||||||
|
|
||||||
- 根据 profile 覆盖原有的 `Headers` 和 `Cookies` 信息
|
- 根据 profile 覆盖原有的 `Headers` 和 `Cookies` 信息
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
override: true
|
override: true
|
||||||
headers:
|
headers:
|
||||||
|
|||||||
@@ -21,43 +21,6 @@ const (
|
|||||||
suffixPyTest = ".py"
|
suffixPyTest = ".py"
|
||||||
)
|
)
|
||||||
|
|
||||||
type InputType int
|
|
||||||
|
|
||||||
const (
|
|
||||||
InputTypeUnknown InputType = iota // default input type: unknown
|
|
||||||
InputTypeHAR
|
|
||||||
InputTypePostman
|
|
||||||
InputTypeSwagger
|
|
||||||
InputTypeJMeter
|
|
||||||
InputTypeJSON
|
|
||||||
InputTypeYAML
|
|
||||||
InputTypeGoTest
|
|
||||||
InputTypePyTest
|
|
||||||
)
|
|
||||||
|
|
||||||
func (inputType InputType) String() string {
|
|
||||||
switch inputType {
|
|
||||||
case InputTypeHAR:
|
|
||||||
return "har"
|
|
||||||
case InputTypePostman:
|
|
||||||
return "postman"
|
|
||||||
case InputTypeSwagger:
|
|
||||||
return "swagger"
|
|
||||||
case InputTypeJMeter:
|
|
||||||
return "jmeter"
|
|
||||||
case InputTypeJSON:
|
|
||||||
return "json testcase"
|
|
||||||
case InputTypeYAML:
|
|
||||||
return "yaml testcase"
|
|
||||||
case InputTypeGoTest:
|
|
||||||
return "gotest script"
|
|
||||||
case InputTypePyTest:
|
|
||||||
return "pytest script"
|
|
||||||
default:
|
|
||||||
return "unknown"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type OutputType int
|
type OutputType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -80,15 +43,6 @@ func (outputType OutputType) String() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TCaseConverter holds the common properties of case converter
|
|
||||||
type TCaseConverter struct {
|
|
||||||
InputPath string
|
|
||||||
OutputDir string
|
|
||||||
InputType InputType
|
|
||||||
OutputType OutputType
|
|
||||||
TCase *hrp.TCase
|
|
||||||
}
|
|
||||||
|
|
||||||
// Profile is used to override or update(create if not existed) original headers and cookies
|
// Profile is used to override or update(create if not existed) original headers and cookies
|
||||||
type Profile struct {
|
type Profile struct {
|
||||||
Override bool `json:"override" yaml:"override"`
|
Override bool `json:"override" yaml:"override"`
|
||||||
@@ -96,6 +50,57 @@ type Profile struct {
|
|||||||
Cookies map[string]string `json:"cookies" yaml:"cookies"`
|
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 _, path := range args {
|
||||||
|
// loads source file and convert to TCase format
|
||||||
|
tCase, err := LoadTCase(path)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn().Err(err).Str("path", path).Msg("construct case loader failed")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
caseConverter := &TCaseConverter{
|
||||||
|
SourcePath: path,
|
||||||
|
OutputDir: outputDir,
|
||||||
|
OutputType: outputType,
|
||||||
|
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("source path", path).
|
||||||
|
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
|
// LoadTCase loads source file and convert to TCase type
|
||||||
func LoadTCase(path string) (*hrp.TCase, error) {
|
func LoadTCase(path string) (*hrp.TCase, error) {
|
||||||
extName := filepath.Ext(path)
|
extName := filepath.Ext(path)
|
||||||
@@ -156,19 +161,27 @@ func LoadTCase(path string) (*hrp.TCase, error) {
|
|||||||
return nil, fmt.Errorf("unsupported file type: %v", extName)
|
return nil, fmt.Errorf("unsupported file type: %v", extName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TCaseConverter holds the common properties of case converter
|
||||||
|
type TCaseConverter struct {
|
||||||
|
SourcePath string
|
||||||
|
OutputDir string
|
||||||
|
OutputType OutputType
|
||||||
|
TCase *hrp.TCase
|
||||||
|
}
|
||||||
|
|
||||||
func (c *TCaseConverter) genOutputPath(suffix string) string {
|
func (c *TCaseConverter) genOutputPath(suffix string) string {
|
||||||
outFileFullName := builtin.GetOutputNameWithoutExtension(c.InputPath) + suffix
|
outFileFullName := builtin.GetOutputNameWithoutExtension(c.SourcePath) + suffix
|
||||||
if c.OutputDir != "" {
|
if c.OutputDir != "" {
|
||||||
return filepath.Join(c.OutputDir, outFileFullName)
|
return filepath.Join(c.OutputDir, outFileFullName)
|
||||||
} else {
|
} else {
|
||||||
return filepath.Join(filepath.Dir(c.InputPath), outFileFullName)
|
return filepath.Join(filepath.Dir(c.SourcePath), outFileFullName)
|
||||||
}
|
}
|
||||||
// TODO avoid outFileFullName conflict?
|
// TODO avoid outFileFullName conflict?
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert TCase to pytest case
|
// convert TCase to pytest case
|
||||||
func (c *TCaseConverter) ToPyTest() (string, error) {
|
func (c *TCaseConverter) ToPyTest() (string, error) {
|
||||||
args := append([]string{"make"}, c.InputPath)
|
args := append([]string{"make"}, c.SourcePath)
|
||||||
err := builtin.ExecPython3Command("httprunner", args...)
|
err := builtin.ExecPython3Command("httprunner", args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -201,54 +214,6 @@ func (c *TCaseConverter) ToYAML() (string, error) {
|
|||||||
return yamlPath, nil
|
return yamlPath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
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 _, path := range args {
|
|
||||||
// loads source file in support types and convert to TCase format
|
|
||||||
tCase, err := LoadTCase(path)
|
|
||||||
if err != nil {
|
|
||||||
log.Warn().Err(err).Str("path", path).Msg("construct case loader failed")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
caseConverter := TCaseConverter{
|
|
||||||
OutputDir: outputDir,
|
|
||||||
OutputType: outputType,
|
|
||||||
TCase: tCase,
|
|
||||||
}
|
|
||||||
|
|
||||||
// override TCase with profile
|
|
||||||
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("source path", path).
|
|
||||||
Msg("convert case failed")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
outputFiles = append(outputFiles, outputFile)
|
|
||||||
}
|
|
||||||
log.Info().Strs("output files", outputFiles).Msg("conversion completed")
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
||||||
@@ -259,6 +224,7 @@ func (c *TCaseConverter) overrideWithProfile(path string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Info().Interface("profile", profile).Msg("override with profile")
|
||||||
for _, step := range c.TCase.TestSteps {
|
for _, step := range c.TCase.TestSteps {
|
||||||
// override original headers and cookies
|
// override original headers and cookies
|
||||||
if profile.Override {
|
if profile.Override {
|
||||||
|
|||||||
@@ -8,11 +8,7 @@ import (
|
|||||||
"github.com/httprunner/httprunner/v4/hrp"
|
"github.com/httprunner/httprunner/v4/hrp"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var harPath = "../../../examples/data/har/demo.har"
|
||||||
harPath = "../../../examples/data/har/demo.har"
|
|
||||||
harPath2 = "../../../examples/data/har/postman-echo.har"
|
|
||||||
harProfileOverridePath = "../../../examples/data/har/profile_override.yml"
|
|
||||||
)
|
|
||||||
|
|
||||||
var caseHar *CaseHar
|
var caseHar *CaseHar
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,7 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var collectionPath = "../../../examples/data/postman/postman_collection.json"
|
||||||
collectionPath = "../../../examples/data/postman/postman_collection.json"
|
|
||||||
collectionProfileOverridePath = "../../../examples/data/postman/profile_override.yml"
|
|
||||||
collectionProfilePath = "../../../examples/data/postman/profile.yml"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestLoadCollection(t *testing.T) {
|
func TestLoadCollection(t *testing.T) {
|
||||||
casePostman, err := loadCasePostman(collectionPath)
|
casePostman, err := loadCasePostman(collectionPath)
|
||||||
|
|||||||
140
hrp/internal/convert/converter_test.go
Normal file
140
hrp/internal/convert/converter_test.go
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
package convert
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/httprunner/httprunner/v4/hrp"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
profilePath = "../../../examples/data/profile.yml"
|
||||||
|
profileOverridePath = "../../../examples/data/profile_override.yml"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLoadTCase(t *testing.T) {
|
||||||
|
tCase, err := LoadTCase(harPath)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.NotEmpty(t, tCase) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLoadHARWithProfileOverride(t *testing.T) {
|
||||||
|
tCase, err := LoadTCase(harPath)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.NotEmpty(t, tCase) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
|
||||||
|
caseConverter := &TCaseConverter{
|
||||||
|
TCase: tCase,
|
||||||
|
}
|
||||||
|
|
||||||
|
// override TCase with profile
|
||||||
|
err = caseConverter.overrideWithProfile(profileOverridePath)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
if !assert.Equal(t,
|
||||||
|
map[string]string{"Content-Type": "application/x-www-form-urlencoded"},
|
||||||
|
caseConverter.TCase.TestSteps[i].Request.Headers) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t,
|
||||||
|
map[string]string{"UserName": "debugtalk"},
|
||||||
|
caseConverter.TCase.TestSteps[i].Request.Cookies) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMakeRequestWithProfile(t *testing.T) {
|
||||||
|
caseConverter := &TCaseConverter{
|
||||||
|
TCase: &hrp.TCase{
|
||||||
|
TestSteps: []*hrp.TStep{
|
||||||
|
{
|
||||||
|
Request: &hrp.Request{
|
||||||
|
Method: hrp.HTTPMethod("POST"),
|
||||||
|
Headers: map[string]string{
|
||||||
|
"Content-Type": "application/json; charset=utf-8",
|
||||||
|
"User-Agent": "hrp",
|
||||||
|
},
|
||||||
|
Cookies: map[string]string{
|
||||||
|
"abc": "123",
|
||||||
|
"UserName": "leolee",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := caseConverter.overrideWithProfile(profilePath)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !assert.Equal(t, map[string]string{
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded", "User-Agent": "hrp",
|
||||||
|
}, caseConverter.TCase.TestSteps[0].Request.Headers) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, map[string]string{
|
||||||
|
"UserName": "debugtalk", "abc": "123",
|
||||||
|
}, caseConverter.TCase.TestSteps[0].Request.Cookies) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMakeRequestWithProfileOverride(t *testing.T) {
|
||||||
|
caseConverter := &TCaseConverter{
|
||||||
|
TCase: &hrp.TCase{
|
||||||
|
TestSteps: []*hrp.TStep{
|
||||||
|
{
|
||||||
|
Request: &hrp.Request{
|
||||||
|
Method: hrp.HTTPMethod("POST"),
|
||||||
|
Headers: map[string]string{
|
||||||
|
"Content-Type": "application/json; charset=utf-8",
|
||||||
|
"User-Agent": "hrp",
|
||||||
|
},
|
||||||
|
Cookies: map[string]string{
|
||||||
|
"abc": "123",
|
||||||
|
"UserName": "leolee",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// override TCase with profile
|
||||||
|
err := caseConverter.overrideWithProfile(profileOverridePath)
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.NoError(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !assert.Equal(t, map[string]string{
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
}, caseConverter.TCase.TestSteps[0].Request.Headers) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
if !assert.Equal(t, map[string]string{
|
||||||
|
"UserName": "debugtalk",
|
||||||
|
}, caseConverter.TCase.TestSteps[0].Request.Cookies) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user