Merge branch 'master' into readme

This commit is contained in:
debugtalk
2019-09-19 00:36:51 +08:00
committed by GitHub
12 changed files with 137 additions and 365 deletions
+4 -1
View File
@@ -2,13 +2,16 @@
__pycache__ __pycache__
.DS_Store .DS_Store
.vscode .vscode
.idea
.pypirc .pypirc
*/tmp/* */tmp/*
build/* build/*
dist/* dist/*
*.egg-info *.egg-info
.python-version .python-version
logs/% logs
.coverage .coverage
locustfile.py locustfile.py
site/ site/
poetry.lock
reports
+11
View File
@@ -1,5 +1,16 @@
# Release History # Release History
## 2.2.6 (2019-09-18)
**Added**
- config variables support parsing from function
**Changed**
- remove unused import
- adjust code format
## 2.2.5 (2019-07-28) ## 2.2.5 (2019-07-28)
**Added** **Added**
+1 -1
View File
@@ -1,4 +1,4 @@
__version__ = "2.2.5" __version__ = "2.2.6"
__description__ = "One-stop solution for HTTP(S) testing." __description__ = "One-stop solution for HTTP(S) testing."
__all__ = ["__version__", "__description__"] __all__ = ["__version__", "__description__"]
+2 -1
View File
@@ -1,5 +1,6 @@
# encoding: utf-8 # encoding: utf-8
def main_hrun(): def main_hrun():
""" API test: parse command line options and run commands. """ API test: parse command line options and run commands.
""" """
@@ -11,7 +12,7 @@ def main_hrun():
from httprunner.compat import is_py2 from httprunner.compat import is_py2
from httprunner.validator import validate_json_file from httprunner.validator import validate_json_file
from httprunner.utils import (create_scaffold, get_python2_retire_msg, from httprunner.utils import (create_scaffold, get_python2_retire_msg,
prettify_json_file) prettify_json_file)
parser = argparse.ArgumentParser(description=__description__) parser = argparse.ArgumentParser(description=__description__)
parser.add_argument( parser.add_argument(
+16 -7
View File
@@ -17,10 +17,12 @@ try:
except AttributeError: except AttributeError:
pass pass
############################################################################### ###############################################################################
## file loader # file loader
############################################################################### ###############################################################################
def _check_format(file_path, content): def _check_format(file_path, content):
""" check testcase format if valid """ check testcase format if valid
""" """
@@ -239,9 +241,10 @@ def locate_file(start_path, file_name):
############################################################################### ###############################################################################
## debugtalk.py module loader # debugtalk.py module loader
############################################################################### ###############################################################################
def load_module_functions(module): def load_module_functions(module):
""" load python module functions. """ load python module functions.
@@ -290,9 +293,10 @@ def load_debugtalk_functions():
############################################################################### ###############################################################################
## testcase loader # testcase loader
############################################################################### ###############################################################################
project_mapping = {} project_mapping = {}
tests_def_mapping = { tests_def_mapping = {
"PWD": None, "PWD": None,
@@ -720,14 +724,16 @@ def load_api_folder(api_folder_path):
if isinstance(api_items, list): if isinstance(api_items, list):
for api_item in api_items: for api_item in api_items:
key, api_dict = api_item.popitem() key, api_dict = api_item.popitem()
api_id = api_dict.get("id") or api_dict.get("def") or api_dict.get("name") api_id = api_dict.get("id") or api_dict.get("def") \
or api_dict.get("name")
if key != "api" or not api_id: if key != "api" or not api_id:
raise exceptions.ParamsError( raise exceptions.ParamsError(
"Invalid API defined in {}".format(api_file_path)) "Invalid API defined in {}".format(api_file_path))
if api_id in api_definition_mapping: if api_id in api_definition_mapping:
raise exceptions.ParamsError( raise exceptions.ParamsError(
"Duplicated API ({}) defined in {}".format(api_id, api_file_path)) "Duplicated API ({}) defined in {}".format(
api_id, api_file_path))
else: else:
api_definition_mapping[api_id] = api_dict api_definition_mapping[api_id] = api_dict
@@ -745,7 +751,8 @@ def locate_debugtalk_py(start_path):
""" locate debugtalk.py file """ locate debugtalk.py file
Args: Args:
start_path (str): start locating path, maybe testcase file path or directory path start_path (str): start locating path,
maybe testcase file path or directory path
Returns: Returns:
str: debugtalk.py file path, None if not found str: debugtalk.py file path, None if not found
@@ -769,7 +776,8 @@ def load_project_tests(test_path, dot_env_path=None):
dot_env_path (str): specified .env file path dot_env_path (str): specified .env file path
Returns: Returns:
dict: project loaded api/testcases definitions, environments and debugtalk.py functions. dict: project loaded api/testcases definitions,
environments and debugtalk.py functions.
""" """
# locate debugtalk.py file # locate debugtalk.py file
@@ -876,6 +884,7 @@ def load_tests(path, dot_env_path=None):
} }
def __load_file_content(path): def __load_file_content(path):
loaded_content = None
try: try:
loaded_content = load_test_file(path) loaded_content = load_test_file(path)
except exceptions.FileFormatError: except exceptions.FileFormatError:
+15 -3
View File
@@ -2,11 +2,10 @@
import ast import ast
import builtins import builtins
import os
import re import re
from httprunner import exceptions, utils, validator from httprunner import exceptions, utils, validator
from httprunner.compat import basestring, builtin_str, numeric_types, str from httprunner.compat import basestring, numeric_types, str
# use $$ to escape $ notation # use $$ to escape $ notation
dolloar_regex_compile = re.compile(r"\$\$") dolloar_regex_compile = re.compile(r"\$\$")
@@ -872,10 +871,23 @@ def __prepare_config(config, project_mapping, session_variables_set=None):
""" """
# get config variables # get config variables
raw_config_variables = config.pop("variables", {}) raw_config_variables = config.pop("variables", {})
raw_config_variables_mapping = utils.ensure_mapping_format(raw_config_variables)
override_variables = utils.deepcopy_dict(project_mapping.get("variables", {})) override_variables = utils.deepcopy_dict(project_mapping.get("variables", {}))
functions = project_mapping.get("functions", {}) functions = project_mapping.get("functions", {})
if isinstance(raw_config_variables, basestring) and function_regex_compile.match(raw_config_variables):
# config variables are generated by calling function
# e.g.
# "config": {
# "name": "basic test with httpbin",
# "variables": "${gen_variables()}"
# }
raw_config_variables_mapping = parse_lazy_data(
prepare_lazy_data(raw_config_variables, functions_mapping=functions)
)
else:
raw_config_variables_mapping = utils.ensure_mapping_format(raw_config_variables)
# override config variables with passed in variables # override config variables with passed in variables
raw_config_variables_mapping.update(override_variables) raw_config_variables_mapping.update(override_variables)
+35 -4
View File
@@ -2,11 +2,11 @@
import json import json
import re import re
import jsonpath
from httprunner import exceptions, logger, utils from httprunner import exceptions, logger, utils
from httprunner.compat import OrderedDict, basestring, is_py2 from httprunner.compat import OrderedDict, basestring, is_py2
from requests.models import PreparedRequest
from requests.structures import CaseInsensitiveDict
text_extractor_regexp_compile = re.compile(r".*\(.*\).*") text_extractor_regexp_compile = re.compile(r".*\(.*\).*")
@@ -38,6 +38,35 @@ class ResponseObject(object):
logger.log_error(err_msg) logger.log_error(err_msg)
raise exceptions.ParamsError(err_msg) raise exceptions.ParamsError(err_msg)
def _extract_field_with_jsonpath(self, field):
"""
JSONPath Docs: https://goessner.net/articles/JsonPath/
For example, response body like below:
{
"code": 200,
"data": {
"items": [{
"id": 1,
"name": "Bob"
},
{
"id": 2,
"name": "James"
}
]
},
"message": "操作成功"
}
:param field: Jsonpath expression, e.g. 1)$.code 2) $..items.*.id
:return: A list that extracted from json repsonse example. 1) [200] 2) [1, 2]
"""
result = jsonpath.jsonpath(self.parsed_body(), field)
if result:
return result
else:
raise exceptions.ExtractFailure("\tjsonpath {} get nothing\n".format(field))
def _extract_field_with_regex(self, field): def _extract_field_with_regex(self, field):
""" extract field from response content with regex. """ extract field from response content with regex.
requests.Response body could be json or html text. requests.Response body could be json or html text.
@@ -81,7 +110,7 @@ class ResponseObject(object):
"content.person.name.first_name" "content.person.name.first_name"
""" """
# string.split(sep=None, maxsplit=-1) -> list of strings # string.split(sep=None, maxsplit=1) -> list of strings
# e.g. "content.person.name" => ["content", "person.name"] # e.g. "content.person.name" => ["content", "person.name"]
try: try:
top_query, sub_query = field.split('.', 1) top_query, sub_query = field.split('.', 1)
@@ -211,7 +240,9 @@ class ResponseObject(object):
msg = "extract: {}".format(field) msg = "extract: {}".format(field)
if text_extractor_regexp_compile.match(field): if field.startswith("$"):
value = self._extract_field_with_jsonpath(field)
elif text_extractor_regexp_compile.match(field):
value = self._extract_field_with_regex(field) value = self._extract_field_with_regex(field)
else: else:
value = self._extract_field_with_delimiter(field) value = self._extract_field_with_delimiter(field)
Generated
-344
View File
@@ -1,344 +0,0 @@
[[package]]
category = "dev"
description = "Fast ASN.1 parser and serializer with definitions for private keys, public keys, certificates, CRL, OCSP, CMS, PKCS#3, PKCS#7, PKCS#8, PKCS#12, PKCS#5, X.509 and TSP"
marker = "python_version < \"3\" and extra == \"secure\""
name = "asn1crypto"
optional = false
python-versions = "*"
version = "0.24.0"
[[package]]
category = "main"
description = "Python package for providing Mozilla's CA Bundle."
name = "certifi"
optional = false
python-versions = "*"
version = "2019.6.16"
[[package]]
category = "dev"
description = "Foreign Function Interface for Python calling C code."
marker = "python_version < \"3\" and extra == \"secure\""
name = "cffi"
optional = false
python-versions = "*"
version = "1.12.3"
[package.dependencies]
pycparser = "*"
[[package]]
category = "main"
description = "Universal encoding detector for Python 2 and 3"
name = "chardet"
optional = false
python-versions = "*"
version = "3.0.4"
[[package]]
category = "dev"
description = "Composable command line interface toolkit"
name = "click"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "7.0"
[[package]]
category = "main"
description = "Cross-platform colored terminal text."
name = "colorama"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.4.1"
[[package]]
category = "main"
description = "Log formatting with colors!"
name = "colorlog"
optional = false
python-versions = "*"
version = "4.0.2"
[package.dependencies]
colorama = "*"
[[package]]
category = "dev"
description = "Backports and enhancements for the contextlib module"
name = "contextlib2"
optional = false
python-versions = "*"
version = "0.5.5"
[[package]]
category = "dev"
description = "Code coverage measurement for Python"
name = "coverage"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, <4"
version = "4.5.3"
[[package]]
category = "dev"
description = "Show coverage stats online via coveralls.io"
name = "coveralls"
optional = false
python-versions = "*"
version = "1.8.1"
[package.dependencies]
coverage = ">=3.6,<5.0"
docopt = ">=0.6.1"
requests = ">=1.0.0"
[package.dependencies.urllib3]
python = "<3"
version = ">=1.21.1,<1.25"
[[package]]
category = "dev"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
marker = "python_version < \"3\" and extra == \"secure\""
name = "cryptography"
optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
version = "2.7"
[package.dependencies]
asn1crypto = ">=0.21.0"
cffi = ">=1.8,<1.11.3 || >1.11.3"
six = ">=1.4.1"
[package.dependencies.enum34]
python = "<3"
version = "*"
[package.dependencies.ipaddress]
python = "<3"
version = "*"
[[package]]
category = "dev"
description = "Pythonic argument parser, that will make you smile"
name = "docopt"
optional = false
python-versions = "*"
version = "0.6.2"
[[package]]
category = "dev"
description = "Python 3.4 Enum backported to 3.3, 3.2, 3.1, 2.7, 2.6, 2.5, and 2.4"
marker = "python_version < \"3\" and extra == \"secure\""
name = "enum34"
optional = false
python-versions = "*"
version = "1.1.6"
[[package]]
category = "main"
description = "Infer file type and MIME type of any file/buffer. No external dependencies."
name = "filetype"
optional = false
python-versions = "*"
version = "1.0.5"
[[package]]
category = "dev"
description = "A microframework based on Werkzeug, Jinja2 and good intentions"
name = "flask"
optional = false
python-versions = "*"
version = "0.12.4"
[package.dependencies]
Jinja2 = ">=2.4"
Werkzeug = ">=0.7"
click = ">=2.0"
itsdangerous = ">=0.21"
[[package]]
category = "main"
description = "Clean single-source support for Python 3 and 2"
marker = "python_version >= \"2.7\" and python_version < \"2.8\""
name = "future"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
version = "0.17.1"
[[package]]
category = "main"
description = "Convert HAR(HTTP Archive) to YAML/JSON testcases for HttpRunner."
name = "har2case"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4"
version = "0.3.1"
[package.dependencies]
PyYAML = "*"
[[package]]
category = "main"
description = "Internationalized Domain Names in Applications (IDNA)"
name = "idna"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "2.8"
[[package]]
category = "dev"
description = "IPv4/IPv6 manipulation library"
marker = "python_version < \"3\" and extra == \"secure\""
name = "ipaddress"
optional = false
python-versions = "*"
version = "1.0.22"
[[package]]
category = "dev"
description = "Various helpers to pass data to untrusted environments and back."
name = "itsdangerous"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "1.1.0"
[[package]]
category = "main"
description = "A small but fast and easy to use stand-alone template engine written in pure python."
name = "jinja2"
optional = false
python-versions = "*"
version = "2.10.1"
[package.dependencies]
MarkupSafe = ">=0.23"
[[package]]
category = "main"
description = "Safely add untrusted strings to HTML/XML markup."
name = "markupsafe"
optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
version = "1.1.1"
[[package]]
category = "dev"
description = "C parser in Python"
marker = "python_version < \"3\" and extra == \"secure\""
name = "pycparser"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "2.19"
[[package]]
category = "dev"
description = "Python wrapper module around the OpenSSL library"
marker = "python_version < \"3\" and extra == \"secure\""
name = "pyopenssl"
optional = false
python-versions = "*"
version = "19.0.0"
[package.dependencies]
cryptography = ">=2.3"
six = ">=1.5.2"
[[package]]
category = "main"
description = "YAML parser and emitter for Python"
name = "pyyaml"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "5.1.1"
[[package]]
category = "main"
description = "Python HTTP for Humans."
name = "requests"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
version = "2.22.0"
[package.dependencies]
certifi = ">=2017.4.17"
chardet = ">=3.0.2,<3.1.0"
idna = ">=2.5,<2.9"
urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26"
[[package]]
category = "main"
description = "A utility belt for advanced users of python-requests"
name = "requests-toolbelt"
optional = false
python-versions = "*"
version = "0.8.0"
[package.dependencies]
requests = ">=2.0.1,<3.0.0"
[[package]]
category = "dev"
description = "Python 2 and 3 compatibility utilities"
marker = "python_version < \"3\" and extra == \"secure\""
name = "six"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*"
version = "1.12.0"
[[package]]
category = "main"
description = "HTTP library with thread-safe connection pooling, file post, and more."
name = "urllib3"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4"
version = "1.24.3"
[package.dependencies]
certifi = "*"
cryptography = ">=1.3.4"
idna = ">=2.0.0"
ipaddress = "*"
pyOpenSSL = ">=0.14"
[[package]]
category = "dev"
description = "The comprehensive WSGI web application library."
name = "werkzeug"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.15.5"
[metadata]
content-hash = "f65a674bd12f46ac9b4a8375fb8ee051bcaaf88dd6b8d793d7cd6aae54e81186"
python-versions = "~2.7 || ^3.5"
[metadata.hashes]
asn1crypto = ["2f1adbb7546ed199e3c90ef23ec95c5cf3585bac7d11fb7eb562a3fe89c64e87", "9d5c20441baf0cb60a4ac34cc447c6c189024b6b4c6cd7877034f4965c464e49"]
certifi = ["046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939", "945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695"]
cffi = ["041c81822e9f84b1d9c401182e174996f0bae9991f33725d059b771744290774", "046ef9a22f5d3eed06334d01b1e836977eeef500d9b78e9ef693f9380ad0b83d", "066bc4c7895c91812eff46f4b1c285220947d4aa46fa0a2651ff85f2afae9c90", "066c7ff148ae33040c01058662d6752fd73fbc8e64787229ea8498c7d7f4041b", "2444d0c61f03dcd26dbf7600cf64354376ee579acad77aef459e34efcb438c63", "300832850b8f7967e278870c5d51e3819b9aad8f0a2c8dbe39ab11f119237f45", "34c77afe85b6b9e967bd8154e3855e847b70ca42043db6ad17f26899a3df1b25", "46de5fa00f7ac09f020729148ff632819649b3e05a007d286242c4882f7b1dc3", "4aa8ee7ba27c472d429b980c51e714a24f47ca296d53f4d7868075b175866f4b", "4d0004eb4351e35ed950c14c11e734182591465a33e960a4ab5e8d4f04d72647", "4e3d3f31a1e202b0f5a35ba3bc4eb41e2fc2b11c1eff38b362de710bcffb5016", "50bec6d35e6b1aaeb17f7c4e2b9374ebf95a8975d57863546fa83e8d31bdb8c4", "55cad9a6df1e2a1d62063f79d0881a414a906a6962bc160ac968cc03ed3efcfb", "5662ad4e4e84f1eaa8efce5da695c5d2e229c563f9d5ce5b0113f71321bcf753", "59b4dc008f98fc6ee2bb4fd7fc786a8d70000d058c2bbe2698275bc53a8d3fa7", "73e1ffefe05e4ccd7bcea61af76f36077b914f92b76f95ccf00b0c1b9186f3f9", "a1f0fd46eba2d71ce1589f7e50a9e2ffaeb739fb2c11e8192aa2b45d5f6cc41f", "a2e85dc204556657661051ff4bab75a84e968669765c8a2cd425918699c3d0e8", "a5457d47dfff24882a21492e5815f891c0ca35fefae8aa742c6c263dac16ef1f", "a8dccd61d52a8dae4a825cdbb7735da530179fea472903eb871a5513b5abbfdc", "ae61af521ed676cf16ae94f30fe202781a38d7178b6b4ab622e4eec8cefaff42", "b012a5edb48288f77a63dba0840c92d0504aa215612da4541b7b42d849bc83a3", "d2c5cfa536227f57f97c92ac30c8109688ace8fa4ac086d19d0af47d134e2909", "d42b5796e20aacc9d15e66befb7a345454eef794fdb0737d1af593447c6c8f45", "dee54f5d30d775f525894d67b1495625dd9322945e7fee00731952e0368ff42d", "e070535507bd6aa07124258171be2ee8dfc19119c28ca94c9dfb7efd23564512", "e1ff2748c84d97b065cc95429814cdba39bcbd77c9c85c89344b317dc0d9cbff", "ed851c75d1e0e043cbf5ca9a8e1b13c4c90f3fbd863dacb01c0808e2b5204201"]
chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"]
click = ["2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", "5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"]
colorama = ["05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", "f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"]
colorlog = ["3cf31b25cbc8f86ec01fef582ef3b840950dea414084ed19ab922c8b493f9b42", "450f52ea2a2b6ebb308f034ea9a9b15cea51e65650593dca1da3eb792e4e4981"]
contextlib2 = ["509f9419ee91cdd00ba34443217d5ca51f5a364a404e1dce9e8979cea969ca48", "f5260a6e679d2ff42ec91ec5252f4eeffdcf21053db9113bd0a8e4d953769c00"]
coverage = ["0c5fe441b9cfdab64719f24e9684502a59432df7570521563d7b1aff27ac755f", "2b412abc4c7d6e019ce7c27cbc229783035eef6d5401695dccba80f481be4eb3", "3684fabf6b87a369017756b551cef29e505cb155ddb892a7a29277b978da88b9", "39e088da9b284f1bd17c750ac672103779f7954ce6125fd4382134ac8d152d74", "3c205bc11cc4fcc57b761c2da73b9b72a59f8d5ca89979afb0c1c6f9e53c7390", "42692db854d13c6c5e9541b6ffe0fe921fe16c9c446358d642ccae1462582d3b", "465ce53a8c0f3a7950dfb836438442f833cf6663d407f37d8c52fe7b6e56d7e8", "48020e343fc40f72a442c8a1334284620f81295256a6b6ca6d8aa1350c763bbe", "4ec30ade438d1711562f3786bea33a9da6107414aed60a5daa974d50a8c2c351", "5296fc86ab612ec12394565c500b412a43b328b3907c0d14358950d06fd83baf", "5f61bed2f7d9b6a9ab935150a6b23d7f84b8055524e7be7715b6513f3328138e", "6899797ac384b239ce1926f3cb86ffc19996f6fa3a1efbb23cb49e0c12d8c18c", "68a43a9f9f83693ce0414d17e019daee7ab3f7113a70c79a3dd4c2f704e4d741", "6b8033d47fe22506856fe450470ccb1d8ba1ffb8463494a15cfc96392a288c09", "7ad7536066b28863e5835e8cfeaa794b7fe352d99a8cded9f43d1161be8e9fbd", "7bacb89ccf4bedb30b277e96e4cc68cd1369ca6841bde7b005191b54d3dd1034", "839dc7c36501254e14331bcb98b27002aa415e4af7ea039d9009409b9d2d5420", "8e679d1bde5e2de4a909efb071f14b472a678b788904440779d2c449c0355b27", "8f9a95b66969cdea53ec992ecea5406c5bd99c9221f539bca1e8406b200ae98c", "932c03d2d565f75961ba1d3cec41ddde00e162c5b46d03f7423edcb807734eab", "93f965415cc51604f571e491f280cff0f5be35895b4eb5e55b47ae90c02a497b", "988529edadc49039d205e0aa6ce049c5ccda4acb2d6c3c5c550c17e8c02c05ba", "998d7e73548fe395eeb294495a04d38942edb66d1fa61eb70418871bc621227e", "9de60893fb447d1e797f6bf08fdf0dbcda0c1e34c1b06c92bd3a363c0ea8c609", "9e80d45d0c7fcee54e22771db7f1b0b126fb4a6c0a2e5afa72f66827207ff2f2", "a545a3dfe5082dc8e8c3eb7f8a2cf4f2870902ff1860bd99b6198cfd1f9d1f49", "a5d8f29e5ec661143621a8f4de51adfb300d7a476224156a39a392254f70687b", "a9abc8c480e103dc05d9b332c6cc9fb1586330356fc14f1aa9c0ca5745097d19", "aca06bfba4759bbdb09bf52ebb15ae20268ee1f6747417837926fae990ebc41d", "bb23b7a6fd666e551a3094ab896a57809e010059540ad20acbeec03a154224ce", "bfd1d0ae7e292105f29d7deaa9d8f2916ed8553ab9d5f39ec65bcf5deadff3f9", "c22ab9f96cbaff05c6a84e20ec856383d27eae09e511d3e6ac4479489195861d", "c62ca0a38958f541a73cf86acdab020c2091631c137bd359c4f5bddde7b75fd4", "c709d8bda72cf4cd348ccec2a4881f2c5848fd72903c185f363d361b2737f773", "c968a6aa7e0b56ecbd28531ddf439c2ec103610d3e2bf3b75b813304f8cb7723", "ca58eba39c68010d7e87a823f22a081b5290e3e3c64714aac3c91481d8b34d22", "df785d8cb80539d0b55fd47183264b7002077859028dfe3070cf6359bf8b2d9c", "f406628ca51e0ae90ae76ea8398677a921b36f0bd71aab2099dfed08abd0322f", "f46087bbd95ebae244a0eda01a618aff11ec7a069b15a3ef8f6b520db523dcf1", "f8019c5279eb32360ca03e9fac40a12667715546eed5c5eb59eb381f2f501260", "fc5f4d209733750afd2714e9109816a29500718b32dd9a5db01c0cb3a019b96a"]
coveralls = ["d3d49234bffd41e91b241a69f0ebb9f64d7f0515711a76134d53d4647e7eb509", "dafabcff87425fa2ab3122dee21229afbb4d6692cfdacc6bb895f7dfa8b2c849"]
cryptography = ["24b61e5fcb506424d3ec4e18bca995833839bf13c59fc43e530e488f28d46b8c", "25dd1581a183e9e7a806fe0543f485103232f940fcfc301db65e630512cce643", "3452bba7c21c69f2df772762be0066c7ed5dc65df494a1d53a58b683a83e1216", "41a0be220dd1ed9e998f5891948306eb8c812b512dc398e5a01846d855050799", "5751d8a11b956fbfa314f6553d186b94aa70fdb03d8a4d4f1c82dcacf0cbe28a", "5f61c7d749048fa6e3322258b4263463bfccefecb0dd731b6561cb617a1d9bb9", "72e24c521fa2106f19623a3851e9f89ddfdeb9ac63871c7643790f872a305dfc", "7b97ae6ef5cba2e3bb14256625423413d5ce8d1abb91d4f29b6d1a081da765f8", "961e886d8a3590fd2c723cf07be14e2a91cf53c25f02435c04d39e90780e3b53", "96d8473848e984184b6728e2c9d391482008646276c3ff084a1bd89e15ff53a1", "ae536da50c7ad1e002c3eee101871d93abdc90d9c5f651818450a0d3af718609", "b0db0cecf396033abb4a93c95d1602f268b3a68bb0a9cc06a7cff587bb9a7292", "cfee9164954c186b191b91d4193989ca994703b2fff406f71cf454a2d3c7327e", "e6347742ac8f35ded4a46ff835c60e68c22a536a8ae5c4422966d06946b6d4c6", "f27d93f0139a3c056172ebb5d4f9056e770fdf0206c2f422ff2ebbad142e09ed", "f57b76e46a58b63d1c6375017f4564a28f19a5ca912691fd2e4261b3414b618d"]
docopt = ["49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"]
enum34 = ["2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850", "644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a", "6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79", "8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1"]
filetype = ["17a3b885f19034da29640b083d767e0f13c2dcb5dcc267945c8b6e5a5a9013c7", "4967124d982a71700d94a08c49c4926423500e79382a92070f5ab248d44fe461"]
flask = ["2ea22336f6d388b4b242bc3abf8a01244a8aa3e236e7407469ef78c16ba355dd", "6c02dbaa5a9ef790d8219bdced392e2d549c10cd5a5ba4b6aa65126b2271af29"]
future = ["67045236dcfd6816dc439556d009594abf643e5eb48992e36beac09c2ca659b8"]
har2case = ["84d3a5cc9fbb16e45372e7e880a936c59bbe8e9b66bad81927769e64f608e2af", "8f159ec7cba82ec4282f46af4a9dac89f65e62796521b2426d3c89c3c9fd8579"]
idna = ["c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", "ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"]
ipaddress = ["64b28eec5e78e7510698f6d4da08800a5c575caa4a286c93d651c5d3ff7b6794", "b146c751ea45cad6188dd6cf2d9b757f6f4f8d6ffb96a023e6f2e26eea02a72c"]
itsdangerous = ["321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19", "b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"]
jinja2 = ["065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", "14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"]
markupsafe = ["00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", "09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", "09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", "24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", "43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", "535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", "62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", "6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", "717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", "7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", "88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", "8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", "98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", "9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", "9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", "ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", "b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", "b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", "b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", "ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", "c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", "cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", "e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"]
pycparser = ["a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3"]
pyopenssl = ["aeca66338f6de19d1aa46ed634c3b9ae519a64b458f8468aec688e7e3c20f200", "c727930ad54b10fc157015014b666f2d8b41f70c0d03e83ab67624fd3dd5d1e6"]
pyyaml = ["57acc1d8533cbe51f6662a55434f0dbecfa2b9eaf115bede8f6fd00115a0c0d3", "588c94b3d16b76cfed8e0be54932e5729cc185caffaa5a451e7ad2f7ed8b4043", "68c8dd247f29f9a0d09375c9c6b8fdc64b60810ebf07ba4cdd64ceee3a58c7b7", "70d9818f1c9cd5c48bb87804f2efc8692f1023dac7f1a1a5c61d454043c1d265", "86a93cccd50f8c125286e637328ff4eef108400dd7089b46a7be3445eecfa391", "a0f329125a926876f647c9fa0ef32801587a12328b4a3c741270464e3e4fa778", "a3c252ab0fa1bb0d5a3f6449a4826732f3eb6c0270925548cac342bc9b22c225", "b4bb4d3f5e232425e25dda21c070ce05168a786ac9eda43768ab7f3ac2770955", "cd0618c5ba5bda5f4039b9398bb7fb6a317bb8298218c3de25c47c4740e4b95e", "ceacb9e5f8474dcf45b940578591c7f3d960e82f926c707788a570b51ba59190", "fe6a88094b64132c4bb3b631412e90032e8cfe9745a58370462240b8cb7553cd"]
requests = ["11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", "9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"]
requests-toolbelt = ["42c9c170abc2cacb78b8ab23ac957945c7716249206f90874651971a4acff237", "f6a531936c6fa4c6cfce1b9c10d5c4f498d16528d2a54a22ca00011205a187b5"]
six = ["3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", "d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"]
urllib3 = ["2393a695cd12afedd0dcb26fe5d50d0cf248e5a66f75dbd89a3d4eb333a61af4", "a637e5fae88995b256e3409dc4d52c2e2e0ba32c42a6365fee8bbd2238de3cfb"]
werkzeug = ["87ae4e5b5366da2347eb3116c0e6c681a0e939a33b2805e2c0cbd282664932c4", "a13b74dd3c45f758d4ebdb224be8f1ab8ef58b3c0ffc1783a8c7d9f4f50227e6"]
+2 -1
View File
@@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "httprunner" name = "httprunner"
version = "2.2.5" version = "2.2.6"
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"
@@ -30,6 +30,7 @@ colorama = "^0.4.1"
colorlog = "^4.0" colorlog = "^4.0"
filetype = "^1.0" filetype = "^1.0"
future = { version = "^0.17.1", python = "~2.7" } future = { version = "^0.17.1", python = "~2.7" }
jsonpath = "^0.82"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
flask = "<1.0.0" flask = "<1.0.0"
+7
View File
@@ -111,3 +111,10 @@ def alter_response(response):
def alter_response_error(response): def alter_response_error(response):
# NameError # NameError
not_defined_variable not_defined_variable
def gen_variables():
return {
"var_a": 1,
"var_b": 2
}
-2
View File
@@ -1,5 +1,4 @@
import os import os
import re
import time import time
import unittest import unittest
@@ -561,7 +560,6 @@ class TestParserBasic(unittest.TestCase):
) )
def test_parse_data_functions(self): def test_parse_data_functions(self):
import random, string
functions_mapping = { functions_mapping = {
"gen_random_string": gen_random_string "gen_random_string": gen_random_string
} }
+44 -1
View File
@@ -336,4 +336,47 @@ class TestRunner(ApiServerUnittest):
parsed_testcases = parser.parse_tests(tests_mapping) parsed_testcases = parser.parse_tests(tests_mapping)
parsed_testcase = parsed_testcases[0] parsed_testcase = parsed_testcases[0]
test_runner = runner.Runner(parsed_testcase["config"]) test_runner = runner.Runner(parsed_testcase["config"])
test_runner.run_test(parsed_testcase["teststeps"][0]) test_runner.run_test(parsed_testcase["teststeps"][0])
def test_run_testcase_config_variables_parsed_from_function(self):
testcases = [
{
"config": {
"name": "basic test with httpbin",
"base_url": HTTPBIN_SERVER,
"variables": "${gen_variables()}"
},
"teststeps": [
{
"name": "modify request headers",
"base_url": HTTPBIN_SERVER,
"request": {
"url": "/anything",
"method": "POST",
"headers": {
"user_agent": "iOS/10.3",
"os_platform": "ios"
},
"data": "a=1&b=2"
},
"validate": [
{"check": "status_code", "expect": 200}
]
}
]
}
]
tests_mapping = {
"project_mapping": {
"functions": self.debugtalk_functions
},
"testcases": testcases
}
parsed_testcases = parser.parse_tests(tests_mapping)
parsed_testcase = parsed_testcases[0]
test_runner = runner.Runner(parsed_testcase["config"])
test_runner.run_test(parsed_testcase["teststeps"][0])
test_variables_mapping = test_runner.session_context.test_variables_mapping
self.assertEqual(test_variables_mapping["var_a"], 1)
self.assertEqual(test_variables_mapping["var_b"], 2)
self.assertEqual(test_variables_mapping["request"]["data"], "a=1&b=2")