mirror of
https://github.com/httprunner/httprunner.git
synced 2026-08-28 11:36:56 +08:00
Merge pull request #975 from httprunner/dev
## 3.1.4 (2020-07-30) **Changed** - change: override variables strategy, step variables > extracted variables from previous steps **Fixed** - fix: parameters feature with custom functions - fix: request json field with variable reference - fix: pickle BufferedReader TypeError in upload feature
This commit is contained in:
@@ -1,5 +1,17 @@
|
|||||||
# Release History
|
# Release History
|
||||||
|
|
||||||
|
## 3.1.4 (2020-07-30)
|
||||||
|
|
||||||
|
**Changed**
|
||||||
|
|
||||||
|
- change: override variables strategy, step variables > extracted variables from previous steps
|
||||||
|
|
||||||
|
**Fixed**
|
||||||
|
|
||||||
|
- fix: parameters feature with custom functions
|
||||||
|
- fix: request json field with variable reference
|
||||||
|
- fix: pickle BufferedReader TypeError in upload feature
|
||||||
|
|
||||||
## 3.1.3 (2020-07-06)
|
## 3.1.3 (2020-07-06)
|
||||||
|
|
||||||
**Added**
|
**Added**
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.3
|
# NOTE: Generated By HttpRunner v3.1.4
|
||||||
# FROM: basic.yml
|
# FROM: basic.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.3
|
# NOTE: Generated By HttpRunner v3.1.4
|
||||||
# FROM: hooks.yml
|
# FROM: hooks.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.3
|
# NOTE: Generated By HttpRunner v3.1.4
|
||||||
# FROM: load_image.yml
|
# FROM: load_image.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.3
|
# NOTE: Generated By HttpRunner v3.1.4
|
||||||
# FROM: upload.yml
|
# FROM: upload.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.3
|
# NOTE: Generated By HttpRunner v3.1.4
|
||||||
# FROM: validate.yml
|
# FROM: validate.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
# NOTICE: Generated By HttpRunner.
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
from httprunner.utils import get_platform, ExtendJSONEncoder
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session", autouse=True)
|
||||||
|
def session_fixture(request):
|
||||||
|
"""setup and teardown each task"""
|
||||||
|
logger.info(f"start running testcases ...")
|
||||||
|
|
||||||
|
start_at = time.time()
|
||||||
|
|
||||||
|
yield
|
||||||
|
|
||||||
|
logger.info(f"task finished, generate task summary for --save-tests")
|
||||||
|
|
||||||
|
summary = {
|
||||||
|
"success": True,
|
||||||
|
"stat": {
|
||||||
|
"testcases": {"total": 0, "success": 0, "fail": 0},
|
||||||
|
"teststeps": {"total": 0, "failures": 0, "successes": 0},
|
||||||
|
},
|
||||||
|
"time": {"start_at": start_at, "duration": time.time() - start_at},
|
||||||
|
"platform": get_platform(),
|
||||||
|
"details": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
for item in request.node.items:
|
||||||
|
testcase_summary = item.instance.get_summary()
|
||||||
|
summary["success"] &= testcase_summary.success
|
||||||
|
|
||||||
|
summary["stat"]["testcases"]["total"] += 1
|
||||||
|
summary["stat"]["teststeps"]["total"] += len(testcase_summary.step_datas)
|
||||||
|
if testcase_summary.success:
|
||||||
|
summary["stat"]["testcases"]["success"] += 1
|
||||||
|
summary["stat"]["teststeps"]["successes"] += len(
|
||||||
|
testcase_summary.step_datas
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
summary["stat"]["testcases"]["fail"] += 1
|
||||||
|
summary["stat"]["teststeps"]["successes"] += (
|
||||||
|
len(testcase_summary.step_datas) - 1
|
||||||
|
)
|
||||||
|
summary["stat"]["teststeps"]["failures"] += 1
|
||||||
|
|
||||||
|
testcase_summary_json = testcase_summary.dict()
|
||||||
|
testcase_summary_json["records"] = testcase_summary_json.pop("step_datas")
|
||||||
|
summary["details"].append(testcase_summary_json)
|
||||||
|
|
||||||
|
summary_path = "/Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/logs/request_methods/hardcode.summary.json"
|
||||||
|
summary_dir = os.path.dirname(summary_path)
|
||||||
|
os.makedirs(summary_dir, exist_ok=True)
|
||||||
|
|
||||||
|
with open(summary_path, "w", encoding="utf-8") as f:
|
||||||
|
json.dump(summary, f, indent=4, ensure_ascii=False, cls=ExtendJSONEncoder)
|
||||||
|
|
||||||
|
logger.info(f"generated task summary: {summary_path}")
|
||||||
|
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.3
|
# NOTE: Generated By HttpRunner v3.1.4
|
||||||
# FROM: request_methods/request_with_functions.yml
|
# FROM: request_methods/request_with_functions.yml
|
||||||
|
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ class TestCaseRequestWithFunctions(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: bar12-$expect_foo2-bar21.",
|
"This is expected to be sent back as part of response body: bar12-$expect_foo2-bar32.",
|
||||||
)
|
)
|
||||||
.assert_type_match("body.json", "None")
|
.assert_type_match("body.json", "None")
|
||||||
.assert_type_match("body.json", "NoneType")
|
.assert_type_match("body.json", "NoneType")
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.3
|
# NOTE: Generated By HttpRunner v3.1.4
|
||||||
# FROM: request_methods/request_with_testcase_reference.yml
|
# FROM: request_methods/request_with_testcase_reference.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.3
|
# NOTE: Generated By HttpRunner v3.1.4
|
||||||
# FROM: request_methods/hardcode.yml
|
# FROM: request_methods/hardcode.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ teststeps:
|
|||||||
data: "This is expected to be sent back as part of response body: $foo1-$foo2-$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: bar12-$expect_foo2-bar21."]
|
- eq: ["body.data", "This is expected to be sent back as part of response body: bar12-$expect_foo2-bar32."]
|
||||||
- type_match: ["body.json", None]
|
- type_match: ["body.json", None]
|
||||||
- type_match: ["body.json", NoneType]
|
- type_match: ["body.json", NoneType]
|
||||||
- type_match: ["body.json", null]
|
- type_match: ["body.json", null]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.3
|
# NOTE: Generated By HttpRunner v3.1.4
|
||||||
# FROM: request_methods/request_with_functions.yml
|
# FROM: request_methods/request_with_functions.yml
|
||||||
|
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ class TestCaseRequestWithFunctions(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: bar12-$expect_foo2-bar21.",
|
"This is expected to be sent back as part of response body: bar12-$expect_foo2-bar32.",
|
||||||
)
|
)
|
||||||
.assert_type_match("body.json", "None")
|
.assert_type_match("body.json", "None")
|
||||||
.assert_type_match("body.json", "NoneType")
|
.assert_type_match("body.json", "NoneType")
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.3
|
# NOTE: Generated By HttpRunner v3.1.4
|
||||||
# FROM: request_methods/request_with_parameters.yml
|
# FROM: request_methods/request_with_parameters.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.3
|
# NOTE: Generated By HttpRunner v3.1.4
|
||||||
# FROM: request_methods/request_with_testcase_reference.yml
|
# FROM: request_methods/request_with_testcase_reference.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ teststeps:
|
|||||||
data: "This is expected to be sent back as part of response body: $foo1-$foo2-$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: bar12-testcase_config_bar2-bar21."]
|
- eq: ["body.data", "This is expected to be sent back as part of response body: bar12-testcase_config_bar2-bar32."]
|
||||||
-
|
-
|
||||||
name: post form data
|
name: post form data
|
||||||
variables:
|
variables:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.3
|
# NOTE: Generated By HttpRunner v3.1.4
|
||||||
# FROM: request_methods\request_with_variables.yml
|
# FROM: request_methods/request_with_variables.yml
|
||||||
|
|
||||||
|
|
||||||
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
|
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
|
||||||
@@ -42,7 +42,7 @@ class TestCaseRequestWithVariables(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: bar12-testcase_config_bar2-bar21.",
|
"This is expected to be sent back as part of response body: bar12-testcase_config_bar2-bar32.",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Step(
|
Step(
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.3
|
# NOTE: Generated By HttpRunner v3.1.4
|
||||||
# FROM: request_methods/validate_with_functions.yml
|
# FROM: request_methods/validate_with_functions.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.3
|
# NOTE: Generated By HttpRunner v3.1.4
|
||||||
# FROM: request_methods/validate_with_variables.yml
|
# FROM: request_methods/validate_with_variables.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
__version__ = "3.1.3"
|
__version__ = "3.1.4"
|
||||||
__description__ = "One-stop solution for HTTP(S) testing."
|
__description__ = "One-stop solution for HTTP(S) testing."
|
||||||
|
|
||||||
# import firstly for monkey patch if needed
|
# import firstly for monkey patch if needed
|
||||||
|
|||||||
+2
-4
@@ -24,7 +24,7 @@ from httprunner.loader import (
|
|||||||
convert_relative_project_root_dir,
|
convert_relative_project_root_dir,
|
||||||
)
|
)
|
||||||
from httprunner.response import uniform_validator
|
from httprunner.response import uniform_validator
|
||||||
from httprunner.utils import override_config_variables, is_support_multiprocessing
|
from httprunner.utils import merge_variables, is_support_multiprocessing
|
||||||
|
|
||||||
""" cache converted pytest files, avoid duplicate making
|
""" cache converted pytest files, avoid duplicate making
|
||||||
"""
|
"""
|
||||||
@@ -485,9 +485,7 @@ def make_testsuite(testsuite: Dict) -> NoReturn:
|
|||||||
testcase_variables = convert_variables(
|
testcase_variables = convert_variables(
|
||||||
testcase.get("variables", {}), testcase_path
|
testcase.get("variables", {}), testcase_path
|
||||||
)
|
)
|
||||||
testcase_variables = override_config_variables(
|
testcase_variables = merge_variables(testcase_variables, testsuite_variables)
|
||||||
testcase_variables, testsuite_variables
|
|
||||||
)
|
|
||||||
# testsuite testcase variables > testcase config variables
|
# testsuite testcase variables > testcase config variables
|
||||||
testcase_dict["config"]["variables"] = convert_variables(
|
testcase_dict["config"]["variables"] = convert_variables(
|
||||||
testcase_dict["config"].get("variables", {}), testcase_path
|
testcase_dict["config"].get("variables", {}), testcase_path
|
||||||
|
|||||||
@@ -21,7 +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.utils import merge_variables
|
||||||
from httprunner.models import (
|
from httprunner.models import (
|
||||||
TConfig,
|
TConfig,
|
||||||
TStep,
|
TStep,
|
||||||
@@ -335,17 +335,16 @@ class HttpRunner(object):
|
|||||||
self.__start_at = time.time()
|
self.__start_at = time.time()
|
||||||
self.__step_datas: List[StepData] = []
|
self.__step_datas: List[StepData] = []
|
||||||
self.__session = self.__session or HttpSession()
|
self.__session = self.__session or HttpSession()
|
||||||
self.__session_variables = {}
|
# save extracted variables of teststeps
|
||||||
|
extracted_variables: VariablesMapping = {}
|
||||||
|
|
||||||
# run teststeps
|
# run teststeps
|
||||||
for step in self.__teststeps:
|
for step in self.__teststeps:
|
||||||
# override variables
|
# override variables
|
||||||
# session variables (extracted from pre step) > step variables
|
# step variables > extracted variables from previous steps
|
||||||
step.variables.update(self.__session_variables)
|
step.variables = merge_variables(step.variables, extracted_variables)
|
||||||
# step variables > testcase config variables
|
# step variables > testcase config variables
|
||||||
step.variables = override_config_variables(
|
step.variables = merge_variables(step.variables, self.__config.variables)
|
||||||
step.variables, self.__config.variables
|
|
||||||
)
|
|
||||||
|
|
||||||
# parse variables
|
# parse variables
|
||||||
step.variables = parse_variables_mapping(
|
step.variables = parse_variables_mapping(
|
||||||
@@ -360,8 +359,9 @@ class HttpRunner(object):
|
|||||||
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)
|
extracted_variables.update(extract_mapping)
|
||||||
|
|
||||||
|
self.__session_variables.update(extracted_variables)
|
||||||
self.__duration = time.time() - self.__start_at
|
self.__duration = time.time() - self.__start_at
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ teststeps:
|
|||||||
data: "This is expected to be sent back as part of response body: $foo1-$foo2-$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: bar12-$expect_foo2-bar21."]
|
- eq: ["body.data", "This is expected to be sent back as part of response body: bar12-$expect_foo2-bar32."]
|
||||||
-
|
-
|
||||||
name: post form data
|
name: post form data
|
||||||
variables:
|
variables:
|
||||||
|
|||||||
+7
-9
@@ -193,15 +193,13 @@ class ExtendJSONEncoder(json.JSONEncoder):
|
|||||||
return repr(obj)
|
return repr(obj)
|
||||||
|
|
||||||
|
|
||||||
def override_config_variables(
|
def merge_variables(
|
||||||
step_variables: VariablesMapping, config_variables: VariablesMapping
|
variables: VariablesMapping, variables_to_be_overridden: VariablesMapping
|
||||||
) -> VariablesMapping:
|
) -> VariablesMapping:
|
||||||
""" override variables:
|
""" merge two variables mapping, the first variables have higher priority
|
||||||
testcase step variables > testcase config variables
|
|
||||||
testsuite testcase variables > testsuite config variables
|
|
||||||
"""
|
"""
|
||||||
step_new_variables = {}
|
step_new_variables = {}
|
||||||
for key, value in step_variables.items():
|
for key, value in variables.items():
|
||||||
if f"${key}" == value or "${" + key + "}" == value:
|
if f"${key}" == value or "${" + key + "}" == value:
|
||||||
# e.g. {"base_url": "$base_url"}
|
# e.g. {"base_url": "$base_url"}
|
||||||
# or {"base_url": "${base_url}"}
|
# or {"base_url": "${base_url}"}
|
||||||
@@ -209,9 +207,9 @@ def override_config_variables(
|
|||||||
|
|
||||||
step_new_variables[key] = value
|
step_new_variables[key] = value
|
||||||
|
|
||||||
variables = copy.deepcopy(config_variables)
|
merged_variables = copy.copy(variables_to_be_overridden)
|
||||||
variables.update(step_new_variables)
|
merged_variables.update(step_new_variables)
|
||||||
return variables
|
return merged_variables
|
||||||
|
|
||||||
|
|
||||||
def is_support_multiprocessing() -> bool:
|
def is_support_multiprocessing() -> bool:
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "httprunner"
|
name = "httprunner"
|
||||||
version = "3.1.3"
|
version = "3.1.4"
|
||||||
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"
|
||||||
|
|||||||
+6
-1
@@ -218,7 +218,12 @@ from request_methods.request_with_functions_test import (
|
|||||||
def test_make_requests_with_json_chain_style(self):
|
def test_make_requests_with_json_chain_style(self):
|
||||||
step = {
|
step = {
|
||||||
"name": "get with params",
|
"name": "get with params",
|
||||||
"variables": {"foo1": "bar1", "foo2": 123, "sum_v": "${sum_two(1, 2)}","myjson":{"name": "user", "password": "123456"}},
|
"variables": {
|
||||||
|
"foo1": "bar1",
|
||||||
|
"foo2": 123,
|
||||||
|
"sum_v": "${sum_two(1, 2)}",
|
||||||
|
"myjson": {"name": "user", "password": "123456"},
|
||||||
|
},
|
||||||
"request": {
|
"request": {
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"url": "/get",
|
"url": "/get",
|
||||||
|
|||||||
+2
-2
@@ -6,7 +6,7 @@ import unittest
|
|||||||
from httprunner import loader, utils
|
from httprunner import loader, utils
|
||||||
from httprunner.utils import (
|
from httprunner.utils import (
|
||||||
ExtendJSONEncoder,
|
ExtendJSONEncoder,
|
||||||
override_config_variables,
|
merge_variables,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ class TestUtils(unittest.TestCase):
|
|||||||
step_variables = {"base_url": "$base_url", "foo1": "bar1"}
|
step_variables = {"base_url": "$base_url", "foo1": "bar1"}
|
||||||
config_variables = {"base_url": "https://httpbin.org", "foo1": "bar111"}
|
config_variables = {"base_url": "https://httpbin.org", "foo1": "bar111"}
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
override_config_variables(step_variables, config_variables),
|
merge_variables(step_variables, config_variables),
|
||||||
{"base_url": "https://httpbin.org", "foo1": "bar1"},
|
{"base_url": "https://httpbin.org", "foo1": "bar1"},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user