feat: make pytest files in chain style

This commit is contained in:
debugtalk
2020-06-03 16:50:53 +08:00
parent e1e7ba7bea
commit 6fa680502e
21 changed files with 937 additions and 526 deletions
+62
View File
@@ -0,0 +1,62 @@
# NOTICE: Generated By HttpRunner.
import json
import os
import time
import pytest
from loguru import logger
from httprunner.utils import get_platform
@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
summary["details"].append(testcase_summary.dict())
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)
logger.info(f"generated task summary: {summary_path}")
@@ -0,0 +1,34 @@
config:
name: "set & delete cookies."
base_url: "https://postman-echo.com"
verify: False
export: ["cookie_foo1", "cookie_foo3"]
teststeps:
-
name: set cookie foo1 & foo2 & foo3
request:
method: GET
url: /cookies/set
params:
foo1: bar1
foo2: bar2
headers:
User-Agent: HttpRunner/${get_httprunner_version()}
extract:
cookie_foo1: $.cookies.foo1
validate:
- eq: ["status_code", 200]
- eq: ["cookies.foo1", "bar1"]
-
name: delete cookie foo2
request:
method: GET
url: /cookies/delete?foo2
headers:
User-Agent: HttpRunner/${get_httprunner_version()}
validate:
- eq: ["status_code", 200]
- ne: ["$.cookies.foo1", "$foo1"]
- eq: ["$.cookies.foo1", "$cookie_foo1"]
- eq: ["$.cookies.foo3", "$cookie_foo3"]
@@ -0,0 +1,54 @@
# NOTICE: Generated By HttpRunner. DO NOT EDIT!
# FROM: examples/postman_echo/cookie_manipulation/hardcode.yml
from httprunner import HttpRunner, TConfig, TStep
class TestCaseHardcode(HttpRunner):
config = TConfig(
**{
"name": "set & delete cookies.",
"base_url": "https://postman-echo.com",
"verify": False,
"export": ["cookie_foo1", "cookie_foo3"],
"path": "examples/postman_echo/cookie_manipulation/hardcode_test.py",
}
)
teststeps = [
TStep(
**{
"name": "set cookie foo1 & foo2 & foo3",
"request": {
"method": "GET",
"url": "/cookies/set",
"params": {"foo1": "bar1", "foo2": "bar2"},
"headers": {"User-Agent": "HttpRunner/${get_httprunner_version()}"},
},
"extract": {"cookie_foo1": "$.cookies.foo1"},
"validate": [
{"eq": ["status_code", 200]},
{"eq": ["cookies.foo1", "bar1"]},
],
}
),
TStep(
**{
"name": "delete cookie foo2",
"request": {
"method": "GET",
"url": "/cookies/delete?foo2",
"headers": {"User-Agent": "HttpRunner/${get_httprunner_version()}"},
},
"validate": [
{"eq": ["status_code", 200]},
{"ne": ["$.cookies.foo1", "$foo1"]},
{"eq": ["$.cookies.foo1", "$cookie_foo1"]},
{"eq": ["$.cookies.foo3", "$cookie_foo3"]},
],
}
),
]
if __name__ == "__main__":
TestCaseHardcode().test_start()
@@ -0,0 +1,62 @@
import unittest
import requests
from httprunner.runner import HttpRunner
from httprunner.schema import TConfig, TStep
class TestCaseSetDeleteCookies(unittest.TestCase):
config = TConfig(
**{
"name": "set & delete cookies.",
"base_url": "https://postman-echo.com",
"variables": {"foo1": "bar1", "foo2": "bar2"},
"verify": False,
"export": ["cookie_foo1", "cookie_foo3"],
}
)
teststeps = [
TStep(
**{
"name": "set cookie foo1 & foo2 & foo3",
"variables": {"foo3": "bar3"},
"request": {
"method": "GET",
"url": "/cookies/set",
"params": {"foo1": "bar111", "foo2": "$foo2", "foo3": "$foo3"},
"headers": {"User-Agent": "HttpRunner/${get_httprunner_version()}"},
},
"extract": {
"cookie_foo1": "$.cookies.foo1",
"cookie_foo3": "$.cookies.foo3",
},
"validate": [
{"eq": ["status_code", 200]},
{"eq": ["$.cookies.foo3", "$foo3"]},
],
}
),
TStep(
**{
"name": "delete cookie foo2",
"request": {
"method": "GET",
"url": "/cookies/delete?foo2",
"headers": {"User-Agent": "HttpRunner/${get_httprunner_version()}"},
},
"validate": [
{"eq": ["status_code", 200]},
{"ne": ["$.cookies.foo1", "$foo1"]},
{"eq": ["$.cookies.foo1", "$cookie_foo1"]},
{"eq": ["$.cookies.foo3", "$cookie_foo3"]},
],
}
),
]
def test_start(self):
s = requests.Session()
HttpRunner(self.config, self.teststeps, session=s).with_variables(
foo1="bar123", foo2="bar22"
).run()
@@ -0,0 +1,59 @@
# NOTICE: Generated By HttpRunner. DO NOT EDIT!
# FROM: examples/postman_echo/cookie_manipulation/set_delete_cookies.yml
from httprunner import HttpRunner, TConfig, TStep
class TestCaseSetDeleteCookies(HttpRunner):
config = TConfig(
**{
"name": "set & delete cookies.",
"variables": {"foo1": "bar1", "foo2": "bar2"},
"base_url": "https://postman-echo.com",
"verify": False,
"export": ["cookie_foo1", "cookie_foo3"],
"path": "examples/postman_echo/cookie_manipulation/set_delete_cookies_test.py",
}
)
teststeps = [
TStep(
**{
"name": "set cookie foo1 & foo2 & foo3",
"variables": {"foo3": "bar3"},
"request": {
"method": "GET",
"url": "/cookies/set",
"params": {"foo1": "bar111", "foo2": "$foo2", "foo3": "$foo3"},
"headers": {"User-Agent": "HttpRunner/${get_httprunner_version()}"},
},
"extract": {
"cookie_foo1": "$.cookies.foo1",
"cookie_foo3": "$.cookies.foo3",
},
"validate": [
{"eq": ["status_code", 200]},
{"ne": ["$.cookies.foo3", "$foo3"]},
],
}
),
TStep(
**{
"name": "delete cookie foo2",
"request": {
"method": "GET",
"url": "/cookies/delete?foo2",
"headers": {"User-Agent": "HttpRunner/${get_httprunner_version()}"},
},
"validate": [
{"eq": ["status_code", 200]},
{"ne": ["$.cookies.foo1", "$foo1"]},
{"eq": ["$.cookies.foo1", "$cookie_foo1"]},
{"eq": ["$.cookies.foo3", "$cookie_foo3"]},
],
}
),
]
if __name__ == "__main__":
TestCaseSetDeleteCookies().test_start()
@@ -1,87 +1,69 @@
# NOTICE: Generated By HttpRunner. DO NOT EDIT! # NOTICE: Generated By HttpRunner. DO NOT EDIT!
# FROM: examples/postman_echo/request_methods/request_with_functions.yml # FROM: examples/postman_echo/request_methods/request_with_functions.yml
from httprunner import HttpRunner, TConfig, TStep from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
class TestCaseRequestWithFunctions(HttpRunner): class TestCaseRequestWithFunctions(HttpRunner):
config = TConfig( config = (
**{ Config("request with functions")
"name": "request with functions", .variables(**{"foo1": "session_bar1", "var1": "testsuite_val1"})
"variables": {"foo1": "session_bar1", "var1": "testsuite_val1"}, .base_url("https://postman-echo.com")
"base_url": "https://postman-echo.com", .verify(False)
"verify": False,
"path": "examples/postman_echo/request_methods/demo_testsuite_yml/request_with_functions_test.py",
}
) )
teststeps = [ teststeps = [
TStep( Step(
**{ RunRequest("get with params")
"name": "get with params", .with_variables(
"variables": { **{"foo1": "bar1", "foo2": "session_bar2", "sum_v": "${sum_two(1, 2)}"}
"foo1": "bar1", )
"foo2": "session_bar2", .get("/get")
"sum_v": "${sum_two(1, 2)}", .with_params(**{"foo1": "$foo1", "foo2": "$foo2", "sum_v": "$sum_v"})
}, .with_headers(**{"User-Agent": "HttpRunner/${get_httprunner_version()}"})
"request": { .extract()
"method": "GET", .with_jmespath("body.args.foo2", "session_foo2")
"url": "/get", .validate()
"params": {"foo1": "$foo1", "foo2": "$foo2", "sum_v": "$sum_v"}, .assert_equal("status_code", 200)
"headers": {"User-Agent": "HttpRunner/${get_httprunner_version()}"}, .assert_equal("body.args.foo1", "session_bar1")
}, .assert_equal("body.args.sum_v", "3")
"extract": {"session_foo2": "body.args.foo2"}, .assert_equal("body.args.foo2", "session_bar2")
"validate": [
{"eq": ["status_code", 200]},
{"eq": ["body.args.foo1", "session_bar1"]},
{"eq": ["body.args.sum_v", "3"]},
{"eq": ["body.args.foo2", "session_bar2"]},
],
}
), ),
TStep( Step(
**{ RunRequest("post raw text")
"name": "post raw text", .with_variables(**{"foo1": "hello world", "foo3": "$session_foo2"})
"variables": {"foo1": "hello world", "foo3": "$session_foo2"}, .post("/post")
"request": { .with_headers(
"method": "POST", **{
"url": "/post", "User-Agent": "HttpRunner/${get_httprunner_version()}",
"headers": { "Content-Type": "text/plain",
"User-Agent": "HttpRunner/${get_httprunner_version()}", }
"Content-Type": "text/plain", )
}, .with_data(
"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-$foo3."
}, )
"validate": [ .validate()
{"eq": ["status_code", 200]}, .assert_equal("status_code", 200)
{ .assert_equal(
"eq": [ "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: session_bar1-session_bar2.", )
]
},
],
}
), ),
TStep( Step(
**{ RunRequest("post form data")
"name": "post form data", .with_variables(**{"foo1": "bar1", "foo2": "bar2"})
"variables": {"foo1": "bar1", "foo2": "bar2"}, .post("/post")
"request": { .with_headers(
"method": "POST", **{
"url": "/post", "User-Agent": "HttpRunner/${get_httprunner_version()}",
"headers": { "Content-Type": "application/x-www-form-urlencoded",
"User-Agent": "HttpRunner/${get_httprunner_version()}", }
"Content-Type": "application/x-www-form-urlencoded", )
}, .with_data("foo1=$foo1&foo2=$foo2")
"data": "foo1=$foo1&foo2=$foo2", .validate()
}, .assert_equal("status_code", 200)
"validate": [ .assert_equal("body.form.foo1", "session_bar1")
{"eq": ["status_code", 200]}, .assert_equal("body.form.foo2", "bar2")
{"eq": ["body.form.foo1", "session_bar1"]},
{"eq": ["body.form.foo2", "bar2"]},
],
}
), ),
] ]
@@ -6,7 +6,7 @@ import sys
sys.path.insert(0, os.getcwd()) sys.path.insert(0, os.getcwd())
from httprunner import HttpRunner, TConfig, TStep from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
from examples.postman_echo.request_methods.request_with_functions_test import ( from examples.postman_echo.request_methods.request_with_functions_test import (
TestCaseRequestWithFunctions as RequestWithFunctions, TestCaseRequestWithFunctions as RequestWithFunctions,
@@ -14,23 +14,18 @@ from examples.postman_echo.request_methods.request_with_functions_test import (
class TestCaseRequestWithTestcaseReference(HttpRunner): class TestCaseRequestWithTestcaseReference(HttpRunner):
config = TConfig( config = (
**{ Config("request with referenced testcase")
"name": "request with referenced testcase", .variables(**{"foo1": "session_bar1", "var2": "testsuite_val2"})
"variables": {"foo1": "session_bar1", "var2": "testsuite_val2"}, .base_url("https://postman-echo.com")
"base_url": "https://postman-echo.com", .verify(False)
"verify": False,
"path": "examples/postman_echo/request_methods/demo_testsuite_yml/request_with_testcase_reference_test.py",
}
) )
teststeps = [ teststeps = [
TStep( Step(
**{ RunTestCase("request with functions")
"name": "request with functions", .with_variables(**{"foo1": "override_bar1"})
"variables": {"foo1": "override_bar1"}, .call(RequestWithFunctions)
"testcase": RequestWithFunctions,
}
), ),
] ]
@@ -1,77 +1,57 @@
# NOTICE: Generated By HttpRunner. DO NOT EDIT! # NOTICE: Generated By HttpRunner. DO NOT EDIT!
# FROM: examples/postman_echo/request_methods/hardcode.yml # FROM: examples/postman_echo/request_methods/hardcode.yml
from httprunner import HttpRunner, TConfig, TStep from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
class TestCaseHardcode(HttpRunner): class TestCaseHardcode(HttpRunner):
config = TConfig( config = (
**{ Config("request methods testcase in hardcode")
"name": "request methods testcase in hardcode", .base_url("https://postman-echo.com")
"base_url": "https://postman-echo.com", .verify(False)
"verify": False,
"path": "examples/postman_echo/request_methods/hardcode_test.py",
"variables": {},
}
) )
teststeps = [ teststeps = [
TStep( Step(
**{ RunRequest("get with params")
"name": "get with params", .get("/get")
"request": { .with_params(**{"foo1": "bar1", "foo2": "bar2"})
"method": "GET", .with_headers(**{"User-Agent": "HttpRunner/3.0"})
"url": "/get", .validate()
"params": {"foo1": "bar1", "foo2": "bar2"}, .assert_equal("status_code", 200)
"headers": {"User-Agent": "HttpRunner/3.0"},
},
"validate": [{"eq": ["status_code", 200]}],
}
), ),
TStep( Step(
**{ RunRequest("post raw text")
"name": "post raw text", .post("/post")
"request": { .with_headers(
"method": "POST", **{"User-Agent": "HttpRunner/3.0", "Content-Type": "text/plain"}
"url": "/post", )
"headers": { .with_data("This is expected to be sent back as part of response body.")
"User-Agent": "HttpRunner/3.0", .validate()
"Content-Type": "text/plain", .assert_equal("status_code", 200)
},
"data": "This is expected to be sent back as part of response body.",
},
"validate": [{"eq": ["status_code", 200]}],
}
), ),
TStep( Step(
**{ RunRequest("post form data")
"name": "post form data", .post("/post")
"request": { .with_headers(
"method": "POST", **{
"url": "/post", "User-Agent": "HttpRunner/3.0",
"headers": { "Content-Type": "application/x-www-form-urlencoded",
"User-Agent": "HttpRunner/3.0", }
"Content-Type": "application/x-www-form-urlencoded", )
}, .with_data("foo1=bar1&foo2=bar2")
"data": "foo1=bar1&foo2=bar2", .validate()
}, .assert_equal("status_code", 200)
"validate": [{"eq": ["status_code", 200]}],
}
), ),
TStep( Step(
**{ RunRequest("put request")
"name": "put request", .put("/put")
"request": { .with_headers(
"method": "PUT", **{"User-Agent": "HttpRunner/3.0", "Content-Type": "text/plain"}
"url": "/put", )
"headers": { .with_data("This is expected to be sent back as part of response body.")
"User-Agent": "HttpRunner/3.0", .validate()
"Content-Type": "text/plain", .assert_equal("status_code", 200)
},
"data": "This is expected to be sent back as part of response body.",
},
"validate": [{"eq": ["status_code", 200]}],
}
), ),
] ]
@@ -1,67 +1,88 @@
# NOTICE: Generated By HttpRunner. DO NOT EDIT! # NOTICE: Generated By HttpRunner. DO NOT EDIT!
# 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, Request from httprunner import HttpRunner, TConfig, TStep
class TestCaseRequestWithFunctions(HttpRunner): class TestCaseRequestWithFunctions(HttpRunner):
config = ( config = TConfig(
Config("request methods testcase with functions") **{
.variables(foo1="session_bar1") "name": "request methods testcase with functions",
.base_url("https://postman-echo.com") "variables": {"foo1": "session_bar1"},
.verify(False) "base_url": "https://postman-echo.com",
"verify": False,
"path": "examples/postman_echo/request_methods/request_with_functions_test.py",
}
) )
teststeps = [ teststeps = [
Step("get with params") TStep(
.with_variables(foo1="bar1", foo2="session_bar2", sum_v="${sum_two(1, 2)}") **{
.set_extractor("session_foo2", "body.args.foo2") "name": "get with params",
.run_request( "variables": {
Request() "foo1": "bar1",
.get("/get") "foo2": "session_bar2",
.with_params(foo1="$foo1", foo2="$foo2", sum_v="$sum_v") "sum_v": "${sum_two(1, 2)}",
.with_headers(**{"User-Agent": "HttpRunner/${get_httprunner_version()}"}) },
) "request": {
.assert_equal("status_code", 200) "method": "GET",
.assert_equal("body.args.foo1", "session_bar1") "url": "/get",
.assert_equal("body.args.sum_v", "3") "params": {"foo1": "$foo1", "foo2": "$foo2", "sum_v": "$sum_v"},
.assert_equal("body.args.foo2", "session_bar2"), "headers": {"User-Agent": "HttpRunner/${get_httprunner_version()}"},
Step("post raw text") },
.with_variables(foo1="hello world", foo3="$session_foo2") "extract": {"session_foo2": "body.args.foo2"},
.run_request( "validate": [
Request() {"eq": ["status_code", 200]},
.post("/post") {"eq": ["body.args.foo1", "session_bar1"]},
.with_headers( {"eq": ["body.args.sum_v", "3"]},
**{ {"eq": ["body.args.foo2", "session_bar2"]},
"User-Agent": "HttpRunner/${get_httprunner_version()}", ],
"Content-Type": "text/plain", }
} ),
) TStep(
.with_data( **{
"This is expected to be sent back as part of response body: $foo1-$foo3." "name": "post raw text",
) "variables": {"foo1": "hello world", "foo3": "$session_foo2"},
) "request": {
.assert_equal("status_code", 200) "method": "POST",
.assert_equal( "url": "/post",
"body.data", "headers": {
"This is expected to be sent back as part of response body: session_bar1-session_bar2.", "User-Agent": "HttpRunner/${get_httprunner_version()}",
"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-session_bar2.",
]
},
],
}
),
TStep(
**{
"name": "post form data",
"variables": {"foo1": "bar1", "foo2": "bar2"},
"request": {
"method": "POST",
"url": "/post",
"headers": {
"User-Agent": "HttpRunner/${get_httprunner_version()}",
"Content-Type": "application/x-www-form-urlencoded",
},
"data": "foo1=$foo1&foo2=$foo2",
},
"validate": [
{"eq": ["status_code", 200]},
{"eq": ["body.form.foo1", "session_bar1"]},
{"eq": ["body.form.foo2", "bar2"]},
],
}
), ),
Step("post form data")
.with_variables(**{"foo1": "bar1", "foo2": "bar2"})
.run_request(
Request()
.post("/post")
.with_headers(
**{
"User-Agent": "HttpRunner/${get_httprunner_version()}",
"Content-Type": "application/x-www-form-urlencoded",
}
)
.with_data("foo1=$foo1&foo2=$foo2")
)
.assert_equal("status_code", 200)
.assert_equal("body.form.foo1", "session_bar1")
.assert_equal("body.form.foo2", "bar2"),
] ]
@@ -6,7 +6,7 @@ import sys
sys.path.insert(0, os.getcwd()) sys.path.insert(0, os.getcwd())
from httprunner import HttpRunner, Config, Step from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
from examples.postman_echo.request_methods.request_with_functions_test import ( from examples.postman_echo.request_methods.request_with_functions_test import (
TestCaseRequestWithFunctions as RequestWithFunctions, TestCaseRequestWithFunctions as RequestWithFunctions,
@@ -16,15 +16,17 @@ 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": "session_bar1"})
.base_url("https://postman-echo.com") .base_url("https://postman-echo.com")
.verify(False) .verify(False)
) )
teststeps = [ teststeps = [
Step("request with functions") Step(
.with_variables(foo1="override_bar1") RunTestCase("request with functions")
.run_testcase(RequestWithFunctions), .with_variables(**{"foo1": "override_bar1"})
.call(RequestWithFunctions)
),
] ]
@@ -1,82 +1,63 @@
# NOTICE: Generated By HttpRunner. DO NOT EDIT! # NOTICE: Generated By HttpRunner. DO NOT EDIT!
# FROM: examples/postman_echo/request_methods/request_with_variables.yml # FROM: examples/postman_echo/request_methods/request_with_variables.yml
from httprunner import HttpRunner, TConfig, TStep from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
class TestCaseRequestWithVariables(HttpRunner): class TestCaseRequestWithVariables(HttpRunner):
config = TConfig( config = (
**{ Config("request methods testcase with variables")
"name": "request methods testcase with variables", .variables(**{"foo1": "session_bar1"})
"variables": {"foo1": "session_bar1"}, .base_url("https://postman-echo.com")
"base_url": "https://postman-echo.com", .verify(False)
"verify": False,
"path": "examples/postman_echo/request_methods/request_with_variables_test.py",
}
) )
teststeps = [ teststeps = [
TStep( Step(
**{ RunRequest("get with params")
"name": "get with params", .with_variables(**{"foo1": "bar1", "foo2": "session_bar2"})
"variables": {"foo1": "bar1", "foo2": "session_bar2"}, .get("/get")
"request": { .with_params(**{"foo1": "$foo1", "foo2": "$foo2"})
"method": "GET", .with_headers(**{"User-Agent": "HttpRunner/3.0"})
"url": "/get", .extract()
"params": {"foo1": "$foo1", "foo2": "$foo2"}, .with_jmespath("body.args.foo2", "session_foo2")
"headers": {"User-Agent": "HttpRunner/3.0"}, .validate()
}, .assert_equal("status_code", 200)
"extract": {"session_foo2": "body.args.foo2"}, .assert_equal("body.args.foo1", "session_bar1")
"validate": [ .assert_equal("body.args.foo2", "session_bar2")
{"eq": ["status_code", 200]},
{"eq": ["body.args.foo1", "session_bar1"]},
{"eq": ["body.args.foo2", "session_bar2"]},
],
}
), ),
TStep( Step(
**{ RunRequest("post raw text")
"name": "post raw text", .with_variables(**{"foo1": "hello world", "foo3": "$session_foo2"})
"variables": {"foo1": "hello world", "foo3": "$session_foo2"}, .post("/post")
"request": { .with_headers(
"method": "POST", **{"User-Agent": "HttpRunner/3.0", "Content-Type": "text/plain"}
"url": "/post", )
"headers": { .with_data(
"User-Agent": "HttpRunner/3.0", "This is expected to be sent back as part of response body: $foo1-$foo3."
"Content-Type": "text/plain", )
}, .validate()
"data": "This is expected to be sent back as part of response body: $foo1-$foo3.", .assert_equal("status_code", 200)
}, .assert_equal(
"validate": [ "body.data",
{"eq": ["status_code", 200]}, "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: session_bar1-session_bar2.",
]
},
],
}
), ),
TStep( Step(
**{ RunRequest("post form data")
"name": "post form data", .with_variables(**{"foo1": "bar1", "foo2": "bar2"})
"variables": {"foo1": "bar1", "foo2": "bar2"}, .post("/post")
"request": { .with_headers(
"method": "POST", **{
"url": "/post", "User-Agent": "HttpRunner/3.0",
"headers": { "Content-Type": "application/x-www-form-urlencoded",
"User-Agent": "HttpRunner/3.0", }
"Content-Type": "application/x-www-form-urlencoded", )
}, .with_data("foo1=$foo1&foo2=$foo2")
"data": "foo1=$foo1&foo2=$foo2", .validate()
}, .assert_equal("status_code", 200)
"validate": [ .assert_equal("body.form.foo1", "session_bar1")
{"eq": ["status_code", 200]}, .assert_equal("body.form.foo2", "bar2")
{"eq": ["body.form.foo1", "session_bar1"]},
{"eq": ["body.form.foo2", "bar2"]},
],
}
), ),
] ]
@@ -1,41 +1,31 @@
# NOTICE: Generated By HttpRunner. DO NOT EDIT! # NOTICE: Generated By HttpRunner. DO NOT EDIT!
# FROM: examples/postman_echo/request_methods/validate_with_functions.yml # FROM: examples/postman_echo/request_methods/validate_with_functions.yml
from httprunner import HttpRunner, TConfig, TStep from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
class TestCaseValidateWithFunctions(HttpRunner): class TestCaseValidateWithFunctions(HttpRunner):
config = TConfig( config = (
**{ Config("request methods testcase: validate with functions")
"name": "request methods testcase: validate with functions", .variables(**{"foo1": "session_bar1"})
"variables": {"foo1": "session_bar1"}, .base_url("https://postman-echo.com")
"base_url": "https://postman-echo.com", .verify(False)
"verify": False,
"path": "examples/postman_echo/request_methods/validate_with_functions_test.py",
}
) )
teststeps = [ teststeps = [
TStep( Step(
**{ RunRequest("get with params")
"name": "get with params", .with_variables(
"variables": { **{"foo1": "bar1", "foo2": "session_bar2", "sum_v": "${sum_two(1, 2)}"}
"foo1": "bar1", )
"foo2": "session_bar2", .get("/get")
"sum_v": "${sum_two(1, 2)}", .with_params(**{"foo1": "$foo1", "foo2": "$foo2", "sum_v": "$sum_v"})
}, .with_headers(**{"User-Agent": "HttpRunner/${get_httprunner_version()}"})
"request": { .extract()
"method": "GET", .with_jmespath("body.args.foo2", "session_foo2")
"url": "/get", .validate()
"params": {"foo1": "$foo1", "foo2": "$foo2", "sum_v": "$sum_v"}, .assert_equal("status_code", 200)
"headers": {"User-Agent": "HttpRunner/${get_httprunner_version()}"}, .assert_equal("body.args.sum_v", "3")
},
"extract": {"session_foo2": "body.args.foo2"},
"validate": [
{"eq": ["status_code", 200]},
{"eq": ["body.args.sum_v", "3"]},
],
}
), ),
] ]
@@ -1,82 +1,63 @@
# NOTICE: Generated By HttpRunner. DO NOT EDIT! # NOTICE: Generated By HttpRunner. DO NOT EDIT!
# FROM: examples/postman_echo/request_methods/validate_with_variables.yml # FROM: examples/postman_echo/request_methods/validate_with_variables.yml
from httprunner import HttpRunner, TConfig, TStep from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
class TestCaseValidateWithVariables(HttpRunner): class TestCaseValidateWithVariables(HttpRunner):
config = TConfig( config = (
**{ Config("request methods testcase: validate with variables")
"name": "request methods testcase: validate with variables", .variables(**{"foo1": "session_bar1"})
"variables": {"foo1": "session_bar1"}, .base_url("https://postman-echo.com")
"base_url": "https://postman-echo.com", .verify(False)
"verify": False,
"path": "examples/postman_echo/request_methods/validate_with_variables_test.py",
}
) )
teststeps = [ teststeps = [
TStep( Step(
**{ RunRequest("get with params")
"name": "get with params", .with_variables(**{"foo1": "bar1", "foo2": "session_bar2"})
"variables": {"foo1": "bar1", "foo2": "session_bar2"}, .get("/get")
"request": { .with_params(**{"foo1": "$foo1", "foo2": "$foo2"})
"method": "GET", .with_headers(**{"User-Agent": "HttpRunner/3.0"})
"url": "/get", .extract()
"params": {"foo1": "$foo1", "foo2": "$foo2"}, .with_jmespath("body.args.foo2", "session_foo2")
"headers": {"User-Agent": "HttpRunner/3.0"}, .validate()
}, .assert_equal("status_code", 200)
"extract": {"session_foo2": "body.args.foo2"}, .assert_equal("body.args.foo1", "$foo1")
"validate": [ .assert_equal("body.args.foo2", "$foo2")
{"eq": ["status_code", 200]},
{"eq": ["body.args.foo1", "$foo1"]},
{"eq": ["body.args.foo2", "$foo2"]},
],
}
), ),
TStep( Step(
**{ RunRequest("post raw text")
"name": "post raw text", .with_variables(**{"foo1": "hello world", "foo3": "$session_foo2"})
"variables": {"foo1": "hello world", "foo3": "$session_foo2"}, .post("/post")
"request": { .with_headers(
"method": "POST", **{"User-Agent": "HttpRunner/3.0", "Content-Type": "text/plain"}
"url": "/post", )
"headers": { .with_data(
"User-Agent": "HttpRunner/3.0", "This is expected to be sent back as part of response body: $foo1-$foo3."
"Content-Type": "text/plain", )
}, .validate()
"data": "This is expected to be sent back as part of response body: $foo1-$foo3.", .assert_equal("status_code", 200)
}, .assert_equal(
"validate": [ "body.data",
{"eq": ["status_code", 200]}, "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: session_bar1-$foo3.",
]
},
],
}
), ),
TStep( Step(
**{ RunRequest("post form data")
"name": "post form data", .with_variables(**{"foo1": "bar1", "foo2": "bar2"})
"variables": {"foo1": "bar1", "foo2": "bar2"}, .post("/post")
"request": { .with_headers(
"method": "POST", **{
"url": "/post", "User-Agent": "HttpRunner/3.0",
"headers": { "Content-Type": "application/x-www-form-urlencoded",
"User-Agent": "HttpRunner/3.0", }
"Content-Type": "application/x-www-form-urlencoded", )
}, .with_data("foo1=$foo1&foo2=$foo2")
"data": "foo1=$foo1&foo2=$foo2", .validate()
}, .assert_equal("status_code", 200)
"validate": [ .assert_equal("body.form.foo1", "$foo1")
{"eq": ["status_code", 200]}, .assert_equal("body.form.foo2", "$foo2")
{"eq": ["body.form.foo1", "$foo1"]},
{"eq": ["body.form.foo2", "$foo2"]},
],
}
), ),
] ]
+3 -2
View File
@@ -3,7 +3,7 @@ __description__ = "One-stop solution for HTTP(S) testing."
from httprunner.runner import HttpRunner from httprunner.runner import HttpRunner
from httprunner.schema import TConfig, TStep from httprunner.schema import TConfig, TStep
from httprunner.testcase import Config, Step, Request from httprunner.testcase import Config, Step, RunRequest, RunTestCase
__all__ = [ __all__ = [
"__version__", "__version__",
@@ -13,5 +13,6 @@ __all__ = [
"TStep", "TStep",
"Config", "Config",
"Step", "Step",
"Request", "RunRequest",
"RunTestCase",
] ]
+7 -2
View File
@@ -23,9 +23,14 @@ def main_run(extra_args):
# keep compatibility with v2 # keep compatibility with v2
extra_args = ensure_cli_args(extra_args) extra_args = ensure_cli_args(extra_args)
chain_style = False
tests_path_list = [] tests_path_list = []
extra_args_new = [] extra_args_new = []
for item in extra_args: for item in extra_args:
if item == "--chain-style":
chain_style = True
continue
if not os.path.exists(item): if not os.path.exists(item):
# item is not file/folder path # item is not file/folder path
extra_args_new.append(item) extra_args_new.append(item)
@@ -38,7 +43,7 @@ def main_run(extra_args):
logger.error(f"No valid testcase path in cli arguments: {extra_args}") logger.error(f"No valid testcase path in cli arguments: {extra_args}")
sys.exit(1) sys.exit(1)
testcase_path_list = main_make(tests_path_list) testcase_path_list = main_make(tests_path_list, chain_style=chain_style)
if not testcase_path_list: if not testcase_path_list:
logger.error("No valid testcases found, exit 1.") logger.error("No valid testcases found, exit 1.")
sys.exit(1) sys.exit(1)
@@ -110,7 +115,7 @@ def main():
elif sys.argv[1] == "har2case": elif sys.argv[1] == "har2case":
main_har2case(args) main_har2case(args)
elif sys.argv[1] == "make": elif sys.argv[1] == "make":
main_make(args.testcase_path) main_make(args.testcase_path, chain_style=args.chain_style)
def main_hrun_alias(): def main_hrun_alias():
+158 -13
View File
@@ -16,6 +16,7 @@ from httprunner.loader import (
load_project_meta, load_project_meta,
) )
from httprunner.parser import parse_data from httprunner.parser import parse_data
from httprunner.response import uniform_validator
""" cache converted pytest files, avoid duplicate making """ cache converted pytest files, avoid duplicate making
""" """
@@ -50,6 +51,35 @@ if __name__ == "__main__":
""" """
) )
__TEMPLATE_CHAIN_STYLE__ = jinja2.Template(
"""# NOTICE: Generated By HttpRunner. DO NOT EDIT!
# FROM: {{ testcase_path }}
{% if imports_list %}
import os
import sys
sys.path.insert(0, os.getcwd())
{% endif %}
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
{% for import_str in imports_list %}
{{ import_str }}
{% endfor %}
class {{ class_name }}(HttpRunner):
config = {{ config_chain_style }}
teststeps = [
{% for step_chain_style in teststeps_chain_style %}
{{ step_chain_style }},
{% endfor %}
]
if __name__ == "__main__":
{{ class_name }}().test_start()
"""
)
def __ensure_file_name(path: Text) -> Text: def __ensure_file_name(path: Text) -> Text:
""" ensure file name not startswith digit """ ensure file name not startswith digit
@@ -96,7 +126,7 @@ def __ensure_testcase_module(path: Text) -> NoReturn:
return return
with open(init_file, "w", encoding="utf-8") as f: with open(init_file, "w", encoding="utf-8") as f:
f.write("# NOTICE: Generated By HttpRunner. DO NOT EDIT!") f.write("# NOTICE: Generated By HttpRunner. DO NOT EDIT!\n")
def convert_testcase_path(testcase_path: Text) -> Tuple[Text, Text]: def convert_testcase_path(testcase_path: Text) -> Tuple[Text, Text]:
@@ -132,8 +162,105 @@ def __format_pytest_with_black(python_paths: List[Text]) -> NoReturn:
logger.error(ex) logger.error(ex)
def make_config_chain_style(config: Dict) -> Text:
config_chain_style = f'Config("{config["name"]}")'
if config["variables"]:
variables = config["variables"]
config_chain_style += f".variables(**{variables})"
if "base_url" in config:
config_chain_style += f'.base_url("{config["base_url"]}")'
if "verify" in config:
config_chain_style += f'.verify({config["verify"]})'
return config_chain_style
def make_request_chain_style(request: Dict) -> Text:
method = request["method"].lower()
url = request["url"]
request_chain_style = f'.{method}("{url}")'
if "params" in request:
params = request["params"]
request_chain_style += f".with_params(**{params})"
if "headers" in request:
headers = request["headers"]
request_chain_style += f".with_headers(**{headers})"
if "cookies" in request:
cookies = request["cookies"]
request_chain_style += f".with_cookies(**{cookies})"
if "data" in request:
data = request["data"]
if isinstance(data, Text):
data = f'"{data}"'
request_chain_style += f".with_data({data})"
if "timeout" in request:
timeout = request["timeout"]
request_chain_style += f".set_timeout({timeout})"
if "verify" in request:
verify = request["verify"]
request_chain_style += f".set_verify({verify})"
if "allow_redirects" in request:
allow_redirects = request["allow_redirects"]
request_chain_style += f".set_allow_redirects({allow_redirects})"
return request_chain_style
def make_teststep_chain_style(teststep: Dict) -> Text:
if teststep.get("request"):
step_info = f'RunRequest("{teststep["name"]}")'
elif teststep.get("testcase"):
step_info = f'RunTestCase("{teststep["name"]}")'
else:
raise exceptions.TestCaseFormatError
if "variables" in teststep:
variables = teststep["variables"]
step_info += f".with_variables(**{variables})"
if teststep.get("request"):
step_info += make_request_chain_style(teststep["request"])
elif teststep.get("testcase"):
testcase = teststep["testcase"].replace("CLS_LB(", "").replace(")CLS_RB", "")
call_ref_testcase = f".call({testcase})"
step_info += call_ref_testcase
if "extract" in teststep:
step_info += ".extract()"
for extract_name, extract_path in teststep["extract"].items():
step_info += f'.with_jmespath("{extract_path}", "{extract_name}")'
if "validate" in teststep:
step_info += ".validate()"
for v in teststep["validate"]:
validator = uniform_validator(v)
assert_method = validator["assert"]
check = validator["check"]
expect = validator["expect"]
if isinstance(expect, Text):
expect = f'"{expect}"'
step_info += f'.assert_{assert_method}("{check}", {expect})'
return f"Step({step_info})"
def __make_testcase( def __make_testcase(
testcase: Dict, dir_path: Text = None, ref_flag: bool = False testcase: Dict,
dir_path: Text = None,
ref_flag: bool = False,
chain_style: bool = False,
) -> NoReturn: ) -> NoReturn:
"""convert valid testcase dict to pytest file path""" """convert valid testcase dict to pytest file path"""
# ensure compatibility with testcase format v2 # ensure compatibility with testcase format v2
@@ -195,12 +322,20 @@ def __make_testcase(
data = { data = {
"testcase_path": __ensure_cwd_relative(testcase_path), "testcase_path": __ensure_cwd_relative(testcase_path),
"class_name": f"TestCase{testcase_cls_name}", "class_name": f"TestCase{testcase_cls_name}",
"config": config,
"teststeps": teststeps,
"imports_list": imports_list, "imports_list": imports_list,
} }
content = __TEMPLATE__.render(data)
content = content.replace("'CLS_LB(", "").replace(")CLS_RB'", "") if chain_style:
data["config_chain_style"] = make_config_chain_style(config)
data["teststeps_chain_style"] = [
make_teststep_chain_style(step) for step in teststeps
]
content = __TEMPLATE_CHAIN_STYLE__.render(data)
else:
data["config"] = config
data["teststeps"] = teststeps
content = __TEMPLATE__.render(data)
content = content.replace("'CLS_LB(", "").replace(")CLS_RB'", "")
with open(testcase_python_path, "w", encoding="utf-8") as f: with open(testcase_python_path, "w", encoding="utf-8") as f:
f.write(content) f.write(content)
@@ -213,7 +348,7 @@ def __make_testcase(
make_files_cache_set.add(__ensure_cwd_relative(testcase_python_path)) make_files_cache_set.add(__ensure_cwd_relative(testcase_python_path))
def __make_testsuite(testsuite: Dict) -> NoReturn: def __make_testsuite(testsuite: Dict, chain_style: bool = False) -> NoReturn:
"""convert valid testsuite dict to pytest folder with testcases""" """convert valid testsuite dict to pytest folder with testcases"""
# validate testsuite format # validate testsuite format
load_testsuite(testsuite) load_testsuite(testsuite)
@@ -258,10 +393,12 @@ def __make_testsuite(testsuite: Dict) -> NoReturn:
testcase_dict["config"]["variables"].update(testsuite_variables) testcase_dict["config"]["variables"].update(testsuite_variables)
# make testcase # make testcase
__make_testcase(testcase_dict, testsuite_dir) __make_testcase(testcase_dict, testsuite_dir, chain_style=chain_style)
def __make(tests_path: Text, ref_flag: bool = False) -> NoReturn: def __make(
tests_path: Text, ref_flag: bool = False, chain_style: bool = False
) -> NoReturn:
""" make testcase(s) with testcase/testsuite/folder absolute path """ make testcase(s) with testcase/testsuite/folder absolute path
generated pytest file path will be cached in make_files_cache_set generated pytest file path will be cached in make_files_cache_set
@@ -295,14 +432,16 @@ def __make(tests_path: Text, ref_flag: bool = False) -> NoReturn:
# testcase # testcase
if "teststeps" in test_content: if "teststeps" in test_content:
try: try:
__make_testcase(test_content, ref_flag=ref_flag) __make_testcase(
test_content, ref_flag=ref_flag, chain_style=chain_style
)
except exceptions.TestCaseFormatError: except exceptions.TestCaseFormatError:
continue continue
# testsuite # testsuite
elif "testcases" in test_content: elif "testcases" in test_content:
try: try:
__make_testsuite(test_content) __make_testsuite(test_content, chain_style=chain_style)
except exceptions.TestSuiteFormatError: except exceptions.TestSuiteFormatError:
continue continue
@@ -313,12 +452,12 @@ def __make(tests_path: Text, ref_flag: bool = False) -> NoReturn:
) )
def main_make(tests_paths: List[Text]) -> List[Text]: def main_make(tests_paths: List[Text], chain_style: bool = False) -> List[Text]:
for tests_path in tests_paths: for tests_path in tests_paths:
if not os.path.isabs(tests_path): if not os.path.isabs(tests_path):
tests_path = os.path.join(os.getcwd(), tests_path) tests_path = os.path.join(os.getcwd(), tests_path)
__make(tests_path) __make(tests_path, chain_style=chain_style)
testcase_path_list = list(make_files_cache_set) testcase_path_list = list(make_files_cache_set)
__format_pytest_with_black(testcase_path_list) __format_pytest_with_black(testcase_path_list)
@@ -334,5 +473,11 @@ def init_make_parser(subparsers):
parser.add_argument( parser.add_argument(
"testcase_path", nargs="*", help="Specify YAML/JSON testcase file/folder path" "testcase_path", nargs="*", help="Specify YAML/JSON testcase file/folder path"
) )
parser.add_argument(
"--chain-style",
dest="chain_style",
action="store_true",
help="Convert pytest files in chain-style.",
)
return parser return parser
+3 -3
View File
@@ -20,7 +20,7 @@ from httprunner.ext.uploader import prepare_upload_step
from httprunner.loader import load_project_meta, load_testcase_file 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, StepValidation from httprunner.testcase import Config, Step
from httprunner.schema import ( from httprunner.schema import (
TConfig, TConfig,
TStep, TStep,
@@ -36,7 +36,7 @@ from httprunner.schema import (
class HttpRunner(object): class HttpRunner(object):
config: Union[TConfig, Config] config: Union[TConfig, Config]
teststeps: List[Union[TStep, StepValidation]] teststeps: List[Union[TStep, Step]]
success: bool = True # indicate testcase execution result success: bool = True # indicate testcase execution result
__config: TConfig __config: TConfig
@@ -64,7 +64,7 @@ class HttpRunner(object):
for step in self.teststeps: for step in self.teststeps:
if isinstance(step, TStep): if isinstance(step, TStep):
self.__teststeps.append(step) self.__teststeps.append(step)
elif isinstance(step, StepValidation): elif isinstance(step, Step):
self.__teststeps.append(step.perform()) self.__teststeps.append(step.perform())
else: else:
raise exceptions.TestCaseFormatError(f"step type error: {step}") raise exceptions.TestCaseFormatError(f"step type error: {step}")
+142 -130
View File
@@ -1,5 +1,5 @@
import inspect import inspect
from typing import Text, Any, Dict, Callable from typing import Text, Any, Union, Callable
from httprunner.schema import ( from httprunner.schema import (
TConfig, TConfig,
@@ -50,154 +50,166 @@ class Config(object):
) )
class RequestWithOptionalArgs(object):
def __init__(self, method: MethodEnum, url: Text):
self.__method = method
self.__url = url
self.__params = {}
self.__headers = {}
self.__cookies = {}
self.__data = ""
self.__timeout = 120
self.__allow_redirects = True
self.__verify = False
def with_params(self, **params) -> "RequestWithOptionalArgs":
self.__params.update(params)
return self
def with_headers(self, **headers) -> "RequestWithOptionalArgs":
self.__headers.update(headers)
return self
def with_cookies(self, **cookies) -> "RequestWithOptionalArgs":
self.__cookies.update(cookies)
return self
def with_data(self, data) -> "RequestWithOptionalArgs":
self.__data = data
return self
def set_timeout(self, timeout: float) -> "RequestWithOptionalArgs":
self.__timeout = timeout
return self
def set_verify(self, verify: bool) -> "RequestWithOptionalArgs":
self.__verify = verify
return self
def set_allow_redirects(self, allow_redirects: bool) -> "RequestWithOptionalArgs":
self.__allow_redirects = allow_redirects
return self
def perform(self) -> TRequest:
"""build TRequest object with configs"""
return TRequest(
method=self.__method,
url=self.__url,
params=self.__params,
headers=self.__headers,
data=self.__data,
timeout=self.__timeout,
verify=self.__verify,
allow_redirects=self.__allow_redirects,
)
class Request(object):
def get(self, url: Text) -> RequestWithOptionalArgs:
return RequestWithOptionalArgs(MethodEnum.GET, url)
def post(self, url: Text) -> RequestWithOptionalArgs:
return RequestWithOptionalArgs(MethodEnum.POST, url)
def put(self, url: Text) -> RequestWithOptionalArgs:
return RequestWithOptionalArgs(MethodEnum.PUT, url)
def head(self, url: Text) -> RequestWithOptionalArgs:
return RequestWithOptionalArgs(MethodEnum.HEAD, url)
def delete(self, url: Text) -> RequestWithOptionalArgs:
return RequestWithOptionalArgs(MethodEnum.DELETE, url)
def options(self, url: Text) -> RequestWithOptionalArgs:
return RequestWithOptionalArgs(MethodEnum.OPTIONS, url)
def patch(self, url: Text) -> RequestWithOptionalArgs:
return RequestWithOptionalArgs(MethodEnum.PATCH, url)
class StepValidation(object): class StepValidation(object):
def __init__( def __init__(self, step: TStep):
self, self.__t_step = step
name: Text,
variables: Dict,
extractors: Dict,
request: TRequest = None,
testcase: Callable = None,
):
self.__name = name
self.__variables = variables
self.__extractors = extractors
self.__request: TRequest = request
self.__testcase: Callable = testcase
self.__validators = []
@property
def request(self) -> TRequest:
return self.__request
@property
def testcase(self) -> TestCase:
return self.__testcase
def assert_equal(self, jmes_path: Text, expected_value: Any) -> "StepValidation": def assert_equal(self, jmes_path: Text, expected_value: Any) -> "StepValidation":
self.__validators.append({"eq": [jmes_path, expected_value]}) self.__t_step.validators.append({"eq": [jmes_path, expected_value]})
return self return self
def assert_greater_than( def assert_greater_than(
self, jmes_path: Text, expected_value: Any self, jmes_path: Text, expected_value: Any
) -> "StepValidation": ) -> "StepValidation":
self.__validators.append({"gt": [jmes_path, expected_value]}) self.__t_step.validators.append({"gt": [jmes_path, expected_value]})
return self return self
def assert_less_than( def assert_less_than(
self, jmes_path: Text, expected_value: Any self, jmes_path: Text, expected_value: Any
) -> "StepValidation": ) -> "StepValidation":
self.__validators.append({"lt": [jmes_path, expected_value]}) self.__t_step.validators.append({"lt": [jmes_path, expected_value]})
return self return self
def perform(self) -> TStep: def perform(self) -> TStep:
return TStep( return self.__t_step
name=self.__name,
variables=self.__variables,
request=self.__request, class StepExtraction(object):
testcase=self.__testcase, def __init__(self, step: TStep):
extract=self.__extractors, self.__t_step = step
validate=self.__validators,
) def with_jmespath(self, jmes_path: Text, var_name: Text) -> "StepExtraction":
self.__t_step.extract[var_name] = jmes_path
return self
# def with_regex(self):
# # TODO: extract response html with regex
# pass
#
# def with_jsonpath(self):
# # TODO: extract response json with jsonpath
# pass
def validate(self) -> StepValidation:
return StepValidation(self.__t_step)
def perform(self) -> TStep:
return self.__t_step
class RequestWithOptionalArgs(object):
def __init__(self, step: TStep):
self.__t_step = step
def with_params(self, **params) -> "RequestWithOptionalArgs":
self.__t_step.request.params.update(params)
return self
def with_headers(self, **headers) -> "RequestWithOptionalArgs":
self.__t_step.request.headers.update(headers)
return self
def with_cookies(self, **cookies) -> "RequestWithOptionalArgs":
self.__t_step.request.cookies.update(cookies)
return self
def with_data(self, data) -> "RequestWithOptionalArgs":
self.__t_step.request.data = data
return self
def set_timeout(self, timeout: float) -> "RequestWithOptionalArgs":
self.__t_step.request.timeout = timeout
return self
def set_verify(self, verify: bool) -> "RequestWithOptionalArgs":
self.__t_step.request.verify = verify
return self
def set_allow_redirects(self, allow_redirects: bool) -> "RequestWithOptionalArgs":
self.__t_step.request.allow_redirects = allow_redirects
return self
# def hooks(self):
# pass
def extract(self) -> StepExtraction:
return StepExtraction(self.__t_step)
def validate(self) -> StepValidation:
return StepValidation(self.__t_step)
def perform(self) -> TStep:
return self.__t_step
class RunRequest(object):
def __init__(self, name: Text):
self.__t_step = TStep(name=name)
def with_variables(self, **variables) -> "RunRequest":
self.__t_step.variables.update(variables)
return self
def get(self, url: Text) -> RequestWithOptionalArgs:
self.__t_step.request = TRequest(method=MethodEnum.GET, url=url)
return RequestWithOptionalArgs(self.__t_step)
def post(self, url: Text) -> RequestWithOptionalArgs:
self.__t_step.request = TRequest(method=MethodEnum.POST, url=url)
return RequestWithOptionalArgs(self.__t_step)
def put(self, url: Text) -> RequestWithOptionalArgs:
self.__t_step.request = TRequest(method=MethodEnum.PUT, url=url)
return RequestWithOptionalArgs(self.__t_step)
def head(self, url: Text) -> RequestWithOptionalArgs:
self.__t_step.request = TRequest(method=MethodEnum.HEAD, url=url)
return RequestWithOptionalArgs(self.__t_step)
def delete(self, url: Text) -> RequestWithOptionalArgs:
self.__t_step.request = TRequest(method=MethodEnum.DELETE, url=url)
return RequestWithOptionalArgs(self.__t_step)
def options(self, url: Text) -> RequestWithOptionalArgs:
self.__t_step.request = TRequest(method=MethodEnum.OPTIONS, url=url)
return RequestWithOptionalArgs(self.__t_step)
def patch(self, url: Text) -> RequestWithOptionalArgs:
self.__t_step.request = TRequest(method=MethodEnum.PATCH, url=url)
return RequestWithOptionalArgs(self.__t_step)
class RunTestCase(object):
def __init__(self, name: Text):
self.__t_step = TStep(name=name)
def with_variables(self, **variables) -> "RunTestCase":
self.__t_step.variables.update(variables)
return self
def call(self, testcase: Callable):
self.__t_step.testcase = testcase
def perform(self) -> TStep:
return self.__t_step
class Step(object): class Step(object):
def __init__(self, name: Text): def __init__(
self.__name = name self,
self.__variables = {} step: Union[
self.__extractors = {} StepValidation, StepExtraction, RequestWithOptionalArgs, RunTestCase
],
):
self.__t_step = step.perform()
def with_variables(self, **variables) -> "Step": @property
self.__variables.update(variables) def request(self) -> TRequest:
return self return self.__t_step.request
def set_extractor(self, var_name: Text, jmes_path: Text) -> "Step": @property
self.__extractors[var_name] = jmes_path def testcase(self) -> TestCase:
return self return self.__t_step.testcase
def run_request(self, req_obj: RequestWithOptionalArgs) -> "StepValidation": def perform(self) -> TStep:
return StepValidation( return self.__t_step
self.__name, self.__variables, self.__extractors, request=req_obj.perform()
)
def run_testcase(self, testcase: Callable) -> "StepValidation":
return StepValidation(
self.__name, self.__variables, self.__extractors, testcase=testcase
)
+46 -1
View File
@@ -1,6 +1,12 @@
import unittest import unittest
from httprunner.make import main_make, convert_testcase_path, make_files_cache_set from httprunner.make import (
main_make,
convert_testcase_path,
make_files_cache_set,
make_config_chain_style,
make_teststep_chain_style,
)
class TestLoader(unittest.TestCase): class TestLoader(unittest.TestCase):
@@ -95,3 +101,42 @@ from examples.postman_echo.request_methods.request_with_functions_test import (
"examples/postman_echo/request_methods/demo_testsuite_yml/request_with_testcase_reference_test.py", "examples/postman_echo/request_methods/demo_testsuite_yml/request_with_testcase_reference_test.py",
testcase_python_list, testcase_python_list,
) )
def test_make_config_chain_style(self):
config = {
"name": "request methods testcase: validate with functions",
"variables": {"foo1": "bar1", "foo2": 22},
"base_url": "https://postman-echo.com",
"verify": False,
"path": "examples/postman_echo/request_methods/validate_with_functions_test.py",
}
self.assertEqual(
make_config_chain_style(config),
"""Config("request methods testcase: validate with functions").variables(**{'foo1': 'bar1', 'foo2': 22}).base_url("https://postman-echo.com").verify(False)""",
)
def test_make_teststep_chain_style(self):
step = {
"name": "get with params",
"variables": {"foo1": "bar1", "foo2": 123, "sum_v": "${sum_two(1, 2)}",},
"request": {
"method": "GET",
"url": "/get",
"params": {"foo1": "$foo1", "foo2": "$foo2", "sum_v": "$sum_v"},
"headers": {"User-Agent": "HttpRunner/${get_httprunner_version()}"},
},
"testcase": "CLS_LB(TestCaseDemo)CLS_RB",
"extract": {
"session_foo1": "body.args.foo1",
"session_foo2": "body.args.foo2",
},
"validate": [
{"eq": ["status_code", 200]},
{"eq": ["body.args.sum_v", "3"]},
],
}
teststep_chain_style = make_teststep_chain_style(step)
self.assertEqual(
teststep_chain_style,
"""Step(RunRequest("get with params").with_variables(**{'foo1': 'bar1', 'foo2': 123, 'sum_v': '${sum_two(1, 2)}'}).get("/get").with_params(**{'foo1': '$foo1', 'foo2': '$foo2', 'sum_v': '$sum_v'}).with_headers(**{'User-Agent': 'HttpRunner/${get_httprunner_version()}'}).extract().with_jmespath("body.args.foo1", "session_foo1").with_jmespath("body.args.foo2", "session_foo2").validate().assert_equal("status_code", 200).assert_equal("body.args.sum_v", "3"))""",
)