From f081cf05f2defddca17ad6b4528ce135ccb42e81 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Tue, 21 Apr 2020 14:26:57 +0800 Subject: [PATCH] feat: validate with config/teststep/extracted variables --- .../validate_with_variables.yml | 58 +++++++++++ .../validate_with_variables_test.py | 98 +++++++++++++++++++ httprunner/v3/response.py | 9 +- httprunner/v3/runner.py | 12 ++- httprunner/v3/schema/__init__.py | 4 +- 5 files changed, 173 insertions(+), 8 deletions(-) create mode 100644 examples/postman_echo/request_methods/validate_with_variables.yml create mode 100644 examples/postman_echo/request_methods/validate_with_variables_test.py diff --git a/examples/postman_echo/request_methods/validate_with_variables.yml b/examples/postman_echo/request_methods/validate_with_variables.yml new file mode 100644 index 00000000..7f77219f --- /dev/null +++ b/examples/postman_echo/request_methods/validate_with_variables.yml @@ -0,0 +1,58 @@ +config: + name: "request methods testcase: validate with variables" + variables: + foo1: session_bar1 + base_url: "https://postman-echo.com" + verify: False + +teststeps: +- + name: get with params + variables: + foo1: bar1 + foo2: session_bar2 + request: + method: GET + url: /get + params: + foo1: $foo1 + foo2: $foo2 + headers: + User-Agent: HttpRunner/3.0 + extract: + session_foo2: "body.args.foo2" + validate: + - eq: ["status_code", 200] + - eq: ["body.args.foo1", "$foo1"] + - eq: ["body.args.foo2", "$foo2"] +- + 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-$foo3." + validate: + - eq: ["status_code", 200] + - eq: ["body.data", "This is expected to be sent back as part of response body: session_bar1-$foo3."] +- + name: post form data + variables: + foo1: bar1 + foo2: bar2 + request: + method: POST + url: /post + headers: + User-Agent: HttpRunner/3.0 + Content-Type: "application/x-www-form-urlencoded" + data: "foo1=$foo1&foo2=$foo2" + validate: + - eq: ["status_code", 200] + - eq: ["body.form.foo1", "$foo1"] + - eq: ["body.form.foo2", "$foo2"] diff --git a/examples/postman_echo/request_methods/validate_with_variables_test.py b/examples/postman_echo/request_methods/validate_with_variables_test.py new file mode 100644 index 00000000..14cd2e71 --- /dev/null +++ b/examples/postman_echo/request_methods/validate_with_variables_test.py @@ -0,0 +1,98 @@ +from httprunner.v3.runner import TestCaseRunner +from httprunner.v3.schema import TestsConfig, TestStep + + +class TestCaseRequestMethodsValidateWithVariables(TestCaseRunner): + config = TestsConfig(**{ + "name": "request methods testcase: validate with variables", + "variables": { + "foo1": "session_bar1" + }, + "base_url": "https://postman-echo.com", + "verify": False + }) + + teststeps = [ + TestStep(**{ + "name": "get with params", + "variables": { + "foo1": "bar1", + "foo2": "session_bar2" + }, + "request": { + "method": "GET", + "url": "/get", + "params": { + "foo1": "$foo1", + "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.foo1", "$foo1"]}, + {"eq": ["body.args.foo2", "session_bar2"]}, + {"eq": ["body.args.foo2", "$foo2"]} + ] + }), + TestStep(**{ + "name": "post raw text", + "variables": { + "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-$foo3.", + "headers": { + "User-Agent": "HttpRunner/3.0", + "Content-Type": "text/plain" + } + }, + "validate": [ + {"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: $foo1-$foo3." + ]}, + ] + }), + TestStep(**{ + "name": "post form data", + "variables": { + "foo1": "session_bar1", + "foo2": "bar2" + }, + "request": { + "method": "POST", + "url": "/post", + "data": "foo1=$foo1&foo2=$foo2", + "headers": { + "User-Agent": "HttpRunner/3.0", + "Content-Type": "application/x-www-form-urlencoded" + } + }, + "validate": [ + {"eq": ["status_code", 200]}, + {"eq": ["body.form.foo1", "session_bar1"]}, + {"eq": ["body.form.foo1", "$foo1"]}, + {"eq": ["body.form.foo2", "bar2"]}, + {"eq": ["body.form.foo2", "$foo2"]} + ] + }) + ] + + +if __name__ == '__main__': + TestCaseRequestMethodsValidateWithVariables().run() diff --git a/httprunner/v3/response.py b/httprunner/v3/response.py index 5dbf9577..222e63b7 100644 --- a/httprunner/v3/response.py +++ b/httprunner/v3/response.py @@ -1,10 +1,12 @@ -from typing import Dict, Text, Any +from typing import Dict, Text, Any, NoReturn import jmespath import requests from loguru import logger from httprunner.v3.exceptions import ParamsError, ValidationFailure +from httprunner.v3.parser import parse_data +from httprunner.v3.schema import VariablesMapping, Validators from httprunner.v3.validator import uniform_validator, AssertMethods @@ -23,7 +25,7 @@ class ResponseObject(object): "body": resp_obj.json() } - def validate(self, validators): + def validate(self, validators: Validators, variables_mapping: VariablesMapping = None) -> NoReturn: for v in validators: u_validator = uniform_validator(v) @@ -39,6 +41,9 @@ class ResponseObject(object): except AttributeError: raise ParamsError(f"Assert Method not supported: {assert_method}") + # parse expected value with config/teststep/extracted variables + expect_value = parse_data(expect_value, variables_mapping) + try: assert_func(actual_value, expect_value) msg += " - success" diff --git a/httprunner/v3/runner.py b/httprunner/v3/runner.py index 8ab7113b..45c92ad3 100644 --- a/httprunner/v3/runner.py +++ b/httprunner/v3/runner.py @@ -44,13 +44,17 @@ class TestCaseRunner(object): resp = session.request(method, url, **parsed_request_dict) resp_obj = ResponseObject(resp) - # validate - validators = step.validation - resp_obj.validate(validators) - # extract extractors = step.extract extract_mapping = resp_obj.extract(extractors) + + variables_mapping = step.variables + variables_mapping.update(extract_mapping) + + # validate + validators = step.validation + resp_obj.validate(validators, variables_mapping) + return extract_mapping def test_start(self): diff --git a/httprunner/v3/schema/__init__.py b/httprunner/v3/schema/__init__.py index 198e4b57..00577a4d 100644 --- a/httprunner/v3/schema/__init__.py +++ b/httprunner/v3/schema/__init__.py @@ -14,7 +14,7 @@ Headers = Dict[Text, Text] Verify = bool Hook = List[Text] Export = List[Text] -Validate = List[Dict] +Validators = List[Dict] Env = Dict[Text, Any] @@ -59,4 +59,4 @@ class TestStep(BaseModel): request: Request variables: VariablesMapping = {} extract: Dict[Text, Text] = {} - validation: Validate = Field([], alias="validate") + validation: Validators = Field([], alias="validate")