Merge pull request #925 from httprunner/v3

## 3.0.11 (2020-06-08)

**Changed**

- change: override variables
    (1) testcase: session variables > step variables > config variables
    (2) testsuite: testcase variables > config variables
    (3) testsuite testcase variables > testcase config variables

**Fixed**

- fix: incorrect summary success when testcase failed
- fix: reload to refresh previously loaded debugtalk module
- fix: escape $$ in variable value
This commit is contained in:
debugtalk
2020-06-08 18:20:12 +08:00
committed by GitHub
38 changed files with 366 additions and 173 deletions

View File

@@ -1,5 +1,20 @@
# Release History # Release History
## 3.0.11 (2020-06-08)
**Changed**
- change: override variables
(1) testcase: session variables > step variables > config variables
(2) testsuite: testcase variables > config variables
(3) testsuite testcase variables > testcase config variables
**Fixed**
- fix: incorrect summary success when testcase failed
- fix: reload to refresh previously loaded debugtalk module
- fix: escape $$ in variable value
## 3.0.10 (2020-06-07) ## 3.0.10 (2020-06-07)
**Added** **Added**

View File

@@ -6,20 +6,20 @@
`HttpRunner` is available on [`PyPI`][PyPI] and can be installed through `pip`. `HttpRunner` is available on [`PyPI`][PyPI] and can be installed through `pip`.
```bash ```bash
$ pip install httprunner $ pip3 install httprunner
``` ```
If you want to keep up with the latest version, you can install with github repository url. If you want to keep up with the latest version, you can install with github repository url.
```bash ```bash
$ pip install git+https://github.com/httprunner/httprunner.git@master $ pip3 install git+https://github.com/httprunner/httprunner.git@master
``` ```
If you have installed `HttpRunner` before and want to upgrade to the latest version, you can use the `-U` option. If you have installed `HttpRunner` before and want to upgrade to the latest version, you can use the `-U` option.
```bash ```bash
$ pip install -U httprunner $ pip3 install -U httprunner
$ pip install -U git+https://github.com/httprunner/httprunner.git@master $ pip3 install -U git+https://github.com/httprunner/httprunner.git@master
``` ```
## Check Installation ## Check Installation
@@ -27,15 +27,15 @@ $ pip install -U git+https://github.com/httprunner/httprunner.git@master
When HttpRunner is installed, 4 commands will be added in your system. When HttpRunner is installed, 4 commands will be added in your system.
- `httprunner`: main command, used for all functions - `httprunner`: main command, used for all functions
- `hrun`: alias for `httprunner run`, used to run YAML/JSON testcases - `hrun`: alias for `httprunner run`, used to run YAML/JSON/pytest testcases
- `hmake`: alias for `httprunner make`, used to convert YAML/JSON testcases to pytest files - `hmake`: alias for `httprunner make`, used to convert YAML/JSON testcases to pytest files
- `har2case`: alias for `httprunner har2case`, used to convert HAR to YAML/JSON testcases - `har2case`: alias for `httprunner har2case`, used to convert HAR to YAML/JSON testcases
To see `HttpRunner` version: To see `HttpRunner` version:
```text ```text
$ httprunner -V $ httprunner -V # hrun -V
3.0.6 3.0.10
``` ```
To see available options, run: To see available options, run:

0
docs/quickstart.md Normal file
View File

View File

@@ -1,4 +1,4 @@
# NOTE: Generated By HttpRunner v3.0.10 # NOTE: Generated By HttpRunner v3.0.11
# FROM: examples/httpbin/basic.yml # FROM: examples/httpbin/basic.yml
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase

View File

@@ -1,4 +1,4 @@
# NOTE: Generated By HttpRunner v3.0.10 # NOTE: Generated By HttpRunner v3.0.11
# FROM: examples/httpbin/hooks.yml # FROM: examples/httpbin/hooks.yml
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase

View File

@@ -1,4 +1,4 @@
# NOTE: Generated By HttpRunner v3.0.10 # NOTE: Generated By HttpRunner v3.0.11
# FROM: examples/httpbin/load_image.yml # FROM: examples/httpbin/load_image.yml
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase

View File

@@ -1,4 +1,4 @@
# NOTE: Generated By HttpRunner v3.0.10 # NOTE: Generated By HttpRunner v3.0.11
# FROM: examples/httpbin/upload.yml # FROM: examples/httpbin/upload.yml
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase

View File

@@ -1,4 +1,4 @@
# NOTE: Generated By HttpRunner v3.0.10 # NOTE: Generated By HttpRunner v3.0.11
# FROM: examples/httpbin/validate.yml # FROM: examples/httpbin/validate.yml
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase

View File

@@ -9,5 +9,9 @@ def sum_two(m, n):
return m + n return m + n
def get_variables(): def get_testcase_config_variables():
return {"foo1": "session_bar1"} return {"foo1": "testcase_config_bar1", "foo2": "testcase_config_bar2"}
def get_testsuite_config_variables():
return {"foo1": "testsuite_config_bar1", "foo2": "testsuite_config_bar2"}

View File

@@ -1,15 +1,20 @@
config: config:
name: "demo testsuite" name: "demo testsuite"
variables: ${get_variables()} variables: ${get_testsuite_config_variables()}
testcases: testcases:
- -
name: request with functions name: request with functions
testcase: request_methods/request_with_functions.yml testcase: request_methods/request_with_functions.yml
variables: variables:
var1: testsuite_val1 foo1: testcase_ref_bar11
expect_foo1: testcase_ref_bar11
expect_foo2: testsuite_config_bar2
- -
name: request with referenced testcase name: request with referenced testcase
testcase: request_methods/request_with_testcase_reference.yml testcase: request_methods/request_with_testcase_reference.yml
variables: variables:
var2: testsuite_val2 foo1: testcase_ref_bar12
expect_foo1: testcase_ref_bar12
foo2: testcase_ref_bar22
expect_foo2: testcase_ref_bar22

View File

@@ -1,4 +1,4 @@
# NOTE: Generated By HttpRunner v3.0.10 # NOTE: Generated By HttpRunner v3.0.11
# FROM: examples/postman_echo/request_methods/request_with_functions.yml # FROM: examples/postman_echo/request_methods/request_with_functions.yml
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
@@ -7,32 +7,39 @@ from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
class TestCaseRequestWithFunctions(HttpRunner): class TestCaseRequestWithFunctions(HttpRunner):
config = ( config = (
Config("request with functions") Config("request with functions")
.variables(**{"var1": "testsuite_val1", "foo1": "session_bar1"}) .variables(
**{
"foo1": "testcase_ref_bar11",
"foo2": "testsuite_config_bar2",
"expect_foo1": "testcase_ref_bar11",
"expect_foo2": "testsuite_config_bar2",
}
)
.base_url("https://postman-echo.com") .base_url("https://postman-echo.com")
.verify(False) .verify(False)
.export(*["session_foo2"]) .export(*["foo3"])
) )
teststeps = [ teststeps = [
Step( Step(
RunRequest("get with params") RunRequest("get with params")
.with_variables( .with_variables(
**{"foo1": "bar1", "foo2": "session_bar2", "sum_v": "${sum_two(1, 2)}"} **{"foo1": "bar11", "foo2": "bar21", "sum_v": "${sum_two(1, 2)}"}
) )
.get("/get") .get("/get")
.with_params(**{"foo1": "$foo1", "foo2": "$foo2", "sum_v": "$sum_v"}) .with_params(**{"foo1": "$foo1", "foo2": "$foo2", "sum_v": "$sum_v"})
.with_headers(**{"User-Agent": "HttpRunner/${get_httprunner_version()}"}) .with_headers(**{"User-Agent": "HttpRunner/${get_httprunner_version()}"})
.extract() .extract()
.with_jmespath("body.args.foo2", "session_foo2") .with_jmespath("body.args.foo2", "foo3")
.validate() .validate()
.assert_equal("status_code", 200) .assert_equal("status_code", 200)
.assert_equal("body.args.foo1", "session_bar1") .assert_equal("body.args.foo1", "bar11")
.assert_equal("body.args.sum_v", "3") .assert_equal("body.args.sum_v", "3")
.assert_equal("body.args.foo2", "session_bar2") .assert_equal("body.args.foo2", "bar21")
), ),
Step( Step(
RunRequest("post raw text") RunRequest("post raw text")
.with_variables(**{"foo1": "hello world", "foo3": "$session_foo2"}) .with_variables(**{"foo1": "bar12", "foo3": "bar32"})
.post("/post") .post("/post")
.with_headers( .with_headers(
**{ **{
@@ -41,18 +48,18 @@ class TestCaseRequestWithFunctions(HttpRunner):
} }
) )
.with_data( .with_data(
"This is expected to be sent back as part of response body: $foo1-$foo3." "This is expected to be sent back as part of response body: $foo1-$foo2-$foo3."
) )
.validate() .validate()
.assert_equal("status_code", 200) .assert_equal("status_code", 200)
.assert_equal( .assert_equal(
"body.data", "body.data",
"This is expected to be sent back as part of response body: session_bar1-session_bar2.", "This is expected to be sent back as part of response body: bar12-$expect_foo2-bar21.",
) )
), ),
Step( Step(
RunRequest("post form data") RunRequest("post form data")
.with_variables(**{"foo1": "bar1", "foo2": "bar2"}) .with_variables(**{"foo2": "bar23"})
.post("/post") .post("/post")
.with_headers( .with_headers(
**{ **{
@@ -60,11 +67,12 @@ class TestCaseRequestWithFunctions(HttpRunner):
"Content-Type": "application/x-www-form-urlencoded", "Content-Type": "application/x-www-form-urlencoded",
} }
) )
.with_data("foo1=$foo1&foo2=$foo2") .with_data("foo1=$foo1&foo2=$foo2&foo3=$foo3")
.validate() .validate()
.assert_equal("status_code", 200) .assert_equal("status_code", 200)
.assert_equal("body.form.foo1", "session_bar1") .assert_equal("body.form.foo1", "$expect_foo1")
.assert_equal("body.form.foo2", "bar2") .assert_equal("body.form.foo2", "bar23")
.assert_equal("body.form.foo3", "bar21")
), ),
] ]

View File

@@ -1,4 +1,4 @@
# NOTE: Generated By HttpRunner v3.0.10 # NOTE: Generated By HttpRunner v3.0.11
# FROM: examples/postman_echo/request_methods/request_with_testcase_reference.yml # FROM: examples/postman_echo/request_methods/request_with_testcase_reference.yml
import os import os
@@ -16,7 +16,14 @@ from examples.postman_echo.request_methods.request_with_functions_test import (
class TestCaseRequestWithTestcaseReference(HttpRunner): class TestCaseRequestWithTestcaseReference(HttpRunner):
config = ( config = (
Config("request with referenced testcase") Config("request with referenced testcase")
.variables(**{"var2": "testsuite_val2", "foo1": "session_bar1"}) .variables(
**{
"foo1": "testcase_ref_bar12",
"expect_foo1": "testcase_ref_bar12",
"expect_foo2": "testcase_ref_bar22",
"foo2": "testcase_ref_bar22",
}
)
.base_url("https://postman-echo.com") .base_url("https://postman-echo.com")
.verify(False) .verify(False)
) )
@@ -24,9 +31,11 @@ class TestCaseRequestWithTestcaseReference(HttpRunner):
teststeps = [ teststeps = [
Step( Step(
RunTestCase("request with functions") RunTestCase("request with functions")
.with_variables(**{"foo1": "override_bar1"}) .with_variables(
**{"foo1": "testcase_ref_bar1", "expect_foo1": "testcase_ref_bar1"}
)
.call(RequestWithFunctions) .call(RequestWithFunctions)
.export(*["session_foo2"]) .export(*["foo3"])
), ),
Step( Step(
RunRequest("post form data") RunRequest("post form data")
@@ -38,11 +47,11 @@ class TestCaseRequestWithTestcaseReference(HttpRunner):
"Content-Type": "application/x-www-form-urlencoded", "Content-Type": "application/x-www-form-urlencoded",
} }
) )
.with_data("foo1=$foo1&foo2=$session_foo2") .with_data("foo1=$foo1&foo2=$foo3")
.validate() .validate()
.assert_equal("status_code", 200) .assert_equal("status_code", 200)
.assert_equal("body.form.foo1", "session_bar1") .assert_equal("body.form.foo1", "bar1")
.assert_equal("body.form.foo2", "session_bar2") .assert_equal("body.form.foo2", "bar21")
), ),
] ]

View File

@@ -1,4 +1,4 @@
# NOTE: Generated By HttpRunner v3.0.10 # NOTE: Generated By HttpRunner v3.0.11
# FROM: examples/postman_echo/request_methods/hardcode.yml # FROM: examples/postman_echo/request_methods/hardcode.yml
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase

View File

@@ -1,17 +1,20 @@
config: config:
name: "request methods testcase with functions" name: "request methods testcase with functions"
variables: variables:
foo1: session_bar1 foo1: config_bar1
foo2: config_bar2
expect_foo1: config_bar1
expect_foo2: config_bar2
base_url: "https://postman-echo.com" base_url: "https://postman-echo.com"
verify: False verify: False
export: ["session_foo2"] export: ["foo3"]
teststeps: teststeps:
- -
name: get with params name: get with params
variables: variables:
foo1: bar1 foo1: bar11
foo2: session_bar2 foo2: bar21
sum_v: "${sum_two(1, 2)}" sum_v: "${sum_two(1, 2)}"
request: request:
method: GET method: GET
@@ -23,40 +26,40 @@ teststeps:
headers: headers:
User-Agent: HttpRunner/${get_httprunner_version()} User-Agent: HttpRunner/${get_httprunner_version()}
extract: extract:
session_foo2: "body.args.foo2" foo3: "body.args.foo2"
validate: validate:
- eq: ["status_code", 200] - eq: ["status_code", 200]
- eq: ["body.args.foo1", "session_bar1"] - eq: ["body.args.foo1", "bar11"]
- eq: ["body.args.sum_v", "3"] - eq: ["body.args.sum_v", "3"]
- eq: ["body.args.foo2", "session_bar2"] - eq: ["body.args.foo2", "bar21"]
- -
name: post raw text name: post raw text
variables: variables:
foo1: "hello world" foo1: "bar12"
foo3: "$session_foo2" foo3: "bar32"
request: request:
method: POST method: POST
url: /post url: /post
headers: headers:
User-Agent: HttpRunner/${get_httprunner_version()} User-Agent: HttpRunner/${get_httprunner_version()}
Content-Type: "text/plain" Content-Type: "text/plain"
data: "This is expected to be sent back as part of response body: $foo1-$foo3." data: "This is expected to be sent back as part of response body: $foo1-$foo2-$foo3."
validate: validate:
- eq: ["status_code", 200] - eq: ["status_code", 200]
- eq: ["body.data", "This is expected to be sent back as part of response body: session_bar1-session_bar2."] - eq: ["body.data", "This is expected to be sent back as part of response body: bar12-$expect_foo2-bar21."]
- -
name: post form data name: post form data
variables: variables:
foo1: bar1 foo2: bar23
foo2: bar2
request: request:
method: POST method: POST
url: /post url: /post
headers: headers:
User-Agent: HttpRunner/${get_httprunner_version()} User-Agent: HttpRunner/${get_httprunner_version()}
Content-Type: "application/x-www-form-urlencoded" Content-Type: "application/x-www-form-urlencoded"
data: "foo1=$foo1&foo2=$foo2" data: "foo1=$foo1&foo2=$foo2&foo3=$foo3"
validate: validate:
- eq: ["status_code", 200] - eq: ["status_code", 200]
- eq: ["body.form.foo1", "session_bar1"] - eq: ["body.form.foo1", "$expect_foo1"]
- eq: ["body.form.foo2", "bar2"] - eq: ["body.form.foo2", "bar23"]
- eq: ["body.form.foo3", "bar21"]

View File

@@ -1,4 +1,4 @@
# NOTE: Generated By HttpRunner v3.0.10 # NOTE: Generated By HttpRunner v3.0.11
# FROM: examples/postman_echo/request_methods/request_with_functions.yml # FROM: examples/postman_echo/request_methods/request_with_functions.yml
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
@@ -7,32 +7,39 @@ from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
class TestCaseRequestWithFunctions(HttpRunner): class TestCaseRequestWithFunctions(HttpRunner):
config = ( config = (
Config("request methods testcase with functions") Config("request methods testcase with functions")
.variables(**{"foo1": "session_bar1"}) .variables(
**{
"foo1": "config_bar1",
"foo2": "config_bar2",
"expect_foo1": "config_bar1",
"expect_foo2": "config_bar2",
}
)
.base_url("https://postman-echo.com") .base_url("https://postman-echo.com")
.verify(False) .verify(False)
.export(*["session_foo2"]) .export(*["foo3"])
) )
teststeps = [ teststeps = [
Step( Step(
RunRequest("get with params") RunRequest("get with params")
.with_variables( .with_variables(
**{"foo1": "bar1", "foo2": "session_bar2", "sum_v": "${sum_two(1, 2)}"} **{"foo1": "bar11", "foo2": "bar21", "sum_v": "${sum_two(1, 2)}"}
) )
.get("/get") .get("/get")
.with_params(**{"foo1": "$foo1", "foo2": "$foo2", "sum_v": "$sum_v"}) .with_params(**{"foo1": "$foo1", "foo2": "$foo2", "sum_v": "$sum_v"})
.with_headers(**{"User-Agent": "HttpRunner/${get_httprunner_version()}"}) .with_headers(**{"User-Agent": "HttpRunner/${get_httprunner_version()}"})
.extract() .extract()
.with_jmespath("body.args.foo2", "session_foo2") .with_jmespath("body.args.foo2", "foo3")
.validate() .validate()
.assert_equal("status_code", 200) .assert_equal("status_code", 200)
.assert_equal("body.args.foo1", "session_bar1") .assert_equal("body.args.foo1", "bar11")
.assert_equal("body.args.sum_v", "3") .assert_equal("body.args.sum_v", "3")
.assert_equal("body.args.foo2", "session_bar2") .assert_equal("body.args.foo2", "bar21")
), ),
Step( Step(
RunRequest("post raw text") RunRequest("post raw text")
.with_variables(**{"foo1": "hello world", "foo3": "$session_foo2"}) .with_variables(**{"foo1": "bar12", "foo3": "bar32"})
.post("/post") .post("/post")
.with_headers( .with_headers(
**{ **{
@@ -41,18 +48,18 @@ class TestCaseRequestWithFunctions(HttpRunner):
} }
) )
.with_data( .with_data(
"This is expected to be sent back as part of response body: $foo1-$foo3." "This is expected to be sent back as part of response body: $foo1-$foo2-$foo3."
) )
.validate() .validate()
.assert_equal("status_code", 200) .assert_equal("status_code", 200)
.assert_equal( .assert_equal(
"body.data", "body.data",
"This is expected to be sent back as part of response body: session_bar1-session_bar2.", "This is expected to be sent back as part of response body: bar12-$expect_foo2-bar21.",
) )
), ),
Step( Step(
RunRequest("post form data") RunRequest("post form data")
.with_variables(**{"foo1": "bar1", "foo2": "bar2"}) .with_variables(**{"foo2": "bar23"})
.post("/post") .post("/post")
.with_headers( .with_headers(
**{ **{
@@ -60,11 +67,12 @@ class TestCaseRequestWithFunctions(HttpRunner):
"Content-Type": "application/x-www-form-urlencoded", "Content-Type": "application/x-www-form-urlencoded",
} }
) )
.with_data("foo1=$foo1&foo2=$foo2") .with_data("foo1=$foo1&foo2=$foo2&foo3=$foo3")
.validate() .validate()
.assert_equal("status_code", 200) .assert_equal("status_code", 200)
.assert_equal("body.form.foo1", "session_bar1") .assert_equal("body.form.foo1", "$expect_foo1")
.assert_equal("body.form.foo2", "bar2") .assert_equal("body.form.foo2", "bar23")
.assert_equal("body.form.foo3", "bar21")
), ),
] ]

View File

@@ -1,7 +1,9 @@
config: config:
name: "request methods testcase: reference testcase" name: "request methods testcase: reference testcase"
variables: variables:
foo1: session_bar1 foo1: testsuite_config_bar1
expect_foo1: testsuite_config_bar1
expect_foo2: config_bar2
base_url: "https://postman-echo.com" base_url: "https://postman-echo.com"
verify: False verify: False
@@ -9,10 +11,11 @@ teststeps:
- -
name: request with functions name: request with functions
variables: variables:
foo1: override_bar1 foo1: testcase_ref_bar1
expect_foo1: testcase_ref_bar1
testcase: request_methods/request_with_functions.yml testcase: request_methods/request_with_functions.yml
export: export:
- session_foo2 - foo3
- -
name: post form data name: post form data
variables: variables:
@@ -23,8 +26,8 @@ teststeps:
headers: headers:
User-Agent: HttpRunner/${get_httprunner_version()} User-Agent: HttpRunner/${get_httprunner_version()}
Content-Type: "application/x-www-form-urlencoded" Content-Type: "application/x-www-form-urlencoded"
data: "foo1=$foo1&foo2=$session_foo2" data: "foo1=$foo1&foo2=$foo3"
validate: validate:
- eq: ["status_code", 200] - eq: ["status_code", 200]
- eq: ["body.form.foo1", "session_bar1"] - eq: ["body.form.foo1", "bar1"]
- eq: ["body.form.foo2", "session_bar2"] - eq: ["body.form.foo2", "bar21"]

View File

@@ -1,4 +1,4 @@
# NOTE: Generated By HttpRunner v3.0.10 # NOTE: Generated By HttpRunner v3.0.11
# FROM: examples/postman_echo/request_methods/request_with_testcase_reference.yml # FROM: examples/postman_echo/request_methods/request_with_testcase_reference.yml
import os import os
@@ -16,7 +16,13 @@ from examples.postman_echo.request_methods.request_with_functions_test import (
class TestCaseRequestWithTestcaseReference(HttpRunner): class TestCaseRequestWithTestcaseReference(HttpRunner):
config = ( config = (
Config("request methods testcase: reference testcase") Config("request methods testcase: reference testcase")
.variables(**{"foo1": "session_bar1"}) .variables(
**{
"foo1": "testsuite_config_bar1",
"expect_foo1": "testsuite_config_bar1",
"expect_foo2": "config_bar2",
}
)
.base_url("https://postman-echo.com") .base_url("https://postman-echo.com")
.verify(False) .verify(False)
) )
@@ -24,9 +30,11 @@ class TestCaseRequestWithTestcaseReference(HttpRunner):
teststeps = [ teststeps = [
Step( Step(
RunTestCase("request with functions") RunTestCase("request with functions")
.with_variables(**{"foo1": "override_bar1"}) .with_variables(
**{"foo1": "testcase_ref_bar1", "expect_foo1": "testcase_ref_bar1"}
)
.call(RequestWithFunctions) .call(RequestWithFunctions)
.export(*["session_foo2"]) .export(*["foo3"])
), ),
Step( Step(
RunRequest("post form data") RunRequest("post form data")
@@ -38,11 +46,11 @@ class TestCaseRequestWithTestcaseReference(HttpRunner):
"Content-Type": "application/x-www-form-urlencoded", "Content-Type": "application/x-www-form-urlencoded",
} }
) )
.with_data("foo1=$foo1&foo2=$session_foo2") .with_data("foo1=$foo1&foo2=$foo3")
.validate() .validate()
.assert_equal("status_code", 200) .assert_equal("status_code", 200)
.assert_equal("body.form.foo1", "session_bar1") .assert_equal("body.form.foo1", "bar1")
.assert_equal("body.form.foo2", "session_bar2") .assert_equal("body.form.foo2", "bar21")
), ),
] ]

View File

@@ -1,6 +1,6 @@
config: config:
name: "request methods testcase with variables" name: "request methods testcase with variables"
variables: ${get_variables()} variables: ${get_testcase_config_variables()}
base_url: "https://postman-echo.com" base_url: "https://postman-echo.com"
verify: False verify: False
@@ -8,8 +8,8 @@ teststeps:
- -
name: get with params name: get with params
variables: variables:
foo1: bar1 foo1: bar11
foo2: session_bar2 foo2: bar21
request: request:
method: GET method: GET
url: /get url: /get
@@ -19,39 +19,39 @@ teststeps:
headers: headers:
User-Agent: HttpRunner/3.0 User-Agent: HttpRunner/3.0
extract: extract:
session_foo2: "body.args.foo2" foo3: "body.args.foo2"
validate: validate:
- eq: ["status_code", 200] - eq: ["status_code", 200]
- eq: ["body.args.foo1", "session_bar1"] - eq: ["body.args.foo1", "bar11"]
- eq: ["body.args.foo2", "session_bar2"] - eq: ["body.args.foo2", "bar21"]
- -
name: post raw text name: post raw text
variables: variables:
foo1: "hello world" foo1: "bar12"
foo3: "$session_foo2" foo3: "bar32"
request: request:
method: POST method: POST
url: /post url: /post
headers: headers:
User-Agent: HttpRunner/3.0 User-Agent: HttpRunner/3.0
Content-Type: "text/plain" Content-Type: "text/plain"
data: "This is expected to be sent back as part of response body: $foo1-$foo3." data: "This is expected to be sent back as part of response body: $foo1-$foo2-$foo3."
validate: validate:
- eq: ["status_code", 200] - eq: ["status_code", 200]
- eq: ["body.data", "This is expected to be sent back as part of response body: session_bar1-session_bar2."] - eq: ["body.data", "This is expected to be sent back as part of response body: bar12-testcase_config_bar2-bar21."]
- -
name: post form data name: post form data
variables: variables:
foo1: bar1 foo2: bar23
foo2: bar2
request: request:
method: POST method: POST
url: /post url: /post
headers: headers:
User-Agent: HttpRunner/3.0 User-Agent: HttpRunner/3.0
Content-Type: "application/x-www-form-urlencoded" Content-Type: "application/x-www-form-urlencoded"
data: "foo1=$foo1&foo2=$foo2" data: "foo1=$foo1&foo2=$foo2&foo3=$foo3"
validate: validate:
- eq: ["status_code", 200] - eq: ["status_code", 200]
- eq: ["body.form.foo1", "session_bar1"] - eq: ["body.form.foo1", "testcase_config_bar1"]
- eq: ["body.form.foo2", "bar2"] - eq: ["body.form.foo2", "bar23"]
- eq: ["body.form.foo3", "bar21"]

View File

@@ -1,4 +1,4 @@
# NOTE: Generated By HttpRunner v3.0.10 # NOTE: Generated By HttpRunner v3.0.11
# FROM: examples/postman_echo/request_methods/request_with_variables.yml # FROM: examples/postman_echo/request_methods/request_with_variables.yml
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
@@ -7,7 +7,7 @@ from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
class TestCaseRequestWithVariables(HttpRunner): class TestCaseRequestWithVariables(HttpRunner):
config = ( config = (
Config("request methods testcase with variables") Config("request methods testcase with variables")
.variables(**{"foo1": "session_bar1"}) .variables(**{"foo1": "testcase_config_bar1", "foo2": "testcase_config_bar2"})
.base_url("https://postman-echo.com") .base_url("https://postman-echo.com")
.verify(False) .verify(False)
) )
@@ -15,37 +15,37 @@ class TestCaseRequestWithVariables(HttpRunner):
teststeps = [ teststeps = [
Step( Step(
RunRequest("get with params") RunRequest("get with params")
.with_variables(**{"foo1": "bar1", "foo2": "session_bar2"}) .with_variables(**{"foo1": "bar11", "foo2": "bar21"})
.get("/get") .get("/get")
.with_params(**{"foo1": "$foo1", "foo2": "$foo2"}) .with_params(**{"foo1": "$foo1", "foo2": "$foo2"})
.with_headers(**{"User-Agent": "HttpRunner/3.0"}) .with_headers(**{"User-Agent": "HttpRunner/3.0"})
.extract() .extract()
.with_jmespath("body.args.foo2", "session_foo2") .with_jmespath("body.args.foo2", "foo3")
.validate() .validate()
.assert_equal("status_code", 200) .assert_equal("status_code", 200)
.assert_equal("body.args.foo1", "session_bar1") .assert_equal("body.args.foo1", "bar11")
.assert_equal("body.args.foo2", "session_bar2") .assert_equal("body.args.foo2", "bar21")
), ),
Step( Step(
RunRequest("post raw text") RunRequest("post raw text")
.with_variables(**{"foo1": "hello world", "foo3": "$session_foo2"}) .with_variables(**{"foo1": "bar12", "foo3": "bar32"})
.post("/post") .post("/post")
.with_headers( .with_headers(
**{"User-Agent": "HttpRunner/3.0", "Content-Type": "text/plain"} **{"User-Agent": "HttpRunner/3.0", "Content-Type": "text/plain"}
) )
.with_data( .with_data(
"This is expected to be sent back as part of response body: $foo1-$foo3." "This is expected to be sent back as part of response body: $foo1-$foo2-$foo3."
) )
.validate() .validate()
.assert_equal("status_code", 200) .assert_equal("status_code", 200)
.assert_equal( .assert_equal(
"body.data", "body.data",
"This is expected to be sent back as part of response body: session_bar1-session_bar2.", "This is expected to be sent back as part of response body: bar12-testcase_config_bar2-bar21.",
) )
), ),
Step( Step(
RunRequest("post form data") RunRequest("post form data")
.with_variables(**{"foo1": "bar1", "foo2": "bar2"}) .with_variables(**{"foo2": "bar23"})
.post("/post") .post("/post")
.with_headers( .with_headers(
**{ **{
@@ -53,11 +53,12 @@ class TestCaseRequestWithVariables(HttpRunner):
"Content-Type": "application/x-www-form-urlencoded", "Content-Type": "application/x-www-form-urlencoded",
} }
) )
.with_data("foo1=$foo1&foo2=$foo2") .with_data("foo1=$foo1&foo2=$foo2&foo3=$foo3")
.validate() .validate()
.assert_equal("status_code", 200) .assert_equal("status_code", 200)
.assert_equal("body.form.foo1", "session_bar1") .assert_equal("body.form.foo1", "testcase_config_bar1")
.assert_equal("body.form.foo2", "bar2") .assert_equal("body.form.foo2", "bar23")
.assert_equal("body.form.foo3", "bar21")
), ),
] ]

View File

@@ -26,4 +26,4 @@ teststeps:
validate: validate:
- eq: ["status_code", 200] - eq: ["status_code", 200]
- eq: ["body.args.sum_v", "3"] - eq: ["body.args.sum_v", "3"]
# - less_than: ["body.args.sum_v", "${sum_two(2, 2)}"] TODO # - less_than: ["body.args.sum_v", "${sum_two(2, 2)}"] FIXME: TypeError: '<' not supported between instances of 'str' and 'int'

View File

@@ -1,4 +1,4 @@
# NOTE: Generated By HttpRunner v3.0.10 # NOTE: Generated By HttpRunner v3.0.11
# FROM: examples/postman_echo/request_methods/validate_with_functions.yml # FROM: examples/postman_echo/request_methods/validate_with_functions.yml
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase

View File

@@ -39,7 +39,7 @@ teststeps:
data: "This is expected to be sent back as part of response body: $foo1-$foo3." data: "This is expected to be sent back as part of response body: $foo1-$foo3."
validate: validate:
- eq: ["status_code", 200] - eq: ["status_code", 200]
- eq: ["body.data", "This is expected to be sent back as part of response body: session_bar1-$foo3."] - eq: ["body.data", "This is expected to be sent back as part of response body: hello world-$foo3."]
- -
name: post form data name: post form data
variables: variables:

View File

@@ -1,4 +1,4 @@
# NOTE: Generated By HttpRunner v3.0.10 # NOTE: Generated By HttpRunner v3.0.11
# FROM: examples/postman_echo/request_methods/validate_with_variables.yml # FROM: examples/postman_echo/request_methods/validate_with_variables.yml
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
@@ -40,7 +40,7 @@ class TestCaseValidateWithVariables(HttpRunner):
.assert_equal("status_code", 200) .assert_equal("status_code", 200)
.assert_equal( .assert_equal(
"body.data", "body.data",
"This is expected to be sent back as part of response body: session_bar1-$foo3.", "This is expected to be sent back as part of response body: hello world-$foo3.",
) )
), ),
Step( Step(

View File

@@ -1,4 +1,4 @@
__version__ = "3.0.10" __version__ = "3.0.11"
__description__ = "One-stop solution for HTTP(S) testing." __description__ = "One-stop solution for HTTP(S) testing."
from httprunner.runner import HttpRunner from httprunner.runner import HttpRunner

View File

@@ -53,6 +53,7 @@ def main_run(extra_args) -> enum.IntEnum:
extra_args_new.append("--tb=short") extra_args_new.append("--tb=short")
extra_args_new.extend(testcase_path_list) extra_args_new.extend(testcase_path_list)
logger.info(f"start to run tests with pytest. HttpRunner version: {__version__}")
return pytest.main(extra_args_new) return pytest.main(extra_args_new)

View File

@@ -371,6 +371,8 @@ def load_debugtalk_functions() -> Dict[Text, Callable]:
""" """
# load debugtalk.py module # load debugtalk.py module
imported_module = importlib.import_module("debugtalk") imported_module = importlib.import_module("debugtalk")
# reload to refresh previously loaded module
imported_module = importlib.reload(imported_module)
return load_module_functions(imported_module) return load_module_functions(imported_module)

View File

@@ -21,9 +21,8 @@ from httprunner.loader import (
load_testsuite, load_testsuite,
load_project_meta, load_project_meta,
) )
from httprunner.parser import parse_data
from httprunner.response import uniform_validator from httprunner.response import uniform_validator
from httprunner.utils import ensure_file_path_valid from httprunner.utils import ensure_file_path_valid, override_config_variables
""" cache converted pytest files, avoid duplicate making """ cache converted pytest files, avoid duplicate making
""" """
@@ -407,11 +406,18 @@ def make_testsuite(testsuite: Dict) -> NoReturn:
if "verify" in testsuite_config: if "verify" in testsuite_config:
testcase_dict["config"]["verify"] = testsuite_config["verify"] testcase_dict["config"]["verify"] = testsuite_config["verify"]
# override variables # override variables
# testsuite testcase variables > testsuite config variables
testcase_variables = convert_variables( testcase_variables = convert_variables(
testcase.get("variables", {}), testcase_path testcase.get("variables", {}), testcase_path
) )
testcase_variables.update(testsuite_variables) testcase_variables = override_config_variables(
testcase_dict["config"]["variables"] = testcase_variables testcase_variables, testsuite_variables
)
# testsuite testcase variables > testcase config variables
testcase_dict["config"]["variables"] = convert_variables(
testcase_dict["config"].get("variables", {}), testcase_path
)
testcase_dict["config"]["variables"].update(testcase_variables)
# make testcase # make testcase
testcase_pytest_path = make_testcase(testcase_dict, testsuite_dir) testcase_pytest_path = make_testcase(testcase_dict, testsuite_dir)
@@ -447,18 +453,18 @@ def __make(tests_path: Text) -> NoReturn:
continue continue
if not isinstance(test_content, Dict): if not isinstance(test_content, Dict):
raise exceptions.FileFormatError( logger.warning(f"test content not in dict format. \npath: {test_file}")
f"test content not in dict format: {test_content}" continue
)
# api in v2 format, convert to v3 testcase # api in v2 format, convert to v3 testcase
if "request" in test_content and "name" in test_content: if "request" in test_content and "name" in test_content:
test_content = ensure_testcase_v3_api(test_content) test_content = ensure_testcase_v3_api(test_content)
if "config" not in test_content: if "config" not in test_content:
raise exceptions.FileFormatError( logger.warning(
f"miss config part in testcase/testsuite: {test_content}" f"Invalid testcase/testsuite: missing config part in testcase/testsuite.\npath: {test_file}"
) )
continue
test_content.setdefault("config", {})["path"] = test_file test_content.setdefault("config", {})["path"] = test_file

View File

@@ -44,11 +44,11 @@ def build_url(base_url, path):
raise exceptions.ParamsError("base url missed!") raise exceptions.ParamsError("base url missed!")
def regex_findall_variables(content: Text) -> List[Text]: def regex_findall_variables(raw_string: Text) -> List[Text]:
""" extract all variable names from content, which is in format $variable """ extract all variable names from content, which is in format $variable
Args: Args:
content (str): string content raw_string (str): string content
Returns: Returns:
list: variables list extracted from string content list: variables list extracted from string content
@@ -68,14 +68,40 @@ def regex_findall_variables(content: Text) -> List[Text]:
""" """
try: try:
vars_list = [] match_start_position = raw_string.index("$", 0)
for var_tuple in variable_regex_compile.findall(content): except ValueError:
vars_list.append(var_tuple[0] or var_tuple[1])
return vars_list
except TypeError as ex:
capture_exception(ex)
return [] return []
vars_list = []
while match_start_position < len(raw_string):
# Notice: notation priority
# $$ > $var
# search $$
dollar_match = dolloar_regex_compile.match(raw_string, match_start_position)
if dollar_match:
match_start_position = dollar_match.end()
continue
# search variable like ${var} or $var
var_match = variable_regex_compile.match(raw_string, match_start_position)
if var_match:
var_name = var_match.group(1) or var_match.group(2)
vars_list.append(var_name)
match_start_position = var_match.end()
continue
curr_position = match_start_position
try:
# find next $ location
match_start_position = raw_string.index("$", curr_position + 1)
except ValueError:
# break while loop
break
return vars_list
def regex_findall_functions(content: Text) -> List[Text]: def regex_findall_functions(content: Text) -> List[Text]:
""" extract all functions from string content, which are in format ${fun()} """ extract all functions from string content, which are in format ${fun()}

View File

@@ -2,7 +2,7 @@ import os
import time import time
import uuid import uuid
from datetime import datetime from datetime import datetime
from typing import List, Dict, Text, NoReturn, Union from typing import List, Dict, Text, NoReturn
try: try:
import allure import allure
@@ -21,6 +21,7 @@ from httprunner.loader import load_project_meta, load_testcase_file
from httprunner.parser import build_url, parse_data, parse_variables_mapping from httprunner.parser import build_url, parse_data, parse_variables_mapping
from httprunner.response import ResponseObject from httprunner.response import ResponseObject
from httprunner.testcase import Config, Step from httprunner.testcase import Config, Step
from httprunner.utils import override_config_variables
from httprunner.models import ( from httprunner.models import (
TConfig, TConfig,
TStep, TStep,
@@ -39,7 +40,7 @@ class HttpRunner(object):
config: Config config: Config
teststeps: List[Step] teststeps: List[Step]
success: bool = True # indicate testcase execution result success: bool = False # indicate testcase execution result
__config: TConfig __config: TConfig
__teststeps: List[TStep] __teststeps: List[TStep]
__project_meta: ProjectMeta = None __project_meta: ProjectMeta = None
@@ -216,7 +217,7 @@ class HttpRunner(object):
finally: finally:
# save request & response meta data # save request & response meta data
self.__session.data.validators = resp_obj.validation_results self.__session.data.validators = resp_obj.validation_results
self.success &= self.__session.data.success self.success = self.__session.data.success
# save step data # save step data
step_data.success = self.__session.data.success step_data.success = self.__session.data.success
step_data.data = self.__session.data step_data.data = self.__session.data
@@ -265,7 +266,7 @@ class HttpRunner(object):
step_data.data = case_result.get_step_datas() # list of step data step_data.data = case_result.get_step_datas() # list of step data
step_data.export_vars = case_result.get_export_variables() step_data.export_vars = case_result.get_export_variables()
step_data.success = case_result.success step_data.success = case_result.success
self.success &= case_result.success self.success = case_result.success
if step_data.export_vars: if step_data.export_vars:
logger.info(f"export variables: {step_data.export_vars}") logger.info(f"export variables: {step_data.export_vars}")
@@ -324,20 +325,26 @@ class HttpRunner(object):
# run teststeps # run teststeps
for step in self.__teststeps: for step in self.__teststeps:
# update with config variables # override variables
step.variables.update(self.__config.variables) # session variables (extracted from pre step) > step variables
# update with session variables extracted from pre step
step.variables.update(self.__session_variables) step.variables.update(self.__session_variables)
# step variables > testcase config variables
step.variables = override_config_variables(
step.variables, self.__config.variables
)
# parse variables # parse variables
step.variables = parse_variables_mapping( step.variables = parse_variables_mapping(
step.variables, self.__project_meta.functions step.variables, self.__project_meta.functions
) )
# run step # run step
if USE_ALLURE: if USE_ALLURE:
with allure.step(f"step: {step.name}"): with allure.step(f"step: {step.name}"):
extract_mapping = self.__run_step(step) extract_mapping = self.__run_step(step)
else: else:
extract_mapping = self.__run_step(step) extract_mapping = self.__run_step(step)
# save extracted variables to session variables # save extracted variables to session variables
self.__session_variables.update(extract_mapping) self.__session_variables.update(extract_mapping)
@@ -413,10 +420,10 @@ class HttpRunner(object):
log_handler = logger.add(self.__log_path, level="DEBUG") log_handler = logger.add(self.__log_path, level="DEBUG")
# parse config name # parse config name
variables = self.__config.variables config_variables = self.__config.variables
variables.update(self.__session_variables) config_variables.update(self.__session_variables)
self.__config.name = parse_data( self.__config.name = parse_data(
self.__config.name, variables, self.__project_meta.functions self.__config.name, config_variables, self.__project_meta.functions
) )
if USE_ALLURE: if USE_ALLURE:

View File

@@ -42,16 +42,20 @@ def create_scaffold(project_name):
config: config:
name: "request methods testcase with functions" name: "request methods testcase with functions"
variables: variables:
foo1: session_bar1 foo1: config_bar1
foo2: config_bar2
expect_foo1: config_bar1
expect_foo2: config_bar2
base_url: "https://postman-echo.com" base_url: "https://postman-echo.com"
verify: False verify: False
export: ["foo3"]
teststeps: teststeps:
- -
name: get with params name: get with params
variables: variables:
foo1: bar1 foo1: bar11
foo2: session_bar2 foo2: bar21
sum_v: "${sum_two(1, 2)}" sum_v: "${sum_two(1, 2)}"
request: request:
method: GET method: GET
@@ -63,43 +67,78 @@ teststeps:
headers: headers:
User-Agent: HttpRunner/${get_httprunner_version()} User-Agent: HttpRunner/${get_httprunner_version()}
extract: extract:
session_foo2: "body.args.foo2" foo3: "body.args.foo2"
validate: validate:
- eq: ["status_code", 200] - eq: ["status_code", 200]
- eq: ["body.args.foo1", "session_bar1"] - eq: ["body.args.foo1", "bar11"]
- eq: ["body.args.sum_v", "3"] - eq: ["body.args.sum_v", "3"]
- eq: ["body.args.foo2", "session_bar2"] - eq: ["body.args.foo2", "bar21"]
- -
name: post raw text name: post raw text
variables: variables:
foo1: "hello world" foo1: "bar12"
foo3: "$session_foo2" foo3: "bar32"
request: request:
method: POST method: POST
url: /post url: /post
headers: headers:
User-Agent: HttpRunner/${get_httprunner_version()} User-Agent: HttpRunner/${get_httprunner_version()}
Content-Type: "text/plain" Content-Type: "text/plain"
data: "This is expected to be sent back as part of response body: $foo1-$foo3." data: "This is expected to be sent back as part of response body: $foo1-$foo2-$foo3."
validate: validate:
- eq: ["status_code", 200] - eq: ["status_code", 200]
- eq: ["body.data", "This is expected to be sent back as part of response body: session_bar1-session_bar2."] - eq: ["body.data", "This is expected to be sent back as part of response body: bar12-$expect_foo2-bar21."]
-
name: post form data
variables:
foo2: bar23
request:
method: POST
url: /post
headers:
User-Agent: HttpRunner/${get_httprunner_version()}
Content-Type: "application/x-www-form-urlencoded"
data: "foo1=$foo1&foo2=$foo2&foo3=$foo3"
validate:
- eq: ["status_code", 200]
- eq: ["body.form.foo1", "$expect_foo1"]
- eq: ["body.form.foo2", "bar23"]
- eq: ["body.form.foo3", "bar21"]
""" """
demo_testcase_with_ref_content = """ demo_testcase_with_ref_content = """
config: config:
name: "request methods testcase: reference testcase" name: "request methods testcase: reference testcase"
variables: variables:
foo1: session_bar1 foo1: testsuite_config_bar1
expect_foo1: testsuite_config_bar1
expect_foo2: config_bar2
base_url: "https://postman-echo.com" base_url: "https://postman-echo.com"
verify: False verify: False
teststeps: teststeps:
- -
name: request with referenced testcase name: request with functions
variables: variables:
foo1: override_bar1 foo1: testcase_ref_bar1
# NOTICE: relative testcase path based on debugtalk.py expect_foo1: testcase_ref_bar1
testcase: testcases/demo_testcase_request.yml testcase: testcases/demo_testcase_request.yml
export:
- foo3
-
name: post form data
variables:
foo1: bar1
request:
method: POST
url: /post
headers:
User-Agent: HttpRunner/${get_httprunner_version()}
Content-Type: "application/x-www-form-urlencoded"
data: "foo1=$foo1&foo2=$foo3"
validate:
- eq: ["status_code", 200]
- eq: ["body.form.foo1", "bar1"]
- eq: ["body.form.foo2", "bar21"]
""" """
ignore_content = "\n".join( ignore_content = "\n".join(
[".env", "reports/*", "__pycache__/*", "*.pyc", ".python-version", "logs/*"] [".env", "reports/*", "__pycache__/*", "*.pyc", ".python-version", "logs/*"]

View File

@@ -1,4 +1,5 @@
import collections import collections
import copy
import json import json
import os.path import os.path
import platform import platform
@@ -11,6 +12,7 @@ from loguru import logger
from httprunner import __version__ from httprunner import __version__
from httprunner import exceptions from httprunner import exceptions
from httprunner.models import VariablesMapping
def init_sentry_sdk(): def init_sentry_sdk():
@@ -223,3 +225,23 @@ class ExtendJSONEncoder(json.JSONEncoder):
return super(ExtendJSONEncoder, self).default(obj) return super(ExtendJSONEncoder, self).default(obj)
except (UnicodeDecodeError, TypeError): except (UnicodeDecodeError, TypeError):
return repr(obj) return repr(obj)
def override_config_variables(
step_variables: VariablesMapping, config_variables: VariablesMapping
) -> VariablesMapping:
""" override variables:
testcase step variables > testcase config variables
testsuite testcase variables > testsuite config variables
"""
step_new_variables = {}
for key, value in step_variables.items():
if f"${key}" == value:
# e.g. {"base_url": "$base_url"}
continue
step_new_variables[key] = value
variables = copy.deepcopy(config_variables)
variables.update(step_new_variables)
return variables

View File

@@ -3,7 +3,7 @@
# $ pip install mkdocs-material # 5.2.2 # $ pip install mkdocs-material # 5.2.2
# Project information # Project information
site_name: HttpRunner V3.x 中文使用文档 site_name: HttpRunner V3.x Docs
site_description: HttpRunner V3.x User Documentation site_description: HttpRunner V3.x User Documentation
site_author: 'debugtalk' site_author: 'debugtalk'
@@ -28,7 +28,7 @@ theme:
# Google Analytics # Google Analytics
google_analytics: google_analytics:
- 'UA-114587036-2' - 'UA-114587036-3'
- 'auto' - 'auto'
# Extensions # Extensions

View File

@@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "httprunner" name = "httprunner"
version = "3.0.10" version = "3.0.11"
description = "One-stop solution for HTTP(S) testing." description = "One-stop solution for HTTP(S) testing."
license = "Apache-2.0" license = "Apache-2.0"
readme = "README.md" readme = "README.md"

View File

@@ -1,11 +1,14 @@
import os import os
import unittest import unittest
from httprunner import compat, exceptions from httprunner import compat, exceptions, loader
from httprunner.compat import convert_variables from httprunner.compat import convert_variables
class TestCompat(unittest.TestCase): class TestCompat(unittest.TestCase):
def setUp(self):
loader.project_meta = None
def test_convert_variables(self): def test_convert_variables(self):
raw_variables = [{"var1": 1}, {"var2": "val2"}] raw_variables = [{"var1": 1}, {"var2": "val2"}]
self.assertEqual( self.assertEqual(

View File

@@ -1,7 +1,8 @@
config: config:
name: "request methods testcase with functions" name: "request methods testcase with functions"
variables: variables:
foo1: session_bar1 foo1: config_bar1
foo2: config_bar2
base_url: "https://postman-echo.com" base_url: "https://postman-echo.com"
verify: False verify: False
@@ -10,7 +11,6 @@ teststeps:
name: get with params name: get with params
variables: variables:
foo1: bar1 foo1: bar1
foo2: session_bar2
sum_v: "${sum_two(1, 2)}" sum_v: "${sum_two(1, 2)}"
request: request:
method: GET method: GET
@@ -25,6 +25,6 @@ teststeps:
session_foo2: "body.args.foo2" session_foo2: "body.args.foo2"
validate: validate:
- eq: ["status_code", 200] - eq: ["status_code", 200]
- eq: ["body.args.foo1", "session_bar1"] - eq: ["body.args.foo1", "bar1"]
- eq: ["body.args.sum_v", "3"] - eq: ["body.args.sum_v", "3"]
- eq: ["body.args.foo2", "session_bar2"] - eq: ["body.args.foo2", "config_bar2"]

View File

@@ -1,22 +1,18 @@
config: config:
name: "reference testcase unittest for abnormal folder path" name: "reference testcase unittest for abnormal folder path"
variables:
foo1: session_bar1
base_url: "https://postman-echo.com" base_url: "https://postman-echo.com"
verify: False verify: False
teststeps: teststeps:
- -
name: request with functions name: request with functions
variables:
foo1: override_bar1
testcase: 1.yml testcase: 1.yml
export: export:
- session_foo2 - session_foo2
- -
name: post form data name: post form data
variables: variables:
foo1: bar1 foo1: bar12
request: request:
method: POST method: POST
url: /post url: /post
@@ -26,5 +22,5 @@ teststeps:
data: "foo1=$foo1&foo2=$session_foo2" data: "foo1=$foo1&foo2=$session_foo2"
validate: validate:
- eq: ["status_code", 200] - eq: ["status_code", 200]
- eq: ["body.form.foo1", "session_bar1"] - eq: ["body.form.foo1", "bar12"]
- eq: ["body.form.foo2", "session_bar2"] - eq: ["body.form.foo2", "config_bar2"]

View File

@@ -3,6 +3,7 @@ import unittest
from httprunner import parser from httprunner import parser
from httprunner.exceptions import VariableNotFound, FunctionNotFound from httprunner.exceptions import VariableNotFound, FunctionNotFound
from httprunner.parser import regex_findall_variables
class TestParserBasic(unittest.TestCase): class TestParserBasic(unittest.TestCase):
@@ -25,6 +26,19 @@ class TestParserBasic(unittest.TestCase):
self.assertEqual(parser.parse_string_value("$var"), "$var") self.assertEqual(parser.parse_string_value("$var"), "$var")
self.assertEqual(parser.parse_string_value("${func}"), "${func}") self.assertEqual(parser.parse_string_value("${func}"), "${func}")
def test_regex_findall_variables(self):
self.assertEqual(regex_findall_variables("$variable"), ["variable"])
self.assertEqual(regex_findall_variables("${variable}123"), ["variable"])
self.assertEqual(regex_findall_variables("/blog/$postid"), ["postid"])
self.assertEqual(regex_findall_variables("/$var1/$var2"), ["var1", "var2"])
self.assertEqual(regex_findall_variables("abc"), [])
self.assertEqual(regex_findall_variables("Z:2>1*0*1+1$a"), ["a"])
self.assertEqual(regex_findall_variables("Z:2>1*0*1+1$$a"), [])
self.assertEqual(regex_findall_variables("Z:2>1*0*1+1$$$a"), ["a"])
self.assertEqual(regex_findall_variables("Z:2>1*0*1+1$$$$a"), [])
self.assertEqual(regex_findall_variables("Z:2>1*0*1+1$$a$b"), ["b"])
self.assertEqual(regex_findall_variables("Z:2>1*0*1+1$$a$$b"), [])
def test_extract_variables(self): def test_extract_variables(self):
self.assertEqual(parser.extract_variables("$var"), {"var"}) self.assertEqual(parser.extract_variables("$var"), {"var"})
self.assertEqual(parser.extract_variables("$var123"), {"var123"}) self.assertEqual(parser.extract_variables("$var123"), {"var123"})
@@ -40,6 +54,7 @@ class TestParserBasic(unittest.TestCase):
parser.extract_variables("${gen_md5($TOKEN, $data, $random)}"), parser.extract_variables("${gen_md5($TOKEN, $data, $random)}"),
{"TOKEN", "data", "random"}, {"TOKEN", "data", "random"},
) )
self.assertEqual(parser.extract_variables("Z:2>1*0*1+1$$1"), set())
def test_parse_function_params(self): def test_parse_function_params(self):
self.assertEqual(parser.parse_function_params(""), {"args": [], "kwargs": {}}) self.assertEqual(parser.parse_function_params(""), {"args": [], "kwargs": {}})

View File

@@ -4,7 +4,11 @@ import os
import unittest import unittest
from httprunner import loader, utils from httprunner import loader, utils
from httprunner.utils import ensure_file_path_valid, ExtendJSONEncoder from httprunner.utils import (
ensure_file_path_valid,
ExtendJSONEncoder,
override_config_variables,
)
class TestUtils(unittest.TestCase): class TestUtils(unittest.TestCase):
@@ -129,3 +133,11 @@ class TestUtils(unittest.TestCase):
json.dumps(data) json.dumps(data)
json.dumps(data, cls=ExtendJSONEncoder) json.dumps(data, cls=ExtendJSONEncoder)
def test_override_config_variables(self):
step_variables = {"base_url": "$base_url", "foo1": "bar1"}
config_variables = {"base_url": "https://httpbin.org", "foo1": "bar111"}
self.assertEqual(
override_config_variables(step_variables, config_variables),
{"base_url": "https://httpbin.org", "foo1": "bar1"},
)