mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-12 02:21:29 +08:00
change: move all unittests to tests folder
This commit is contained in:
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
0
tests/app/__init__.py
Normal file
0
tests/app/__init__.py
Normal file
50
tests/app/debug_test.py
Normal file
50
tests/app/debug_test.py
Normal file
@@ -0,0 +1,50 @@
|
||||
import unittest
|
||||
|
||||
from starlette.testclient import TestClient
|
||||
|
||||
from httprunner.app.main import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
class TestDebug(unittest.TestCase):
|
||||
def test_debug_single_testcase(self):
|
||||
json_data = {
|
||||
"project_meta": {
|
||||
"debugtalk_py": "\ndef hello(name):\n print(f'hello, {name}')\n",
|
||||
"variables": {},
|
||||
"env": {},
|
||||
},
|
||||
"testcase": {
|
||||
"config": {
|
||||
"name": "test demo for debug service",
|
||||
"verify": False,
|
||||
"base_url": "",
|
||||
"variables": {},
|
||||
"setup_hooks": [],
|
||||
"teardown_hooks": [],
|
||||
"export": [],
|
||||
},
|
||||
"teststeps": [
|
||||
{
|
||||
"name": "get index page",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"url": "https://httpbin.org/",
|
||||
"params": {},
|
||||
"headers": {},
|
||||
"json": {},
|
||||
"cookies": {},
|
||||
"timeout": 30,
|
||||
"allow_redirects": True,
|
||||
"verify": False,
|
||||
},
|
||||
"extract": {},
|
||||
"validate": [],
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
response = client.post("/hrun/debug/testcase", json=json_data)
|
||||
assert response.status_code == 200
|
||||
assert response.json()["code"] == 0
|
||||
48
tests/cli_test.py
Normal file
48
tests/cli_test.py
Normal file
@@ -0,0 +1,48 @@
|
||||
import io
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import pytest
|
||||
|
||||
from httprunner.cli import main
|
||||
|
||||
|
||||
class TestCli(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.captured_output = io.StringIO()
|
||||
sys.stdout = self.captured_output
|
||||
|
||||
def tearDown(self):
|
||||
sys.stdout = sys.__stdout__ # Reset redirect.
|
||||
|
||||
def test_show_version(self):
|
||||
sys.argv = ["hrun", "-V"]
|
||||
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
main()
|
||||
|
||||
self.assertEqual(cm.exception.code, 0)
|
||||
|
||||
from httprunner import __version__
|
||||
|
||||
self.assertIn(__version__, self.captured_output.getvalue().strip())
|
||||
|
||||
def test_show_help(self):
|
||||
sys.argv = ["hrun", "-h"]
|
||||
|
||||
with self.assertRaises(SystemExit) as cm:
|
||||
main()
|
||||
|
||||
self.assertEqual(cm.exception.code, 0)
|
||||
|
||||
from httprunner import __description__
|
||||
|
||||
self.assertIn(__description__, self.captured_output.getvalue().strip())
|
||||
|
||||
def test_debug_pytest(self):
|
||||
pytest.main(
|
||||
[
|
||||
"-s",
|
||||
"examples/postman_echo/request_methods/request_with_testcase_reference_test.py",
|
||||
]
|
||||
)
|
||||
161
tests/compat_test.py
Normal file
161
tests/compat_test.py
Normal file
@@ -0,0 +1,161 @@
|
||||
import unittest
|
||||
|
||||
from httprunner import compat
|
||||
|
||||
|
||||
class TestCompat(unittest.TestCase):
|
||||
def test_convert_jmespath(self):
|
||||
|
||||
self.assertEqual(compat.convert_jmespath("content.abc"), "body.abc")
|
||||
self.assertEqual(compat.convert_jmespath("json.abc"), "body.abc")
|
||||
self.assertEqual(
|
||||
compat.convert_jmespath("headers.Content-Type"), 'headers."Content-Type"'
|
||||
)
|
||||
self.assertEqual(
|
||||
compat.convert_jmespath("body.data.buildings.0.building_id"),
|
||||
"body.data.buildings[0].building_id",
|
||||
)
|
||||
|
||||
def test_convert_extractors(self):
|
||||
self.assertEqual(
|
||||
compat.convert_extractors(
|
||||
[{"varA": "content.varA"}, {"varB": "json.varB"}]
|
||||
),
|
||||
{"varA": "body.varA", "varB": "body.varB"},
|
||||
)
|
||||
self.assertEqual(
|
||||
compat.convert_extractors([{"varA": "content.0.varA"}]),
|
||||
{"varA": "body[0].varA"},
|
||||
)
|
||||
self.assertEqual(
|
||||
compat.convert_extractors({"varA": "content.0.varA"}),
|
||||
{"varA": "body[0].varA"},
|
||||
)
|
||||
|
||||
def test_convert_validators(self):
|
||||
self.assertEqual(
|
||||
compat.convert_validators(
|
||||
[{"check": "content.abc", "assert": "eq", "expect": 201}]
|
||||
),
|
||||
[{"check": "body.abc", "assert": "eq", "expect": 201}],
|
||||
)
|
||||
self.assertEqual(
|
||||
compat.convert_validators([{"eq": ["content.abc", 201]}]),
|
||||
[{"eq": ["body.abc", 201]}],
|
||||
)
|
||||
self.assertEqual(
|
||||
compat.convert_validators([{"eq": ["content.0.name", 201]}]),
|
||||
[{"eq": ["body[0].name", 201]}],
|
||||
)
|
||||
|
||||
def test_ensure_testcase_v3_api(self):
|
||||
api_content = {
|
||||
"name": "get with params",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"url": "/get",
|
||||
"params": {"foo1": "bar1", "foo2": "bar2"},
|
||||
"headers": {"User-Agent": "HttpRunner/3.0"},
|
||||
},
|
||||
"extract": [{"varA": "content.varA"}, {"user_agent": "headers.User-Agent"}],
|
||||
"validate": [{"eq": ["content.varB", 200]}, {"lt": ["json.0.varC", 0]}],
|
||||
}
|
||||
self.assertEqual(
|
||||
compat.ensure_testcase_v3_api(api_content),
|
||||
{
|
||||
"config": {"name": "get with params"},
|
||||
"teststeps": [
|
||||
{
|
||||
"name": "get with params",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"url": "/get",
|
||||
"params": {"foo1": "bar1", "foo2": "bar2"},
|
||||
"headers": {"User-Agent": "HttpRunner/3.0"},
|
||||
},
|
||||
"extract": {
|
||||
"varA": "body.varA",
|
||||
"user_agent": 'headers."User-Agent"',
|
||||
},
|
||||
"validate": [
|
||||
{"eq": ["body.varB", 200]},
|
||||
{"lt": ["body[0].varC", 0]},
|
||||
],
|
||||
}
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
def test_ensure_testcase_v3(self):
|
||||
testcase_content = {
|
||||
"config": {"name": "xxx", "base_url": "https://httpbin.org"},
|
||||
"teststeps": [
|
||||
{
|
||||
"name": "get with params",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"url": "/get",
|
||||
"params": {"foo1": "bar1", "foo2": "bar2"},
|
||||
"headers": {"User-Agent": "HttpRunner/3.0"},
|
||||
},
|
||||
"extract": [
|
||||
{"varA": "content.varA"},
|
||||
{"user_agent": "headers.User-Agent"},
|
||||
],
|
||||
"validate": [
|
||||
{"eq": ["content.varB", 200]},
|
||||
{"lt": ["json.0.varC", 0]},
|
||||
],
|
||||
}
|
||||
],
|
||||
}
|
||||
self.assertEqual(
|
||||
compat.ensure_testcase_v3(testcase_content),
|
||||
{
|
||||
"config": {"name": "xxx", "base_url": "https://httpbin.org"},
|
||||
"teststeps": [
|
||||
{
|
||||
"name": "get with params",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"url": "/get",
|
||||
"params": {"foo1": "bar1", "foo2": "bar2"},
|
||||
"headers": {"User-Agent": "HttpRunner/3.0"},
|
||||
},
|
||||
"extract": {
|
||||
"varA": "body.varA",
|
||||
"user_agent": 'headers."User-Agent"',
|
||||
},
|
||||
"validate": [
|
||||
{"eq": ["body.varB", 200]},
|
||||
{"lt": ["body[0].varC", 0]},
|
||||
],
|
||||
}
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
def test_ensure_cli_args(self):
|
||||
args1 = ["/path/to/testcase.yml", "--failfast"]
|
||||
self.assertEqual(compat.ensure_cli_args(args1), ["/path/to/testcase.yml"])
|
||||
|
||||
args2 = ["/path/to/testcase.yml", "--save-tests"]
|
||||
self.assertEqual(compat.ensure_cli_args(args2), ["/path/to/testcase.yml"])
|
||||
|
||||
args3 = ["/path/to/testcase.yml", "--report-file", "report.html"]
|
||||
self.assertEqual(
|
||||
compat.ensure_cli_args(args3),
|
||||
["/path/to/testcase.yml", "--html", "report.html", "--self-contained-html"],
|
||||
)
|
||||
|
||||
args4 = [
|
||||
"/path/to/testcase.yml",
|
||||
"--failfast",
|
||||
"--save-tests",
|
||||
"--report-file",
|
||||
"report.html",
|
||||
]
|
||||
self.assertEqual(
|
||||
compat.ensure_cli_args(args4),
|
||||
["/path/to/testcase.yml", "--html", "report.html", "--self-contained-html"],
|
||||
)
|
||||
0
tests/ext/__init__.py
Normal file
0
tests/ext/__init__.py
Normal file
0
tests/ext/har2case/__init__.py
Normal file
0
tests/ext/har2case/__init__.py
Normal file
166
tests/ext/har2case/core_test.py
Normal file
166
tests/ext/har2case/core_test.py
Normal file
@@ -0,0 +1,166 @@
|
||||
import os
|
||||
|
||||
from httprunner.ext.har2case.core import HarParser
|
||||
from httprunner.ext.har2case.utils import load_har_log_entries
|
||||
from tests.ext.har2case.utils_test import TestHar2CaseUtils
|
||||
|
||||
|
||||
class TestHar(TestHar2CaseUtils):
|
||||
def setUp(self):
|
||||
self.har_path = os.path.join(os.path.dirname(__file__), "data", "demo.har")
|
||||
self.har_parser = HarParser(self.har_path)
|
||||
|
||||
def test_prepare_teststep(self):
|
||||
log_entries = load_har_log_entries(self.har_path)
|
||||
teststep_dict = self.har_parser._prepare_teststep(log_entries[0])
|
||||
self.assertIn("name", teststep_dict)
|
||||
self.assertIn("request", teststep_dict)
|
||||
self.assertIn("validate", teststep_dict)
|
||||
|
||||
validators_mapping = {
|
||||
validator["eq"][0]: validator["eq"][1]
|
||||
for validator in teststep_dict["validate"]
|
||||
}
|
||||
self.assertEqual(validators_mapping["status_code"], 200)
|
||||
self.assertEqual(validators_mapping["body.IsSuccess"], True)
|
||||
self.assertEqual(validators_mapping["body.Code"], 200)
|
||||
self.assertEqual(validators_mapping["body.Message"], None)
|
||||
|
||||
def test_prepare_teststeps(self):
|
||||
teststeps = self.har_parser._prepare_teststeps()
|
||||
self.assertIsInstance(teststeps, list)
|
||||
self.assertIn("name", teststeps[0])
|
||||
self.assertIn("request", teststeps[0])
|
||||
self.assertIn("validate", teststeps[0])
|
||||
|
||||
def test_gen_testcase_yaml(self):
|
||||
yaml_file = os.path.join(os.path.dirname(__file__), "data", "demo.yaml")
|
||||
|
||||
self.har_parser.gen_testcase(file_type="YAML")
|
||||
self.assertTrue(os.path.isfile(yaml_file))
|
||||
os.remove(yaml_file)
|
||||
|
||||
def test_gen_testcase_json(self):
|
||||
json_file = os.path.join(os.path.dirname(__file__), "data", "demo.json")
|
||||
|
||||
self.har_parser.gen_testcase(file_type="JSON")
|
||||
self.assertTrue(os.path.isfile(json_file))
|
||||
os.remove(json_file)
|
||||
|
||||
def test_filter(self):
|
||||
filter_str = "httprunner"
|
||||
har_parser = HarParser(self.har_path, filter_str)
|
||||
teststeps = har_parser._prepare_teststeps()
|
||||
self.assertEqual(
|
||||
teststeps[0]["request"]["url"],
|
||||
"https://httprunner.top/api/v1/Account/Login",
|
||||
)
|
||||
|
||||
filter_str = "debugtalk"
|
||||
har_parser = HarParser(self.har_path, filter_str)
|
||||
teststeps = har_parser._prepare_teststeps()
|
||||
self.assertEqual(teststeps, [])
|
||||
|
||||
def test_exclude(self):
|
||||
exclude_str = "debugtalk"
|
||||
har_parser = HarParser(self.har_path, exclude_str=exclude_str)
|
||||
teststeps = har_parser._prepare_teststeps()
|
||||
self.assertEqual(
|
||||
teststeps[0]["request"]["url"],
|
||||
"https://httprunner.top/api/v1/Account/Login",
|
||||
)
|
||||
|
||||
exclude_str = "httprunner"
|
||||
har_parser = HarParser(self.har_path, exclude_str=exclude_str)
|
||||
teststeps = har_parser._prepare_teststeps()
|
||||
self.assertEqual(teststeps, [])
|
||||
|
||||
def test_exclude_multiple(self):
|
||||
exclude_str = "httprunner|v2"
|
||||
har_parser = HarParser(self.har_path, exclude_str=exclude_str)
|
||||
teststeps = har_parser._prepare_teststeps()
|
||||
self.assertEqual(teststeps, [])
|
||||
|
||||
exclude_str = "http2|v1"
|
||||
har_parser = HarParser(self.har_path, exclude_str=exclude_str)
|
||||
teststeps = har_parser._prepare_teststeps()
|
||||
self.assertEqual(teststeps, [])
|
||||
|
||||
def test_make_request_data_params(self):
|
||||
testcase_dict = {"name": "", "request": {}, "validate": []}
|
||||
entry_json = {
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"postData": {
|
||||
"mimeType": "application/x-www-form-urlencoded; charset=utf-8",
|
||||
"params": [{"name": "a", "value": 1}, {"name": "b", "value": "2"}],
|
||||
},
|
||||
}
|
||||
}
|
||||
self.har_parser._make_request_data(testcase_dict, entry_json)
|
||||
self.assertEqual(testcase_dict["request"]["data"]["a"], 1)
|
||||
self.assertEqual(testcase_dict["request"]["data"]["b"], "2")
|
||||
|
||||
def test_make_request_data_json(self):
|
||||
testcase_dict = {"name": "", "request": {}, "validate": []}
|
||||
entry_json = {
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"postData": {
|
||||
"mimeType": "application/json; charset=utf-8",
|
||||
"text": '{"a":"1","b":"2"}',
|
||||
},
|
||||
}
|
||||
}
|
||||
self.har_parser._make_request_data(testcase_dict, entry_json)
|
||||
self.assertEqual(testcase_dict["request"]["json"], {"a": "1", "b": "2"})
|
||||
|
||||
def test_make_request_data_text_empty(self):
|
||||
testcase_dict = {"name": "", "request": {}, "validate": []}
|
||||
entry_json = {
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"postData": {"mimeType": "application/json; charset=utf-8", "text": ""},
|
||||
}
|
||||
}
|
||||
self.har_parser._make_request_data(testcase_dict, entry_json)
|
||||
self.assertEqual(testcase_dict["request"]["data"], "")
|
||||
|
||||
def test_make_validate(self):
|
||||
testcase_dict = {"name": "", "request": {}, "validate": []}
|
||||
entry_json = {
|
||||
"request": {},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": [
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "application/json; charset=utf-8",
|
||||
},
|
||||
],
|
||||
"content": {
|
||||
"size": 71,
|
||||
"mimeType": "application/json; charset=utf-8",
|
||||
# raw response content text is application/jose type
|
||||
"text": "ZXlKaGJHY2lPaUpTVTBFeFh6VWlMQ0psYm1NaU9pSkJNVEk0UTBKRExV",
|
||||
"encoding": "base64",
|
||||
},
|
||||
},
|
||||
}
|
||||
self.har_parser._make_validate(testcase_dict, entry_json)
|
||||
self.assertEqual(testcase_dict["validate"][0], {"eq": ["status_code", 200]})
|
||||
self.assertEqual(
|
||||
testcase_dict["validate"][1],
|
||||
{"eq": ["headers.Content-Type", "application/json; charset=utf-8"]},
|
||||
)
|
||||
|
||||
def test_make_testcase(self):
|
||||
har_path = os.path.join(
|
||||
os.path.dirname(__file__), "data", "demo-quickstart.har"
|
||||
)
|
||||
har_parser = HarParser(har_path)
|
||||
testcase = har_parser._make_testcase()
|
||||
self.assertIsInstance(testcase, dict)
|
||||
self.assertIn("config", testcase)
|
||||
self.assertIn("teststeps", testcase)
|
||||
self.assertEqual(len(testcase["teststeps"]), 2)
|
||||
223
tests/ext/har2case/data/demo-quickstart.har
Normal file
223
tests/ext/har2case/data/demo-quickstart.har
Normal file
@@ -0,0 +1,223 @@
|
||||
{
|
||||
"log": {
|
||||
"version": "1.2",
|
||||
"creator": {
|
||||
"name": "Charles Proxy",
|
||||
"version": "4.2.1"
|
||||
},
|
||||
"entries": [
|
||||
{
|
||||
"startedDateTime": "2018-02-19T17:30:00.904+08:00",
|
||||
"time": 3,
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "http://127.0.0.1:5000/api/get-token",
|
||||
"httpVersion": "HTTP/1.1",
|
||||
"cookies": [],
|
||||
"headers": [
|
||||
{
|
||||
"name": "Host",
|
||||
"value": "127.0.0.1:5000"
|
||||
},
|
||||
{
|
||||
"name": "User-Agent",
|
||||
"value": "python-requests/2.18.4"
|
||||
},
|
||||
{
|
||||
"name": "Accept-Encoding",
|
||||
"value": "gzip, deflate"
|
||||
},
|
||||
{
|
||||
"name": "Accept",
|
||||
"value": "*/*"
|
||||
},
|
||||
{
|
||||
"name": "Connection",
|
||||
"value": "keep-alive"
|
||||
},
|
||||
{
|
||||
"name": "device_sn",
|
||||
"value": "FwgRiO7CNA50DSU"
|
||||
},
|
||||
{
|
||||
"name": "user_agent",
|
||||
"value": "iOS/10.3"
|
||||
},
|
||||
{
|
||||
"name": "os_platform",
|
||||
"value": "ios"
|
||||
},
|
||||
{
|
||||
"name": "app_version",
|
||||
"value": "2.8.6"
|
||||
},
|
||||
{
|
||||
"name": "Content-Length",
|
||||
"value": "52"
|
||||
},
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "application/json"
|
||||
}
|
||||
],
|
||||
"queryString": [],
|
||||
"postData": {
|
||||
"mimeType": "application/json",
|
||||
"text": "{\"sign\": \"958a05393efef0ac7c0fb80a7eac45e24fd40c27\"}"
|
||||
},
|
||||
"headersSize": 299,
|
||||
"bodySize": 52
|
||||
},
|
||||
"response": {
|
||||
"_charlesStatus": "COMPLETE",
|
||||
"status": 200,
|
||||
"statusText": "OK",
|
||||
"httpVersion": "HTTP/1.0",
|
||||
"cookies": [],
|
||||
"headers": [
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"name": "Content-Length",
|
||||
"value": "46"
|
||||
},
|
||||
{
|
||||
"name": "Server",
|
||||
"value": "Werkzeug/0.14.1 Python/3.6.4"
|
||||
},
|
||||
{
|
||||
"name": "Date",
|
||||
"value": "Mon, 19 Feb 2018 09:30:00 GMT"
|
||||
},
|
||||
{
|
||||
"name": "Proxy-Connection",
|
||||
"value": "Close"
|
||||
}
|
||||
],
|
||||
"content": {
|
||||
"size": 46,
|
||||
"mimeType": "application/json",
|
||||
"text": "eyJzdWNjZXNzIjogdHJ1ZSwgInRva2VuIjogImJhTkxYMXpoRllQMTFTZWIifQ\u003d\u003d",
|
||||
"encoding": "base64"
|
||||
},
|
||||
"headersSize": 175,
|
||||
"bodySize": 46
|
||||
},
|
||||
"serverIPAddress": "127.0.0.1",
|
||||
"cache": {},
|
||||
"timings": {
|
||||
"dns": 1,
|
||||
"connect": 0,
|
||||
"ssl": -1,
|
||||
"send": 0,
|
||||
"wait": 1,
|
||||
"receive": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"startedDateTime": "2018-02-19T17:30:00.911+08:00",
|
||||
"time": 3,
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "http://127.0.0.1:5000/api/users/1000",
|
||||
"httpVersion": "HTTP/1.1",
|
||||
"cookies": [],
|
||||
"headers": [
|
||||
{
|
||||
"name": "Host",
|
||||
"value": "127.0.0.1:5000"
|
||||
},
|
||||
{
|
||||
"name": "User-Agent",
|
||||
"value": "python-requests/2.18.4"
|
||||
},
|
||||
{
|
||||
"name": "Accept-Encoding",
|
||||
"value": "gzip, deflate"
|
||||
},
|
||||
{
|
||||
"name": "Accept",
|
||||
"value": "*/*"
|
||||
},
|
||||
{
|
||||
"name": "Connection",
|
||||
"value": "keep-alive"
|
||||
},
|
||||
{
|
||||
"name": "device_sn",
|
||||
"value": "FwgRiO7CNA50DSU"
|
||||
},
|
||||
{
|
||||
"name": "token",
|
||||
"value": "baNLX1zhFYP11Seb"
|
||||
},
|
||||
{
|
||||
"name": "Content-Length",
|
||||
"value": "39"
|
||||
},
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "application/json"
|
||||
}
|
||||
],
|
||||
"queryString": [],
|
||||
"postData": {
|
||||
"mimeType": "application/json",
|
||||
"text": "{\"name\": \"user1\", \"password\": \"123456\"}"
|
||||
},
|
||||
"headersSize": 265,
|
||||
"bodySize": 39
|
||||
},
|
||||
"response": {
|
||||
"_charlesStatus": "COMPLETE",
|
||||
"status": 201,
|
||||
"statusText": "CREATED",
|
||||
"httpVersion": "HTTP/1.0",
|
||||
"cookies": [],
|
||||
"headers": [
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"name": "Content-Length",
|
||||
"value": "54"
|
||||
},
|
||||
{
|
||||
"name": "Server",
|
||||
"value": "Werkzeug/0.14.1 Python/3.6.4"
|
||||
},
|
||||
{
|
||||
"name": "Date",
|
||||
"value": "Mon, 19 Feb 2018 09:30:00 GMT"
|
||||
},
|
||||
{
|
||||
"name": "Proxy-Connection",
|
||||
"value": "Close"
|
||||
}
|
||||
],
|
||||
"content": {
|
||||
"size": 54,
|
||||
"mimeType": "application/json",
|
||||
"text": "eyJzdWNjZXNzIjogdHJ1ZSwgIm1zZyI6ICJ1c2VyIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5LiJ9",
|
||||
"encoding": "base64"
|
||||
},
|
||||
"headersSize": 77,
|
||||
"bodySize": 54
|
||||
},
|
||||
"serverIPAddress": "127.0.0.1",
|
||||
"cache": {},
|
||||
"timings": {
|
||||
"dns": 0,
|
||||
"connect": 0,
|
||||
"ssl": -1,
|
||||
"send": 0,
|
||||
"wait": 3,
|
||||
"receive": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
148
tests/ext/har2case/data/demo.har
Normal file
148
tests/ext/har2case/data/demo.har
Normal file
@@ -0,0 +1,148 @@
|
||||
{
|
||||
"log": {
|
||||
"version": "1.2",
|
||||
"creator": {
|
||||
"name": "Charles Proxy",
|
||||
"version": "4.2"
|
||||
},
|
||||
"entries": [
|
||||
{
|
||||
"startedDateTime": "2017-11-13T11:40:07.212+08:00",
|
||||
"time": 35,
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "https://httprunner.top/api/v1/Account/Login",
|
||||
"httpVersion": "HTTP/1.1",
|
||||
"cookies": [
|
||||
{
|
||||
"name": "lang",
|
||||
"value": "zh"
|
||||
}
|
||||
],
|
||||
"headers": [
|
||||
{
|
||||
"name": "Host",
|
||||
"value": "httprunner.top"
|
||||
},
|
||||
{
|
||||
"name": "Connection",
|
||||
"value": "keep-alive"
|
||||
},
|
||||
{
|
||||
"name": "Content-Length",
|
||||
"value": "50"
|
||||
},
|
||||
{
|
||||
"name": "Accept",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"name": "Origin",
|
||||
"value": "https://httprunner.top"
|
||||
},
|
||||
{
|
||||
"name": "User-Agent",
|
||||
"value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36"
|
||||
},
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"name": "Referer",
|
||||
"value": "https://httprunner.top/login"
|
||||
},
|
||||
{
|
||||
"name": "Accept-Encoding",
|
||||
"value": "gzip, deflate, br"
|
||||
},
|
||||
{
|
||||
"name": "Accept-Language",
|
||||
"value": "en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4"
|
||||
}
|
||||
],
|
||||
"queryString": [],
|
||||
"postData": {
|
||||
"mimeType": "application/json",
|
||||
"text": "{\"UserName\":\"test001\",\"Pwd\":\"123\",\"VerCode\":\"\"}"
|
||||
},
|
||||
"headersSize": 640,
|
||||
"bodySize": 50
|
||||
},
|
||||
"response": {
|
||||
"_charlesStatus": "COMPLETE",
|
||||
"status": 200,
|
||||
"statusText": "OK",
|
||||
"httpVersion": "HTTP/1.1",
|
||||
"cookies": [
|
||||
{
|
||||
"name": "lang",
|
||||
"value": "zh",
|
||||
"path": "/",
|
||||
"domain": ".httprunner.top",
|
||||
"expires": null,
|
||||
"httpOnly": false,
|
||||
"secure": false,
|
||||
"comment": null,
|
||||
"_maxAge": null
|
||||
}
|
||||
],
|
||||
"headers": [
|
||||
{
|
||||
"name": "Date",
|
||||
"value": "Mon, 13 Nov 2017 03:40:07 GMT"
|
||||
},
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "application/json; charset=utf-8"
|
||||
},
|
||||
{
|
||||
"name": "Content-Length",
|
||||
"value": "71"
|
||||
},
|
||||
{
|
||||
"name": "Cache-Control",
|
||||
"value": "no-cache"
|
||||
},
|
||||
{
|
||||
"name": "Pragma",
|
||||
"value": "no-cache"
|
||||
},
|
||||
{
|
||||
"name": "Expires",
|
||||
"value": "-1"
|
||||
},
|
||||
{
|
||||
"name": "Server",
|
||||
"value": "Microsoft-IIS/8.5"
|
||||
},
|
||||
{
|
||||
"name": "X-AspNet-Version",
|
||||
"value": "4.0.30319"
|
||||
}
|
||||
],
|
||||
"content": {
|
||||
"size": 71,
|
||||
"mimeType": "application/json; charset=utf-8",
|
||||
"text": "eyJJc1N1Y2Nlc3MiOnRydWUsIkNvZGUiOjIwMCwiTWVzc2FnZSI6bnVsbCwiVmFsdWUiOnsiQmxuUmVzdWx0Ijp0cnVlfX0=",
|
||||
"encoding": "base64"
|
||||
},
|
||||
"redirectURL": null,
|
||||
"headersSize": 0,
|
||||
"bodySize": 71
|
||||
},
|
||||
"serverIPAddress": "192.168.1.169",
|
||||
"cache": {},
|
||||
"timings": {
|
||||
"dns": -1,
|
||||
"connect": -1,
|
||||
"ssl": -1,
|
||||
"send": 6,
|
||||
"wait": 28,
|
||||
"receive": 1
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
}
|
||||
56
tests/ext/har2case/utils_test.py
Normal file
56
tests/ext/har2case/utils_test.py
Normal file
@@ -0,0 +1,56 @@
|
||||
import json
|
||||
import os
|
||||
import unittest
|
||||
|
||||
from httprunner.ext.har2case import utils
|
||||
|
||||
|
||||
class TestHar2CaseUtils(unittest.TestCase):
|
||||
@staticmethod
|
||||
def create_har_file(file_name, content):
|
||||
file_path = os.path.join(
|
||||
os.path.dirname(__file__), "data", "{}.har".format(file_name)
|
||||
)
|
||||
with open(file_path, "w") as f:
|
||||
f.write(json.dumps(content))
|
||||
|
||||
return file_path
|
||||
|
||||
def test_load_har_log_entries(self):
|
||||
har_path = os.path.join(os.path.dirname(__file__), "data", "demo.har")
|
||||
log_entries = utils.load_har_log_entries(har_path)
|
||||
self.assertIsInstance(log_entries, list)
|
||||
self.assertIn("request", log_entries[0])
|
||||
self.assertIn("response", log_entries[0])
|
||||
|
||||
def test_load_har_log_key_error(self):
|
||||
empty_json_file_path = TestHar2CaseUtils.create_har_file(
|
||||
file_name="empty_json", content={}
|
||||
)
|
||||
with self.assertRaises(SystemExit):
|
||||
utils.load_har_log_entries(empty_json_file_path)
|
||||
os.remove(empty_json_file_path)
|
||||
|
||||
def test_load_har_log_empty_error(self):
|
||||
empty_file_path = TestHar2CaseUtils.create_har_file(
|
||||
file_name="empty", content=""
|
||||
)
|
||||
with self.assertRaises(SystemExit):
|
||||
utils.load_har_log_entries(empty_file_path)
|
||||
os.remove(empty_file_path)
|
||||
|
||||
# def test_x_www_form_urlencoded(self):
|
||||
# origin_dict = {"a":1, "b": "2"}
|
||||
# self.assertIn("a=1", utils.x_www_form_urlencoded(origin_dict))
|
||||
# self.assertIn("b=2", utils.x_www_form_urlencoded(origin_dict))
|
||||
|
||||
def test_convert_list_to_dict(self):
|
||||
origin_list = [{"name": "v", "value": "1"}, {"name": "w", "value": "2"}]
|
||||
self.assertEqual(utils.convert_list_to_dict(origin_list), {"v": "1", "w": "2"})
|
||||
|
||||
def test_convert_x_www_form_urlencoded_to_dict(self):
|
||||
origin_str = "a=1&b=2"
|
||||
converted_dict = utils.convert_x_www_form_urlencoded_to_dict(origin_str)
|
||||
self.assertIsInstance(converted_dict, dict)
|
||||
self.assertEqual(converted_dict["a"], "1")
|
||||
self.assertEqual(converted_dict["b"], "2")
|
||||
101
tests/ext/make_test.py
Normal file
101
tests/ext/make_test.py
Normal file
@@ -0,0 +1,101 @@
|
||||
import unittest
|
||||
|
||||
from httprunner.ext.make import main_make, convert_testcase_path, make_files_cache_set
|
||||
|
||||
|
||||
class TestLoader(unittest.TestCase):
|
||||
def test_make_testcase(self):
|
||||
path = ["examples/postman_echo/request_methods/request_with_variables.yml"]
|
||||
testcase_python_list = main_make(path)
|
||||
self.assertEqual(
|
||||
testcase_python_list[0],
|
||||
"examples/postman_echo/request_methods/request_with_variables_test.py",
|
||||
)
|
||||
|
||||
def test_make_testcase_with_ref(self):
|
||||
path = [
|
||||
"examples/postman_echo/request_methods/request_with_testcase_reference.yml"
|
||||
]
|
||||
make_files_cache_set.clear()
|
||||
testcase_python_list = main_make(path)
|
||||
self.assertEqual(len(testcase_python_list), 2)
|
||||
self.assertIn(
|
||||
"examples/postman_echo/request_methods/request_with_testcase_reference_test.py",
|
||||
testcase_python_list,
|
||||
)
|
||||
|
||||
with open(
|
||||
"examples/postman_echo/request_methods/request_with_testcase_reference_test.py"
|
||||
) as f:
|
||||
content = f.read()
|
||||
self.assertIn(
|
||||
"""
|
||||
from examples.postman_echo.request_methods.request_with_functions_test import (
|
||||
TestCaseRequestWithFunctions as RequestWithFunctions,
|
||||
)
|
||||
""",
|
||||
content,
|
||||
)
|
||||
self.assertIn(
|
||||
'"testcase": RequestWithFunctions,', content,
|
||||
)
|
||||
|
||||
def test_make_testcase_folder(self):
|
||||
path = ["examples/postman_echo/request_methods/"]
|
||||
testcase_python_list = main_make(path)
|
||||
self.assertIn(
|
||||
"examples/postman_echo/request_methods/request_with_functions_test.py",
|
||||
testcase_python_list,
|
||||
)
|
||||
|
||||
def test_convert_testcase_path(self):
|
||||
self.assertEqual(
|
||||
convert_testcase_path("mubu.login.yml")[0], "mubu_login_test.py"
|
||||
)
|
||||
self.assertEqual(
|
||||
convert_testcase_path("/path/to/mubu.login.yml")[0],
|
||||
"/path/to/mubu_login_test.py",
|
||||
)
|
||||
self.assertEqual(
|
||||
convert_testcase_path("/path/to 2/mubu.login.yml")[0],
|
||||
"/path/to 2/mubu_login_test.py",
|
||||
)
|
||||
self.assertEqual(
|
||||
convert_testcase_path("/path/to 2/mubu.login.yml")[1], "MubuLogin"
|
||||
)
|
||||
self.assertEqual(
|
||||
convert_testcase_path("mubu login.yml")[0], "mubu_login_test.py"
|
||||
)
|
||||
self.assertEqual(
|
||||
convert_testcase_path("/path/to 2/mubu login.yml")[1], "MubuLogin"
|
||||
)
|
||||
self.assertEqual(
|
||||
convert_testcase_path("/path/to 2/mubu-login.yml")[0],
|
||||
"/path/to 2/mubu_login_test.py",
|
||||
)
|
||||
self.assertEqual(
|
||||
convert_testcase_path("/path/to 2/mubu-login.yml")[1], "MubuLogin"
|
||||
)
|
||||
self.assertEqual(
|
||||
convert_testcase_path("/path/to 2/幕布login.yml")[0],
|
||||
"/path/to 2/幕布login_test.py",
|
||||
)
|
||||
self.assertEqual(convert_testcase_path("/path/to/幕布login.yml")[1], "幕布Login")
|
||||
|
||||
def test_make_testsuite(self):
|
||||
path = ["examples/postman_echo/request_methods/demo_testsuite.yml"]
|
||||
make_files_cache_set.clear()
|
||||
testcase_python_list = main_make(path)
|
||||
self.assertEqual(len(testcase_python_list), 3)
|
||||
self.assertIn(
|
||||
"examples/postman_echo/request_methods/demo_testsuite_yml/request_with_functions_test.py",
|
||||
testcase_python_list,
|
||||
)
|
||||
self.assertIn(
|
||||
"examples/postman_echo/request_methods/demo_testsuite_yml/request_with_testcase_reference_test.py",
|
||||
testcase_python_list,
|
||||
)
|
||||
self.assertIn(
|
||||
"examples/postman_echo/request_methods/request_with_functions_test.py",
|
||||
testcase_python_list,
|
||||
)
|
||||
25
tests/ext/scaffold_test.py
Normal file
25
tests/ext/scaffold_test.py
Normal file
@@ -0,0 +1,25 @@
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import unittest
|
||||
|
||||
from httprunner.ext.scaffold import create_scaffold
|
||||
|
||||
|
||||
class TestScaffold(unittest.TestCase):
|
||||
def test_create_scaffold(self):
|
||||
project_name = "projectABC"
|
||||
create_scaffold(project_name)
|
||||
self.assertTrue(os.path.isdir(os.path.join(project_name, "har")))
|
||||
self.assertTrue(os.path.isdir(os.path.join(project_name, "testcases")))
|
||||
self.assertTrue(os.path.isdir(os.path.join(project_name, "reports")))
|
||||
self.assertTrue(os.path.isfile(os.path.join(project_name, "debugtalk.py")))
|
||||
self.assertTrue(os.path.isfile(os.path.join(project_name, ".env")))
|
||||
|
||||
# run demo testcases
|
||||
try:
|
||||
subprocess.check_call(["hrun", project_name])
|
||||
except subprocess.SubprocessError:
|
||||
raise
|
||||
finally:
|
||||
shutil.rmtree(project_name)
|
||||
123
tests/loader_test.py
Normal file
123
tests/loader_test.py
Normal file
@@ -0,0 +1,123 @@
|
||||
import os
|
||||
import unittest
|
||||
|
||||
from httprunner import exceptions, loader
|
||||
|
||||
|
||||
class TestLoader(unittest.TestCase):
|
||||
def test_load_testcase_file(self):
|
||||
path = "examples/postman_echo/request_methods/request_with_variables.yml"
|
||||
testcase_obj = loader.load_testcase_file(path)
|
||||
self.assertEqual(
|
||||
testcase_obj.config.name, "request methods testcase with variables"
|
||||
)
|
||||
self.assertEqual(len(testcase_obj.teststeps), 3)
|
||||
|
||||
def test_load_json_file_file_format_error(self):
|
||||
json_tmp_file = "/tmp/tmp.json"
|
||||
# create empty file
|
||||
with open(json_tmp_file, "w") as f:
|
||||
f.write("")
|
||||
|
||||
with self.assertRaises(exceptions.FileFormatError):
|
||||
loader._load_json_file(json_tmp_file)
|
||||
|
||||
os.remove(json_tmp_file)
|
||||
|
||||
# create empty json file
|
||||
with open(json_tmp_file, "w") as f:
|
||||
f.write("{}")
|
||||
|
||||
loader._load_json_file(json_tmp_file)
|
||||
os.remove(json_tmp_file)
|
||||
|
||||
# create invalid format json file
|
||||
with open(json_tmp_file, "w") as f:
|
||||
f.write("abc")
|
||||
|
||||
with self.assertRaises(exceptions.FileFormatError):
|
||||
loader._load_json_file(json_tmp_file)
|
||||
|
||||
os.remove(json_tmp_file)
|
||||
|
||||
def test_load_testcases_bad_filepath(self):
|
||||
testcase_file_path = os.path.join(os.getcwd(), "tests/data/demo")
|
||||
with self.assertRaises(exceptions.FileNotFound):
|
||||
loader.load_testcase_file(testcase_file_path)
|
||||
|
||||
def test_load_csv_file_one_parameter(self):
|
||||
csv_file_path = os.path.join(os.getcwd(), "examples/httpbin/user_agent.csv")
|
||||
csv_content = loader.load_csv_file(csv_file_path)
|
||||
self.assertEqual(
|
||||
csv_content,
|
||||
[
|
||||
{"user_agent": "iOS/10.1"},
|
||||
{"user_agent": "iOS/10.2"},
|
||||
{"user_agent": "iOS/10.3"},
|
||||
],
|
||||
)
|
||||
|
||||
def test_load_csv_file_multiple_parameters(self):
|
||||
csv_file_path = os.path.join(os.getcwd(), "examples/httpbin/account.csv")
|
||||
csv_content = loader.load_csv_file(csv_file_path)
|
||||
self.assertEqual(
|
||||
csv_content,
|
||||
[
|
||||
{"username": "test1", "password": "111111"},
|
||||
{"username": "test2", "password": "222222"},
|
||||
{"username": "test3", "password": "333333"},
|
||||
],
|
||||
)
|
||||
|
||||
def test_load_folder_files(self):
|
||||
folder = os.path.join(os.getcwd(), "examples")
|
||||
file1 = os.path.join(os.getcwd(), "examples", "test_utils.py")
|
||||
file2 = os.path.join(os.getcwd(), "examples", "httpbin", "hooks.yml")
|
||||
|
||||
files = loader.load_folder_files(folder, recursive=False)
|
||||
self.assertEqual(files, [])
|
||||
|
||||
files = loader.load_folder_files(folder)
|
||||
self.assertIn(file2, files)
|
||||
self.assertNotIn(file1, files)
|
||||
|
||||
files = loader.load_folder_files("not_existed_foulder", recursive=False)
|
||||
self.assertEqual([], files)
|
||||
|
||||
files = loader.load_folder_files(file2, recursive=False)
|
||||
self.assertEqual([], files)
|
||||
|
||||
def test_load_custom_dot_env_file(self):
|
||||
dot_env_path = os.path.join(os.getcwd(), "examples", "httpbin", "test.env")
|
||||
env_variables_mapping = loader.load_dot_env_file(dot_env_path)
|
||||
self.assertIn("PROJECT_KEY", env_variables_mapping)
|
||||
self.assertEqual(env_variables_mapping["UserName"], "test")
|
||||
self.assertEqual(
|
||||
env_variables_mapping["content_type"], "application/json; charset=UTF-8"
|
||||
)
|
||||
|
||||
def test_load_env_path_not_exist(self):
|
||||
dot_env_path = os.path.join(os.getcwd(), "tests", "data",)
|
||||
env_variables_mapping = loader.load_dot_env_file(dot_env_path)
|
||||
self.assertEqual(env_variables_mapping, {})
|
||||
|
||||
def test_locate_file(self):
|
||||
with self.assertRaises(exceptions.FileNotFound):
|
||||
loader.locate_file(os.getcwd(), "debugtalk.py")
|
||||
|
||||
with self.assertRaises(exceptions.FileNotFound):
|
||||
loader.locate_file("", "debugtalk.py")
|
||||
|
||||
start_path = os.path.join(os.getcwd(), "examples", "httpbin")
|
||||
self.assertEqual(
|
||||
loader.locate_file(start_path, "debugtalk.py"),
|
||||
os.path.join(os.getcwd(), "examples/httpbin/debugtalk.py"),
|
||||
)
|
||||
self.assertEqual(
|
||||
loader.locate_file("examples/httpbin/", "debugtalk.py"),
|
||||
os.path.join(os.getcwd(), "examples", "httpbin", "debugtalk.py"),
|
||||
)
|
||||
self.assertEqual(
|
||||
loader.locate_file("examples/httpbin/", "debugtalk.py"),
|
||||
os.path.join(os.getcwd(), "examples/httpbin/debugtalk.py"),
|
||||
)
|
||||
439
tests/parser_test.py
Normal file
439
tests/parser_test.py
Normal file
@@ -0,0 +1,439 @@
|
||||
import time
|
||||
import unittest
|
||||
|
||||
from httprunner import parser
|
||||
from httprunner.exceptions import VariableNotFound, FunctionNotFound
|
||||
|
||||
|
||||
class TestParserBasic(unittest.TestCase):
|
||||
def test_parse_variables_mapping(self):
|
||||
variables = {"varA": "$varB", "varB": "$varC", "varC": "123", "a": 1, "b": 2}
|
||||
parsed_variables = parser.parse_variables_mapping(variables)
|
||||
print(parsed_variables)
|
||||
self.assertEqual(parsed_variables["varA"], "123")
|
||||
self.assertEqual(parsed_variables["varB"], "123")
|
||||
|
||||
def test_parse_variables_mapping_exception(self):
|
||||
variables = {"varA": "$varB", "varB": "$varC", "a": 1, "b": 2}
|
||||
with self.assertRaises(VariableNotFound):
|
||||
parser.parse_variables_mapping(variables)
|
||||
|
||||
def test_parse_string_value(self):
|
||||
self.assertEqual(parser.parse_string_value("123"), 123)
|
||||
self.assertEqual(parser.parse_string_value("12.3"), 12.3)
|
||||
self.assertEqual(parser.parse_string_value("a123"), "a123")
|
||||
self.assertEqual(parser.parse_string_value("$var"), "$var")
|
||||
self.assertEqual(parser.parse_string_value("${func}"), "${func}")
|
||||
|
||||
def test_extract_variables(self):
|
||||
self.assertEqual(parser.extract_variables("$var"), {"var"})
|
||||
self.assertEqual(parser.extract_variables("$var123"), {"var123"})
|
||||
self.assertEqual(parser.extract_variables("$var_name"), {"var_name"})
|
||||
self.assertEqual(parser.extract_variables("var"), set())
|
||||
self.assertEqual(parser.extract_variables("a$var"), {"var"})
|
||||
self.assertEqual(parser.extract_variables("$v ar"), {"v"})
|
||||
self.assertEqual(parser.extract_variables(" "), set())
|
||||
self.assertEqual(parser.extract_variables("$abc*"), {"abc"})
|
||||
self.assertEqual(parser.extract_variables("${func()}"), set())
|
||||
self.assertEqual(parser.extract_variables("${func(1,2)}"), set())
|
||||
self.assertEqual(
|
||||
parser.extract_variables("${gen_md5($TOKEN, $data, $random)}"),
|
||||
{"TOKEN", "data", "random"},
|
||||
)
|
||||
|
||||
def test_parse_function_params(self):
|
||||
self.assertEqual(parser.parse_function_params(""), {"args": [], "kwargs": {}})
|
||||
self.assertEqual(parser.parse_function_params("5"), {"args": [5], "kwargs": {}})
|
||||
self.assertEqual(
|
||||
parser.parse_function_params("1, 2"), {"args": [1, 2], "kwargs": {}}
|
||||
)
|
||||
self.assertEqual(
|
||||
parser.parse_function_params("a=1, b=2"),
|
||||
{"args": [], "kwargs": {"a": 1, "b": 2}},
|
||||
)
|
||||
self.assertEqual(
|
||||
parser.parse_function_params("a= 1, b =2"),
|
||||
{"args": [], "kwargs": {"a": 1, "b": 2}},
|
||||
)
|
||||
self.assertEqual(
|
||||
parser.parse_function_params("1, 2, a=3, b=4"),
|
||||
{"args": [1, 2], "kwargs": {"a": 3, "b": 4}},
|
||||
)
|
||||
self.assertEqual(
|
||||
parser.parse_function_params("$request, 123"),
|
||||
{"args": ["$request", 123], "kwargs": {}},
|
||||
)
|
||||
self.assertEqual(parser.parse_function_params(" "), {"args": [], "kwargs": {}})
|
||||
self.assertEqual(
|
||||
parser.parse_function_params("hello world, a=3, b=4"),
|
||||
{"args": ["hello world"], "kwargs": {"a": 3, "b": 4}},
|
||||
)
|
||||
self.assertEqual(
|
||||
parser.parse_function_params("$request, 12 3"),
|
||||
{"args": ["$request", "12 3"], "kwargs": {}},
|
||||
)
|
||||
|
||||
def test_extract_functions(self):
|
||||
self.assertEqual(parser.regex_findall_functions("${func()}"), [("func", "")])
|
||||
self.assertEqual(parser.regex_findall_functions("${func(5)}"), [("func", "5")])
|
||||
self.assertEqual(
|
||||
parser.regex_findall_functions("${func(a=1, b=2)}"), [("func", "a=1, b=2")]
|
||||
)
|
||||
self.assertEqual(
|
||||
parser.regex_findall_functions("${func(1, $b, c=$x, d=4)}"),
|
||||
[("func", "1, $b, c=$x, d=4")],
|
||||
)
|
||||
self.assertEqual(
|
||||
parser.regex_findall_functions("/api/1000?_t=${get_timestamp()}"),
|
||||
[("get_timestamp", "")],
|
||||
)
|
||||
self.assertEqual(
|
||||
parser.regex_findall_functions("/api/${add(1, 2)}"), [("add", "1, 2")]
|
||||
)
|
||||
self.assertEqual(
|
||||
parser.regex_findall_functions("/api/${add(1, 2)}?_t=${get_timestamp()}"),
|
||||
[("add", "1, 2"), ("get_timestamp", "")],
|
||||
)
|
||||
self.assertEqual(
|
||||
parser.regex_findall_functions("abc${func(1, 2, a=3, b=4)}def"),
|
||||
[("func", "1, 2, a=3, b=4")],
|
||||
)
|
||||
|
||||
def test_parse_data_string_with_variables(self):
|
||||
variables_mapping = {
|
||||
"var_1": "abc",
|
||||
"var_2": "def",
|
||||
"var_3": 123,
|
||||
"var_4": {"a": 1},
|
||||
"var_5": True,
|
||||
"var_6": None,
|
||||
}
|
||||
self.assertEqual(parser.parse_data("$var_1", variables_mapping), "abc")
|
||||
self.assertEqual(parser.parse_data("${var_1}", variables_mapping), "abc")
|
||||
self.assertEqual(parser.parse_data("var_1", variables_mapping), "var_1")
|
||||
self.assertEqual(parser.parse_data("$var_1#XYZ", variables_mapping), "abc#XYZ")
|
||||
self.assertEqual(
|
||||
parser.parse_data("${var_1}#XYZ", variables_mapping), "abc#XYZ"
|
||||
)
|
||||
self.assertEqual(
|
||||
parser.parse_data("/$var_1/$var_2/var3", variables_mapping), "/abc/def/var3"
|
||||
)
|
||||
self.assertEqual(parser.parse_data("$var_3", variables_mapping), 123)
|
||||
self.assertEqual(parser.parse_data("$var_4", variables_mapping), {"a": 1})
|
||||
self.assertEqual(parser.parse_data("$var_5", variables_mapping), True)
|
||||
self.assertEqual(parser.parse_data("abc$var_5", variables_mapping), "abcTrue")
|
||||
self.assertEqual(
|
||||
parser.parse_data("abc$var_4", variables_mapping), "abc{'a': 1}"
|
||||
)
|
||||
self.assertEqual(parser.parse_data("$var_6", variables_mapping), None)
|
||||
|
||||
with self.assertRaises(VariableNotFound):
|
||||
parser.parse_data("/api/$SECRET_KEY", variables_mapping)
|
||||
|
||||
self.assertEqual(
|
||||
parser.parse_data(["$var_1", "$var_2"], variables_mapping), ["abc", "def"]
|
||||
)
|
||||
self.assertEqual(
|
||||
parser.parse_data({"$var_1": "$var_2"}, variables_mapping), {"abc": "def"}
|
||||
)
|
||||
|
||||
# format: $var
|
||||
value = parser.parse_data("ABC$var_1", variables_mapping)
|
||||
self.assertEqual(value, "ABCabc")
|
||||
|
||||
value = parser.parse_data("ABC$var_1$var_3", variables_mapping)
|
||||
self.assertEqual(value, "ABCabc123")
|
||||
|
||||
value = parser.parse_data("ABC$var_1/$var_3", variables_mapping)
|
||||
self.assertEqual(value, "ABCabc/123")
|
||||
|
||||
value = parser.parse_data("ABC$var_1/", variables_mapping)
|
||||
self.assertEqual(value, "ABCabc/")
|
||||
|
||||
value = parser.parse_data("ABC$var_1$", variables_mapping)
|
||||
self.assertEqual(value, "ABCabc$")
|
||||
|
||||
value = parser.parse_data("ABC$var_1/123$var_1/456", variables_mapping)
|
||||
self.assertEqual(value, "ABCabc/123abc/456")
|
||||
|
||||
value = parser.parse_data("ABC$var_1/$var_2/$var_1", variables_mapping)
|
||||
self.assertEqual(value, "ABCabc/def/abc")
|
||||
|
||||
value = parser.parse_data("func1($var_1, $var_3)", variables_mapping)
|
||||
self.assertEqual(value, "func1(abc, 123)")
|
||||
|
||||
# format: ${var}
|
||||
value = parser.parse_data("ABC${var_1}", variables_mapping)
|
||||
self.assertEqual(value, "ABCabc")
|
||||
|
||||
value = parser.parse_data("ABC${var_1}${var_3}", variables_mapping)
|
||||
self.assertEqual(value, "ABCabc123")
|
||||
|
||||
value = parser.parse_data("ABC${var_1}/${var_3}", variables_mapping)
|
||||
self.assertEqual(value, "ABCabc/123")
|
||||
|
||||
value = parser.parse_data("ABC${var_1}/", variables_mapping)
|
||||
self.assertEqual(value, "ABCabc/")
|
||||
|
||||
value = parser.parse_data("ABC${var_1}123", variables_mapping)
|
||||
self.assertEqual(value, "ABCabc123")
|
||||
|
||||
value = parser.parse_data("ABC${var_1}/123${var_1}/456", variables_mapping)
|
||||
self.assertEqual(value, "ABCabc/123abc/456")
|
||||
|
||||
value = parser.parse_data("ABC${var_1}/${var_2}/${var_1}", variables_mapping)
|
||||
self.assertEqual(value, "ABCabc/def/abc")
|
||||
|
||||
value = parser.parse_data("func1(${var_1}, ${var_3})", variables_mapping)
|
||||
self.assertEqual(value, "func1(abc, 123)")
|
||||
|
||||
def test_parse_data_multiple_identical_variables(self):
|
||||
variables_mapping = {
|
||||
"var_1": "abc",
|
||||
"var_2": "def",
|
||||
}
|
||||
self.assertEqual(
|
||||
parser.parse_data("/$var_1/$var_2/$var_1", variables_mapping),
|
||||
"/abc/def/abc",
|
||||
)
|
||||
|
||||
variables_mapping = {"userid": 100, "data": 1498}
|
||||
content = "/users/$userid/training/$data?userId=$userid&data=$data"
|
||||
self.assertEqual(
|
||||
parser.parse_data(content, variables_mapping),
|
||||
"/users/100/training/1498?userId=100&data=1498",
|
||||
)
|
||||
|
||||
variables_mapping = {"user": 100, "userid": 1000, "data": 1498}
|
||||
content = "/users/$user/$userid/$data?userId=$userid&data=$data"
|
||||
self.assertEqual(
|
||||
parser.parse_data(content, variables_mapping),
|
||||
"/users/100/1000/1498?userId=1000&data=1498",
|
||||
)
|
||||
|
||||
def test_parse_data_string_with_functions(self):
|
||||
import random, string
|
||||
|
||||
functions_mapping = {
|
||||
"gen_random_string": lambda str_len: "".join(
|
||||
random.choice(string.ascii_letters + string.digits)
|
||||
for _ in range(str_len)
|
||||
)
|
||||
}
|
||||
result = parser.parse_data(
|
||||
"${gen_random_string(5)}", functions_mapping=functions_mapping
|
||||
)
|
||||
self.assertEqual(len(result), 5)
|
||||
|
||||
add_two_nums = lambda a, b=1: a + b
|
||||
functions_mapping["add_two_nums"] = add_two_nums
|
||||
self.assertEqual(
|
||||
parser.parse_data(
|
||||
"${add_two_nums(1)}", functions_mapping=functions_mapping
|
||||
),
|
||||
2,
|
||||
)
|
||||
self.assertEqual(
|
||||
parser.parse_data(
|
||||
"${add_two_nums(1, 2)}", functions_mapping=functions_mapping
|
||||
),
|
||||
3,
|
||||
)
|
||||
self.assertEqual(
|
||||
parser.parse_data(
|
||||
"/api/${add_two_nums(1, 2)}", functions_mapping=functions_mapping
|
||||
),
|
||||
"/api/3",
|
||||
)
|
||||
|
||||
with self.assertRaises(FunctionNotFound):
|
||||
parser.parse_data("/api/${gen_md5(abc)}")
|
||||
|
||||
variables_mapping = {
|
||||
"var_1": "abc",
|
||||
"var_2": "def",
|
||||
"var_3": 123,
|
||||
"var_4": {"a": 1},
|
||||
"var_5": True,
|
||||
"var_6": None,
|
||||
}
|
||||
functions_mapping = {"func1": lambda x, y: str(x) + str(y)}
|
||||
|
||||
value = parser.parse_data(
|
||||
"${func1($var_1, $var_3)}", variables_mapping, functions_mapping
|
||||
)
|
||||
self.assertEqual(value, "abc123")
|
||||
|
||||
value = parser.parse_data(
|
||||
"ABC${func1($var_1, $var_3)}DE", variables_mapping, functions_mapping
|
||||
)
|
||||
self.assertEqual(value, "ABCabc123DE")
|
||||
|
||||
value = parser.parse_data(
|
||||
"ABC${func1($var_1, $var_3)}$var_5", variables_mapping, functions_mapping
|
||||
)
|
||||
self.assertEqual(value, "ABCabc123True")
|
||||
|
||||
value = parser.parse_data(
|
||||
"ABC${func1($var_1, $var_3)}DE$var_4", variables_mapping, functions_mapping
|
||||
)
|
||||
self.assertEqual(value, "ABCabc123DE{'a': 1}")
|
||||
|
||||
value = parser.parse_data(
|
||||
"ABC$var_5${func1($var_1, $var_3)}", variables_mapping, functions_mapping
|
||||
)
|
||||
self.assertEqual(value, "ABCTrueabc123")
|
||||
|
||||
value = parser.parse_data(
|
||||
"ABC${ord(a)}DEF${len(abcd)}", variables_mapping, functions_mapping
|
||||
)
|
||||
self.assertEqual(value, "ABC97DEF4")
|
||||
|
||||
def test_parse_data_func_var_duplicate(self):
|
||||
variables_mapping = {
|
||||
"var_1": "abc",
|
||||
"var_2": "def",
|
||||
"var_3": 123,
|
||||
"var_4": {"a": 1},
|
||||
"var_5": True,
|
||||
"var_6": None,
|
||||
}
|
||||
functions_mapping = {"func1": lambda x, y: str(x) + str(y)}
|
||||
value = parser.parse_data(
|
||||
"ABC${func1($var_1, $var_3)}--${func1($var_1, $var_3)}",
|
||||
variables_mapping,
|
||||
functions_mapping,
|
||||
)
|
||||
self.assertEqual(value, "ABCabc123--abc123")
|
||||
|
||||
value = parser.parse_data(
|
||||
"ABC${func1($var_1, $var_3)}$var_1", variables_mapping, functions_mapping
|
||||
)
|
||||
self.assertEqual(value, "ABCabc123abc")
|
||||
|
||||
value = parser.parse_data(
|
||||
"ABC${func1($var_1, $var_3)}$var_1--${func1($var_1, $var_3)}$var_1",
|
||||
variables_mapping,
|
||||
functions_mapping,
|
||||
)
|
||||
self.assertEqual(value, "ABCabc123abc--abc123abc")
|
||||
|
||||
def test_parse_data_func_abnormal(self):
|
||||
variables_mapping = {
|
||||
"var_1": "abc",
|
||||
"var_2": "def",
|
||||
"var_3": 123,
|
||||
"var_4": {"a": 1},
|
||||
"var_5": True,
|
||||
"var_6": None,
|
||||
}
|
||||
functions_mapping = {"func1": lambda x, y: str(x) + str(y)}
|
||||
|
||||
# {
|
||||
value = parser.parse_data("ABC$var_1{", variables_mapping, functions_mapping)
|
||||
self.assertEqual(value, "ABCabc{")
|
||||
|
||||
value = parser.parse_data(
|
||||
"{ABC$var_1{}a}", variables_mapping, functions_mapping
|
||||
)
|
||||
self.assertEqual(value, "{ABCabc{}a}")
|
||||
|
||||
value = parser.parse_data(
|
||||
"AB{C$var_1{}a}", variables_mapping, functions_mapping
|
||||
)
|
||||
self.assertEqual(value, "AB{Cabc{}a}")
|
||||
|
||||
# }
|
||||
value = parser.parse_data("ABC$var_1}", variables_mapping, functions_mapping)
|
||||
self.assertEqual(value, "ABCabc}")
|
||||
|
||||
# $$
|
||||
value = parser.parse_data("ABC$$var_1{", variables_mapping, functions_mapping)
|
||||
self.assertEqual(value, "ABC$var_1{")
|
||||
|
||||
# $$$
|
||||
value = parser.parse_data("ABC$$$var_1{", variables_mapping, functions_mapping)
|
||||
self.assertEqual(value, "ABC$abc{")
|
||||
|
||||
# $$$$
|
||||
value = parser.parse_data("ABC$$$$var_1{", variables_mapping, functions_mapping)
|
||||
self.assertEqual(value, "ABC$$var_1{")
|
||||
|
||||
# ${
|
||||
value = parser.parse_data("ABC$var_1${", variables_mapping, functions_mapping)
|
||||
self.assertEqual(value, "ABCabc${")
|
||||
|
||||
value = parser.parse_data("ABC$var_1${a", variables_mapping, functions_mapping)
|
||||
self.assertEqual(value, "ABCabc${a")
|
||||
|
||||
# $}
|
||||
value = parser.parse_data("ABC$var_1$}a", variables_mapping, functions_mapping)
|
||||
self.assertEqual(value, "ABCabc$}a")
|
||||
|
||||
# }{
|
||||
value = parser.parse_data("ABC$var_1}{a", variables_mapping, functions_mapping)
|
||||
self.assertEqual(value, "ABCabc}{a")
|
||||
|
||||
# {}
|
||||
value = parser.parse_data("ABC$var_1{}a", variables_mapping, functions_mapping)
|
||||
self.assertEqual(value, "ABCabc{}a")
|
||||
|
||||
def test_parse_data_request(self):
|
||||
content = {
|
||||
"request": {
|
||||
"url": "/api/users/$uid",
|
||||
"method": "$method",
|
||||
"headers": {"token": "$token"},
|
||||
"data": {
|
||||
"null": None,
|
||||
"true": True,
|
||||
"false": False,
|
||||
"empty_str": "",
|
||||
"value": "abc${add_one(3)}def",
|
||||
},
|
||||
}
|
||||
}
|
||||
variables_mapping = {"uid": 1000, "method": "POST", "token": "abc123"}
|
||||
functions_mapping = {"add_one": lambda x: x + 1}
|
||||
result = parser.parse_data(content, variables_mapping, functions_mapping)
|
||||
self.assertEqual("/api/users/1000", result["request"]["url"])
|
||||
self.assertEqual("abc123", result["request"]["headers"]["token"])
|
||||
self.assertEqual("POST", result["request"]["method"])
|
||||
self.assertIsNone(result["request"]["data"]["null"])
|
||||
self.assertTrue(result["request"]["data"]["true"])
|
||||
self.assertFalse(result["request"]["data"]["false"])
|
||||
self.assertEqual("", result["request"]["data"]["empty_str"])
|
||||
self.assertEqual("abc4def", result["request"]["data"]["value"])
|
||||
|
||||
def test_parse_data_testcase(self):
|
||||
variables = {
|
||||
"uid": "1000",
|
||||
"random": "A2dEx",
|
||||
"authorization": "a83de0ff8d2e896dbd8efb81ba14e17d",
|
||||
"data": {"name": "user", "password": "123456"},
|
||||
}
|
||||
functions = {
|
||||
"add_two_nums": lambda a, b=1: a + b,
|
||||
"get_timestamp": lambda: int(time.time() * 1000),
|
||||
}
|
||||
testcase_template = {
|
||||
"url": "http://127.0.0.1:5000/api/users/$uid/${add_two_nums(1,2)}",
|
||||
"method": "POST",
|
||||
"headers": {
|
||||
"Content-Type": "application/json",
|
||||
"authorization": "$authorization",
|
||||
"random": "$random",
|
||||
"sum": "${add_two_nums(1, 2)}",
|
||||
},
|
||||
"body": "$data",
|
||||
}
|
||||
parsed_testcase = parser.parse_data(testcase_template, variables, functions)
|
||||
self.assertEqual(
|
||||
parsed_testcase["url"], "http://127.0.0.1:5000/api/users/1000/3"
|
||||
)
|
||||
self.assertEqual(
|
||||
parsed_testcase["headers"]["authorization"], variables["authorization"]
|
||||
)
|
||||
self.assertEqual(parsed_testcase["headers"]["random"], variables["random"])
|
||||
self.assertEqual(parsed_testcase["body"], variables["data"])
|
||||
self.assertEqual(parsed_testcase["headers"]["sum"], 3)
|
||||
28
tests/runner_test.py
Normal file
28
tests/runner_test.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import unittest
|
||||
|
||||
from httprunner.runner import HttpRunner
|
||||
|
||||
|
||||
class TestHttpRunner(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.runner = HttpRunner()
|
||||
|
||||
def test_run_testcase_by_path_request_only(self):
|
||||
self.runner.run_path(
|
||||
"examples/postman_echo/request_methods/request_with_functions.yml"
|
||||
)
|
||||
result = self.runner.get_summary()
|
||||
self.assertTrue(result.success)
|
||||
self.assertEqual(result.name, "request methods testcase with functions")
|
||||
self.assertEqual(result.step_datas[0].name, "get with params")
|
||||
self.assertEqual(len(result.step_datas), 3)
|
||||
|
||||
def test_run_testcase_by_path_ref_testcase(self):
|
||||
self.runner.run_path(
|
||||
"examples/postman_echo/request_methods/request_with_testcase_reference.yml"
|
||||
)
|
||||
result = self.runner.get_summary()
|
||||
self.assertTrue(result.success)
|
||||
self.assertEqual(result.name, "request methods testcase: reference testcase")
|
||||
self.assertEqual(result.step_datas[0].name, "request with functions")
|
||||
self.assertEqual(len(result.step_datas), 1)
|
||||
100
tests/utils_test.py
Normal file
100
tests/utils_test.py
Normal file
@@ -0,0 +1,100 @@
|
||||
import os
|
||||
import unittest
|
||||
|
||||
from httprunner import loader, utils
|
||||
|
||||
|
||||
class TestUtils(unittest.TestCase):
|
||||
def test_set_os_environ(self):
|
||||
self.assertNotIn("abc", os.environ)
|
||||
variables_mapping = {"abc": "123"}
|
||||
utils.set_os_environ(variables_mapping)
|
||||
self.assertIn("abc", os.environ)
|
||||
self.assertEqual(os.environ["abc"], "123")
|
||||
|
||||
def current_validators(self):
|
||||
from httprunner.builtin import comparators
|
||||
|
||||
functions_mapping = loader.load_module_functions(comparators)
|
||||
|
||||
functions_mapping["equals"](None, None)
|
||||
functions_mapping["equals"](1, 1)
|
||||
functions_mapping["equals"]("abc", "abc")
|
||||
with self.assertRaises(AssertionError):
|
||||
functions_mapping["equals"]("123", 123)
|
||||
|
||||
functions_mapping["less_than"](1, 2)
|
||||
functions_mapping["less_than_or_equals"](2, 2)
|
||||
|
||||
functions_mapping["greater_than"](2, 1)
|
||||
functions_mapping["greater_than_or_equals"](2, 2)
|
||||
|
||||
functions_mapping["not_equals"](123, "123")
|
||||
|
||||
functions_mapping["length_equals"]("123", 3)
|
||||
# Because the Numbers in a CSV file are by default treated as strings,
|
||||
# you need to convert them to Numbers, and we'll test that out here.
|
||||
functions_mapping["length_equals"]("123", "3")
|
||||
with self.assertRaises(AssertionError):
|
||||
functions_mapping["length_equals"]("123", "abc")
|
||||
functions_mapping["length_greater_than"]("123", 2)
|
||||
functions_mapping["length_greater_than_or_equals"]("123", 3)
|
||||
|
||||
functions_mapping["contains"]("123abc456", "3ab")
|
||||
functions_mapping["contains"](["1", "2"], "1")
|
||||
functions_mapping["contains"]({"a": 1, "b": 2}, "a")
|
||||
functions_mapping["contained_by"]("3ab", "123abc456")
|
||||
|
||||
functions_mapping["regex_match"]("123abc456", "^123\w+456$")
|
||||
with self.assertRaises(AssertionError):
|
||||
functions_mapping["regex_match"]("123abc456", "^12b.*456$")
|
||||
|
||||
functions_mapping["startswith"]("abc123", "ab")
|
||||
functions_mapping["startswith"]("123abc", 12)
|
||||
functions_mapping["startswith"](12345, 123)
|
||||
|
||||
functions_mapping["endswith"]("abc123", 23)
|
||||
functions_mapping["endswith"]("123abc", "abc")
|
||||
functions_mapping["endswith"](12345, 45)
|
||||
|
||||
functions_mapping["type_match"](580509390, int)
|
||||
functions_mapping["type_match"](580509390, "int")
|
||||
functions_mapping["type_match"]([], list)
|
||||
functions_mapping["type_match"]([], "list")
|
||||
functions_mapping["type_match"]([1], "list")
|
||||
functions_mapping["type_match"]({}, "dict")
|
||||
functions_mapping["type_match"]({"a": 1}, "dict")
|
||||
|
||||
def test_lower_dict_keys(self):
|
||||
request_dict = {
|
||||
"url": "http://127.0.0.1:5000",
|
||||
"METHOD": "POST",
|
||||
"Headers": {"Accept": "application/json", "User-Agent": "ios/9.3"},
|
||||
}
|
||||
new_request_dict = utils.lower_dict_keys(request_dict)
|
||||
self.assertIn("method", new_request_dict)
|
||||
self.assertIn("headers", new_request_dict)
|
||||
self.assertIn("Accept", new_request_dict["headers"])
|
||||
self.assertIn("User-Agent", new_request_dict["headers"])
|
||||
|
||||
request_dict = "$default_request"
|
||||
new_request_dict = utils.lower_dict_keys(request_dict)
|
||||
self.assertEqual("$default_request", request_dict)
|
||||
|
||||
request_dict = None
|
||||
new_request_dict = utils.lower_dict_keys(request_dict)
|
||||
self.assertEqual(None, request_dict)
|
||||
|
||||
def test_print_info(self):
|
||||
info_mapping = {"a": 1, "t": (1, 2), "b": {"b1": 123}, "c": None, "d": [4, 5]}
|
||||
utils.print_info(info_mapping)
|
||||
|
||||
def test_sort_dict_by_custom_order(self):
|
||||
self.assertEqual(
|
||||
list(
|
||||
utils.sort_dict_by_custom_order(
|
||||
{"C": 3, "D": 2, "A": 1, "B": 8}, ["A", "D"]
|
||||
).keys()
|
||||
),
|
||||
["A", "D", "C", "B"],
|
||||
)
|
||||
Reference in New Issue
Block a user