diff --git a/examples/postman_echo/request_methods/with_variables.yml b/examples/postman_echo/request_methods/with_variables.yml index 008dd007..625e240f 100644 --- a/examples/postman_echo/request_methods/with_variables.yml +++ b/examples/postman_echo/request_methods/with_variables.yml @@ -10,7 +10,7 @@ teststeps: name: get with params variables: foo1: bar1 - foo2: bar2 + foo2: session_bar2 request: method: GET url: /get @@ -19,24 +19,27 @@ teststeps: foo2: $foo2 headers: User-Agent: HttpRunner/3.0 + extract: + session_foo2: "body.args.foo2" validate: - eq: ["status_code", 200] - eq: ["body.args.foo1", "session_bar1"] - - eq: ["body.args.foo2", "bar2"] + - eq: ["body.args.foo2", "session_bar2"] - name: post raw text variables: foo1: "hello world" + foo3: "$session_foo2" request: method: POST url: /post headers: User-Agent: HttpRunner/3.0 Content-Type: "text/plain" - data: "This is expected to be sent back as part of response body: $foo1." + data: "This is expected to be sent back as part of response body: $foo1-$foo3." validate: - eq: ["status_code", 200] - - eq: ["body.data", "This is expected to be sent back as part of response body: session_bar1."] + - eq: ["body.data", "This is expected to be sent back as part of response body: session_bar1-session_bar2."] - name: post form data variables: diff --git a/examples/postman_echo/request_methods/with_variables_test.py b/examples/postman_echo/request_methods/with_variables_test.py index c68c99fa..df29953f 100644 --- a/examples/postman_echo/request_methods/with_variables_test.py +++ b/examples/postman_echo/request_methods/with_variables_test.py @@ -17,7 +17,7 @@ class TestCaseRequestMethodsWithVariables(TestCaseRunner): "name": "get with params", "variables": { "foo1": "bar1", - "foo2": "bar2" + "foo2": "session_bar2" }, "request": { "method": "GET", @@ -30,21 +30,25 @@ class TestCaseRequestMethodsWithVariables(TestCaseRunner): "User-Agent": "HttpRunner/3.0" } }, + "extract": { + "session_foo2": "body.args.foo2" + }, "validate": [ {"eq": ["status_code", 200]}, {"eq": ["body.args.foo1", "session_bar1"]}, - {"eq": ["body.args.foo2", "bar2"]} + {"eq": ["body.args.foo2", "session_bar2"]} ] }), TestStep(**{ "name": "post raw text", "variables": { - "foo1": "hello world" + "foo1": "hello world", + "foo3": "$session_foo2" }, "request": { "method": "POST", "url": "/post", - "data": "This is expected to be sent back as part of response body: $foo1.", + "data": "This is expected to be sent back as part of response body: $foo1-$foo3.", "headers": { "User-Agent": "HttpRunner/3.0", "Content-Type": "text/plain" @@ -52,7 +56,10 @@ class TestCaseRequestMethodsWithVariables(TestCaseRunner): }, "validate": [ {"eq": ["status_code", 200]}, - {"eq": ["body.data", "This is expected to be sent back as part of response body: session_bar1."]}, + {"eq": [ + "body.data", + "This is expected to be sent back as part of response body: session_bar1-session_bar2." + ]}, ] }), TestStep(**{ diff --git a/httprunner/v3/parser.py b/httprunner/v3/parser.py index c3365490..9e1b2ad3 100644 --- a/httprunner/v3/parser.py +++ b/httprunner/v3/parser.py @@ -3,6 +3,7 @@ from typing import Any, Set, Text from typing import Dict from httprunner.v3 import exceptions +from httprunner.v3.exceptions import VariableNotFound absolute_http_url_regexp = re.compile(r"^https?://", re.I) @@ -98,7 +99,10 @@ def parse_string_variables(content, variables_mapping): """ variables_list = extract_variables(content) for variable_name in variables_list: - variable_value = variables_mapping[variable_name] + try: + variable_value = variables_mapping[variable_name] + except KeyError: + raise VariableNotFound(f"{variable_name} not in {variables_mapping}") # TODO: replace variable label from $var to {{var}} if f"${variable_name}" == content: @@ -158,20 +162,24 @@ def parse_content(content: Any, variables_mapping: Dict[str, Any] = None, functi return content -def parse_variables_mapping(variables_mapping: Dict[str, Any]): +def parse_variables_mapping(variables_mapping: Dict[Text, Any]) -> Dict[Text, Any]: - parsed_variables: Dict[str, Any] = {} + parsed_variables: Dict[Text, Any] = {} while len(parsed_variables) != len(variables_mapping): for var_name in variables_mapping: - var_value = variables_mapping[var_name] - # variables = extract_variables(var_value) - if var_name in parsed_variables: continue - parsed_value = parse_content(var_value, parsed_variables) + var_value = variables_mapping[var_name] + # variables = extract_variables(var_value) + + try: + parsed_value = parse_content(var_value, parsed_variables) + except VariableNotFound: + continue + parsed_variables[var_name] = parsed_value return parsed_variables diff --git a/httprunner/v3/runner.py b/httprunner/v3/runner.py index fc237f71..12d28059 100644 --- a/httprunner/v3/runner.py +++ b/httprunner/v3/runner.py @@ -3,7 +3,7 @@ from typing import List import requests from loguru import logger -from httprunner.v3.parser import build_url, parse_content +from httprunner.v3.parser import build_url, parse_content, parse_variables_mapping from httprunner.v3.response import ResponseObject from httprunner.v3.schema import TestsConfig, TestStep @@ -57,9 +57,15 @@ class TestCaseRunner(object): """main entrance""" session_variables = {} for step in self.teststeps: + # update with config variables step.variables.update(self.config.variables) + # update with session variables extracted from former step step.variables.update(session_variables) + # parse variables + step.variables = parse_variables_mapping(step.variables) + # run step extract_mapping = self.run_step(step) + # save extracted variables to session variables session_variables.update(extract_mapping) def run(self):