mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-12 02:21:29 +08:00
change: remove unittests with flask mock server
This commit is contained in:
@@ -113,7 +113,7 @@ class RequestData(BaseModel):
|
||||
class ResponseData(BaseModel):
|
||||
status_code: int
|
||||
cookies: Dict
|
||||
encoding: Text
|
||||
encoding: Union[Text, None] = None
|
||||
headers: Dict
|
||||
content_type: Text
|
||||
body: Union[Text, bytes, Dict]
|
||||
|
||||
49
poetry.lock
generated
49
poetry.lock
generated
@@ -151,20 +151,6 @@ optional = false
|
||||
python-versions = "*"
|
||||
version = "1.0.5"
|
||||
|
||||
[[package]]
|
||||
category = "dev"
|
||||
description = "A microframework based on Werkzeug, Jinja2 and good intentions"
|
||||
name = "flask"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
version = "0.12.4"
|
||||
|
||||
[package.dependencies]
|
||||
Jinja2 = ">=2.4"
|
||||
Werkzeug = ">=0.7"
|
||||
click = ">=2.0"
|
||||
itsdangerous = ">=0.21"
|
||||
|
||||
[[package]]
|
||||
category = "dev"
|
||||
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
|
||||
@@ -218,14 +204,6 @@ zipp = ">=0.5"
|
||||
docs = ["sphinx", "rst.linker"]
|
||||
testing = ["packaging", "importlib-resources"]
|
||||
|
||||
[[package]]
|
||||
category = "dev"
|
||||
description = "Various helpers to pass data to untrusted environments and back."
|
||||
name = "itsdangerous"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
version = "1.1.0"
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "A very fast and expressive template engine."
|
||||
@@ -512,19 +490,6 @@ optional = false
|
||||
python-versions = ">=3.6"
|
||||
version = "8.0.2"
|
||||
|
||||
[[package]]
|
||||
category = "dev"
|
||||
description = "The comprehensive WSGI web application library."
|
||||
name = "werkzeug"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
version = "0.16.0"
|
||||
|
||||
[package.extras]
|
||||
dev = ["pytest", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinx-issues"]
|
||||
termcolor = ["termcolor"]
|
||||
watchdog = ["watchdog"]
|
||||
|
||||
[[package]]
|
||||
category = "main"
|
||||
description = "A small Python utility to set file creation time on Windows"
|
||||
@@ -551,7 +516,7 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
|
||||
testing = ["jaraco.itertools", "func-timeout"]
|
||||
|
||||
[metadata]
|
||||
content-hash = "e0fe5a044fc942eba590b0a3778679bc09bbec8703f1abdda58e2f76bc99ee49"
|
||||
content-hash = "be53fb0cd423bac9dda129a958a58026009a99a455081333d7af51c22a4df8cf"
|
||||
python-versions = "^3.6"
|
||||
|
||||
[metadata.files]
|
||||
@@ -640,10 +605,6 @@ filetype = [
|
||||
{file = "filetype-1.0.5-py2.py3-none-any.whl", hash = "sha256:4967124d982a71700d94a08c49c4926423500e79382a92070f5ab248d44fe461"},
|
||||
{file = "filetype-1.0.5.tar.gz", hash = "sha256:17a3b885f19034da29640b083d767e0f13c2dcb5dcc267945c8b6e5a5a9013c7"},
|
||||
]
|
||||
flask = [
|
||||
{file = "Flask-0.12.4-py2.py3-none-any.whl", hash = "sha256:6c02dbaa5a9ef790d8219bdced392e2d549c10cd5a5ba4b6aa65126b2271af29"},
|
||||
{file = "Flask-0.12.4.tar.gz", hash = "sha256:2ea22336f6d388b4b242bc3abf8a01244a8aa3e236e7407469ef78c16ba355dd"},
|
||||
]
|
||||
h11 = [
|
||||
{file = "h11-0.9.0-py2.py3-none-any.whl", hash = "sha256:4bc6d6a1238b7615b266ada57e0618568066f57dd6fa967d1290ec9309b2f2f1"},
|
||||
{file = "h11-0.9.0.tar.gz", hash = "sha256:33d4bca7be0fa039f4e84d50ab00531047e53d6ee8ffbc83501ea602c169cae1"},
|
||||
@@ -688,10 +649,6 @@ importlib-metadata = [
|
||||
{file = "importlib_metadata-1.6.0-py2.py3-none-any.whl", hash = "sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f"},
|
||||
{file = "importlib_metadata-1.6.0.tar.gz", hash = "sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e"},
|
||||
]
|
||||
itsdangerous = [
|
||||
{file = "itsdangerous-1.1.0-py2.py3-none-any.whl", hash = "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"},
|
||||
{file = "itsdangerous-1.1.0.tar.gz", hash = "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19"},
|
||||
]
|
||||
jinja2 = [
|
||||
{file = "Jinja2-2.10.3-py2.py3-none-any.whl", hash = "sha256:74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f"},
|
||||
{file = "Jinja2-2.10.3.tar.gz", hash = "sha256:9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de"},
|
||||
@@ -892,10 +849,6 @@ websockets = [
|
||||
{file = "websockets-8.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:049e694abe33f8a1d99969fee7bfc0ae6761f7fd5f297c58ea933b27dd6805f2"},
|
||||
{file = "websockets-8.0.2.tar.gz", hash = "sha256:882a7266fa867a2ebb2c0baaa0f9159cabf131cf18c1b4270d79ad42f9208dc5"},
|
||||
]
|
||||
werkzeug = [
|
||||
{file = "Werkzeug-0.16.0-py2.py3-none-any.whl", hash = "sha256:e5f4a1f98b52b18a93da705a7458e55afb26f32bff83ff5d19189f92462d65c4"},
|
||||
{file = "Werkzeug-0.16.0.tar.gz", hash = "sha256:7280924747b5733b246fe23972186c6b348f9ae29724135a6dfc1e53cea433e7"},
|
||||
]
|
||||
win32-setctime = [
|
||||
{file = "win32_setctime-1.0.1-py3-none-any.whl", hash = "sha256:568fd636c68350bcc54755213fe01966fe0a6c90b386c0776425944a0382abef"},
|
||||
{file = "win32_setctime-1.0.1.tar.gz", hash = "sha256:b47e5023ec7f0b4962950902b15bc56464a380d869f59d27dbf9ab423b23e8f9"},
|
||||
|
||||
@@ -41,7 +41,6 @@ black = "^19.10b0"
|
||||
pytest = "^5.4.2"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
flask = "<1.0.0"
|
||||
coverage = "^4.5.4"
|
||||
uvicorn = "^0.11.3"
|
||||
fastapi = "^0.49.0"
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
UserName=debugtalk
|
||||
Password=123456
|
||||
PROJECT_KEY=ABCDEFGH
|
||||
@@ -1,18 +0,0 @@
|
||||
name: create user
|
||||
variables:
|
||||
user_name: user0
|
||||
user_password: "000000"
|
||||
uid: 9000
|
||||
token: XXX
|
||||
request:
|
||||
url: /api/users/$uid
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: "application/json"
|
||||
device_sn: $device_sn
|
||||
token: $token
|
||||
json:
|
||||
name: $user_name
|
||||
password: $user_password
|
||||
validate:
|
||||
- eq: ["status_code", 201]
|
||||
@@ -1,12 +0,0 @@
|
||||
variables:
|
||||
uid: 9000
|
||||
token: XXX
|
||||
request:
|
||||
url: /api/users/$uid
|
||||
method: DELETE
|
||||
headers:
|
||||
Content-Type: "application/json"
|
||||
device_sn: $device_sn
|
||||
token: $token
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
@@ -1,16 +0,0 @@
|
||||
variables:
|
||||
n_secs: 1
|
||||
request:
|
||||
url: /headers
|
||||
headers:
|
||||
Content-Type: "application/json"
|
||||
device_sn: $device_sn
|
||||
method: GET
|
||||
setup_hooks:
|
||||
- ${setup_hook_add_kwargs($request)}
|
||||
- ${setup_hook_remove_kwargs($request)}
|
||||
teardown_hooks:
|
||||
- ${teardown_hook_sleep_N_secs($response, $n_secs)}
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
- contained_by: [content.headers.Host, "${get_httpbin_server()}"]
|
||||
@@ -1,22 +0,0 @@
|
||||
name: get token
|
||||
variables:
|
||||
user_agent: XXX
|
||||
device_sn: API_XXX
|
||||
os_platform: XXX
|
||||
app_version: XXX
|
||||
request:
|
||||
url: /api/get-token
|
||||
method: POST
|
||||
headers:
|
||||
user_agent: $user_agent
|
||||
device_sn: $device_sn
|
||||
os_platform: $os_platform
|
||||
app_version: $app_version
|
||||
Content-Type: "application/json"
|
||||
device_sn: $device_sn
|
||||
json:
|
||||
sign: ${get_sign($device_sn, $os_platform, $app_version)}
|
||||
validate:
|
||||
- eq: ["status_code", 0]
|
||||
- len_eq: ["content.token", 12]
|
||||
- contains: [{"a": 1, "b": 2}, "a"]
|
||||
@@ -1,12 +0,0 @@
|
||||
variables:
|
||||
uid: 9000
|
||||
token: XXX
|
||||
request:
|
||||
url: /api/users/$uid
|
||||
method: GET
|
||||
headers:
|
||||
Content-Type: "application/json"
|
||||
device_sn: $device_sn
|
||||
token: $token
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
@@ -1,11 +0,0 @@
|
||||
variables:
|
||||
token: XXX
|
||||
request:
|
||||
url: /api/users
|
||||
method: GET
|
||||
headers:
|
||||
Content-Type: "application/json"
|
||||
device_sn: $device_sn
|
||||
token: $token
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
@@ -1,12 +0,0 @@
|
||||
variables:
|
||||
token: XXX
|
||||
request:
|
||||
url: /api/reset-all
|
||||
method: GET
|
||||
headers:
|
||||
Content-Type: "application/json"
|
||||
device_sn: $device_sn
|
||||
token: $token
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
- eq: ["content.success", true]
|
||||
@@ -1,17 +0,0 @@
|
||||
variables:
|
||||
user_name: user0
|
||||
user_password: "000000"
|
||||
uid: 9000
|
||||
token: XXX
|
||||
request:
|
||||
url: /api/users/$uid
|
||||
method: PUT
|
||||
headers:
|
||||
Content-Type: "application/json"
|
||||
device_sn: $device_sn
|
||||
token: $token
|
||||
json:
|
||||
name: $user_name
|
||||
password: $user_password
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
@@ -1,236 +0,0 @@
|
||||
import hashlib
|
||||
import hmac
|
||||
import json
|
||||
from functools import wraps
|
||||
|
||||
from flask import Flask, make_response, request
|
||||
|
||||
from httprunner.builtin.functions import gen_random_string
|
||||
|
||||
try:
|
||||
from httpbin import app as httpbin_app
|
||||
HTTPBIN_HOST = "127.0.0.1"
|
||||
HTTPBIN_PORT = 3458
|
||||
HTTPBIN_SERVER = "http://{}:{}".format(HTTPBIN_HOST, HTTPBIN_PORT)
|
||||
except ImportError:
|
||||
httpbin_app = None
|
||||
HTTPBIN_HOST = "httpbin.org"
|
||||
HTTPBIN_PORT = 80
|
||||
HTTPBIN_SERVER = "http://{}:{}".format(HTTPBIN_HOST, HTTPBIN_PORT)
|
||||
|
||||
FLASK_APP_PORT = 5000
|
||||
SECRET_KEY = "DebugTalk"
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
""" storage all users' data
|
||||
data structure:
|
||||
users_dict = {
|
||||
'uid1': {
|
||||
'name': 'name1',
|
||||
'password': 'pwd1'
|
||||
},
|
||||
'uid2': {
|
||||
'name': 'name2',
|
||||
'password': 'pwd2'
|
||||
}
|
||||
}
|
||||
"""
|
||||
users_dict = {}
|
||||
|
||||
""" storage all token data
|
||||
data structure:
|
||||
token_dict = {
|
||||
'device_sn1': 'token1',
|
||||
'device_sn2': 'token1'
|
||||
}
|
||||
"""
|
||||
token_dict = {}
|
||||
|
||||
|
||||
def get_sign(*args):
|
||||
content = ''.join(args).encode('ascii')
|
||||
sign_key = SECRET_KEY.encode('ascii')
|
||||
sign = hmac.new(sign_key, content, hashlib.sha1).hexdigest()
|
||||
return sign
|
||||
|
||||
|
||||
def gen_md5(*args):
|
||||
return hashlib.md5("".join(args).encode('utf-8')).hexdigest()
|
||||
|
||||
|
||||
def validate_request(func):
|
||||
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
device_sn = request.headers.get('device_sn', "")
|
||||
token = request.headers.get('token', "")
|
||||
|
||||
if not device_sn or not token:
|
||||
result = {
|
||||
'success': False,
|
||||
'msg': "device_sn or token is null."
|
||||
}
|
||||
response = make_response(json.dumps(result), 401)
|
||||
response.headers["Content-Type"] = "application/json"
|
||||
return response
|
||||
|
||||
if token_dict[device_sn] != token:
|
||||
result = {
|
||||
'success': False,
|
||||
'msg': "Authorization failed!"
|
||||
}
|
||||
response = make_response(json.dumps(result), 403)
|
||||
response.headers["Content-Type"] = "application/json"
|
||||
return response
|
||||
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
return "Hello World!"
|
||||
|
||||
|
||||
@app.route('/api/get-token', methods=['POST'])
|
||||
def get_token():
|
||||
device_sn = request.headers.get('device_sn', "")
|
||||
os_platform = request.headers.get('os_platform', "")
|
||||
app_version = request.headers.get('app_version', "")
|
||||
data = request.get_json()
|
||||
sign = data.get('sign', "")
|
||||
|
||||
expected_sign = get_sign(device_sn, os_platform, app_version)
|
||||
if expected_sign != sign:
|
||||
result = {
|
||||
'success': False,
|
||||
'msg': "Authorization failed!"
|
||||
}
|
||||
response = make_response(json.dumps(result), 403)
|
||||
else:
|
||||
token = gen_random_string(16)
|
||||
token_dict[device_sn] = token
|
||||
|
||||
result = {
|
||||
'success': True,
|
||||
'token': token
|
||||
}
|
||||
response = make_response(json.dumps(result))
|
||||
|
||||
response.headers["Content-Type"] = "application/json"
|
||||
return response
|
||||
|
||||
|
||||
@app.route('/api/users')
|
||||
@validate_request
|
||||
def get_users():
|
||||
users_list = [user for uid, user in users_dict.items()]
|
||||
users = {
|
||||
'success': True,
|
||||
'count': len(users_list),
|
||||
'items': users_list
|
||||
}
|
||||
response = make_response(json.dumps(users))
|
||||
response.headers["Content-Type"] = "application/json"
|
||||
return response
|
||||
|
||||
|
||||
@app.route('/api/reset-all')
|
||||
@validate_request
|
||||
def clear_users():
|
||||
users_dict.clear()
|
||||
result = {
|
||||
'success': True
|
||||
}
|
||||
response = make_response(json.dumps(result))
|
||||
response.headers["Content-Type"] = "application/json"
|
||||
return response
|
||||
|
||||
|
||||
@app.route('/api/users/<int:uid>', methods=['POST'])
|
||||
@validate_request
|
||||
def create_user(uid):
|
||||
user = request.get_json()
|
||||
if uid not in users_dict:
|
||||
result = {
|
||||
'success': True,
|
||||
'msg': "user created successfully."
|
||||
}
|
||||
status_code = 201
|
||||
users_dict[uid] = user
|
||||
else:
|
||||
result = {
|
||||
'success': False,
|
||||
'msg': "user already existed."
|
||||
}
|
||||
status_code = 500
|
||||
|
||||
response = make_response(json.dumps(result), status_code)
|
||||
response.headers["Content-Type"] = "application/json"
|
||||
return response
|
||||
|
||||
|
||||
@app.route('/api/users/<int:uid>')
|
||||
@validate_request
|
||||
def get_user(uid):
|
||||
user = users_dict.get(uid, {})
|
||||
if user:
|
||||
result = {
|
||||
'success': True,
|
||||
'data': user
|
||||
}
|
||||
status_code = 200
|
||||
else:
|
||||
result = {
|
||||
'success': False,
|
||||
'data': user
|
||||
}
|
||||
status_code = 404
|
||||
|
||||
response = make_response(json.dumps(result), status_code)
|
||||
response.headers["Content-Type"] = "application/json"
|
||||
return response
|
||||
|
||||
|
||||
@app.route('/api/users/<int:uid>', methods=['PUT'])
|
||||
@validate_request
|
||||
def update_user(uid):
|
||||
user = users_dict.get(uid, {})
|
||||
if user:
|
||||
user = request.get_json()
|
||||
success = True
|
||||
status_code = 200
|
||||
users_dict[uid] = user
|
||||
else:
|
||||
success = False
|
||||
status_code = 404
|
||||
|
||||
result = {
|
||||
'success': success,
|
||||
'data': user
|
||||
}
|
||||
response = make_response(json.dumps(result), status_code)
|
||||
response.headers["Content-Type"] = "application/json"
|
||||
return response
|
||||
|
||||
|
||||
@app.route('/api/users/<int:uid>', methods=['DELETE'])
|
||||
@validate_request
|
||||
def delete_user(uid):
|
||||
user = users_dict.pop(uid, {})
|
||||
if user:
|
||||
success = True
|
||||
status_code = 200
|
||||
else:
|
||||
success = False
|
||||
status_code = 404
|
||||
|
||||
result = {
|
||||
'success': success,
|
||||
'data': user
|
||||
}
|
||||
response = make_response(json.dumps(result), status_code)
|
||||
response.headers["Content-Type"] = "application/json"
|
||||
return response
|
||||
@@ -1,75 +0,0 @@
|
||||
import multiprocessing
|
||||
import time
|
||||
import unittest
|
||||
|
||||
import requests
|
||||
|
||||
from tests.api_server import FLASK_APP_PORT, HTTPBIN_HOST, HTTPBIN_PORT
|
||||
from tests.api_server import app as flask_app
|
||||
from tests.api_server import gen_random_string, get_sign, httpbin_app
|
||||
|
||||
|
||||
def run_flask():
|
||||
flask_app.run(port=FLASK_APP_PORT)
|
||||
|
||||
|
||||
def run_httpbin():
|
||||
if httpbin_app:
|
||||
httpbin_app.run(host=HTTPBIN_HOST, port=HTTPBIN_PORT)
|
||||
|
||||
|
||||
class ApiServerUnittest(unittest.TestCase):
|
||||
""" Test case class that sets up an HTTP server which can be used within the tests
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.host = "http://127.0.0.1:5000"
|
||||
cls.flask_process = multiprocessing.Process(
|
||||
target=run_flask
|
||||
)
|
||||
cls.httpbin_process = multiprocessing.Process(
|
||||
target=run_httpbin
|
||||
)
|
||||
cls.flask_process.start()
|
||||
cls.httpbin_process.start()
|
||||
time.sleep(1)
|
||||
cls.api_client = requests.Session()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.flask_process.terminate()
|
||||
cls.httpbin_process.terminate()
|
||||
|
||||
def get_token(self, user_agent, device_sn, os_platform, app_version):
|
||||
url = "%s/api/get-token" % self.host
|
||||
headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': user_agent,
|
||||
'device_sn': device_sn,
|
||||
'os_platform': os_platform,
|
||||
'app_version': app_version
|
||||
}
|
||||
data = {
|
||||
'sign': get_sign(device_sn, os_platform, app_version)
|
||||
}
|
||||
|
||||
resp = self.api_client.post(url, json=data, headers=headers)
|
||||
resp_json = resp.json()
|
||||
self.assertTrue(resp_json["success"])
|
||||
self.assertIn("token", resp_json)
|
||||
self.assertEqual(len(resp_json["token"]), 16)
|
||||
return resp_json["token"]
|
||||
|
||||
def get_authenticated_headers(self):
|
||||
user_agent = 'iOS/10.3'
|
||||
device_sn = gen_random_string(15)
|
||||
os_platform = 'ios'
|
||||
app_version = '2.8.6'
|
||||
|
||||
token = self.get_token(user_agent, device_sn, os_platform, app_version)
|
||||
headers = {
|
||||
'device_sn': device_sn,
|
||||
'token': token
|
||||
}
|
||||
return headers
|
||||
@@ -1,4 +0,0 @@
|
||||
username,password
|
||||
test1,111111
|
||||
test2,222222
|
||||
test3,333333
|
||||
|
@@ -1,4 +0,0 @@
|
||||
app_version
|
||||
2.8.5
|
||||
2.8.6
|
||||
|
||||
|
@@ -1,13 +0,0 @@
|
||||
config:
|
||||
name: "bugfix testcases."
|
||||
base_url: http://127.0.0.1:5000
|
||||
|
||||
teststeps:
|
||||
-
|
||||
name: bugfix type_match #84
|
||||
request:
|
||||
url: http://127.0.0.1:5000/api/users/1000
|
||||
method: GET
|
||||
validate:
|
||||
- eq: [status_code, 401]
|
||||
- type_match: [status_code, int]
|
||||
@@ -1,14 +0,0 @@
|
||||
config:
|
||||
name: basic test with httpbin
|
||||
base_url: https://httpbin.org/
|
||||
verify: False
|
||||
|
||||
teststeps:
|
||||
-
|
||||
name: headers
|
||||
request:
|
||||
url: /headers
|
||||
method: GET
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
- eq: [content.headers.Host, "httpbin.org"]
|
||||
@@ -1,22 +0,0 @@
|
||||
config:
|
||||
name: "123t$var_a"
|
||||
variables:
|
||||
var_a: 1
|
||||
var_b: 2
|
||||
var_c: "${sum_two($var_a, $var_b)}"
|
||||
var_d: "${gen_random_string(5)}"
|
||||
var_e: $var_d
|
||||
PROJECT_KEY: ${ENV(PROJECT_KEY)}
|
||||
|
||||
teststeps:
|
||||
-
|
||||
name: testcase1-$var_a
|
||||
request:
|
||||
url: /api1
|
||||
method: GET
|
||||
headers:
|
||||
var_a: $var_a
|
||||
var_b: $var_b
|
||||
var_c: $var_c
|
||||
validate:
|
||||
- {"check": "status_code", "comparator": "eq", "expect": 200}
|
||||
@@ -1,135 +0,0 @@
|
||||
config:
|
||||
name: xxx
|
||||
|
||||
teststeps:
|
||||
-
|
||||
name: get token
|
||||
request:
|
||||
url: http://127.0.0.1:5000/api/get-token
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
user_agent: 'iOS/10.3'
|
||||
device_sn: 'HZfFBh6tU59EdXJ'
|
||||
os_platform: 'ios'
|
||||
app_version: '2.8.6'
|
||||
json:
|
||||
sign: 5188962c489d1a35effa99e9346dd5efd4fdabad
|
||||
variables:
|
||||
expect_status_code: 200
|
||||
token_len: 16
|
||||
extract:
|
||||
token: content.token
|
||||
validate:
|
||||
- {"check": "status_code", "comparator": "eq", "expect": 200}
|
||||
- eq: ["status_code", $expect_status_code]
|
||||
- {"check": "$token", "comparator": "len_eq", "expect": 16}
|
||||
- len_eq: ["$token", $token_len]
|
||||
- len_eq: ["content.token", 16]
|
||||
- {"check": "status_code", "comparator": "sum_status_code", "expect": 2}
|
||||
- sum_status_code: ["status_code", 2]
|
||||
|
||||
-
|
||||
name: create user which does not exist
|
||||
request:
|
||||
url: http://127.0.0.1:5000/api/users/1000
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
device_sn: 'HZfFBh6tU59EdXJ'
|
||||
token: $token
|
||||
json:
|
||||
name: "user1"
|
||||
password: "123456"
|
||||
extract:
|
||||
success: content.success
|
||||
validate:
|
||||
- eq: ["status_code", 201]
|
||||
- sum_status_code: ["status_code", 3]
|
||||
- eq: ["$success", True]
|
||||
- eq: ["abc$success", "abcTrue"]
|
||||
- {"check": "status_code", "comparator": "eq", "expect": 201}
|
||||
- {"check": "content.success", "comparator": "eq", "expect": true}
|
||||
|
||||
-
|
||||
name: create user which existed
|
||||
times: 2
|
||||
request:
|
||||
url: http://127.0.0.1:5000/api/users/1000
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
device_sn: 'HZfFBh6tU59EdXJ'
|
||||
token: $token
|
||||
json:
|
||||
name: "user1"
|
||||
password: "123456"
|
||||
validate:
|
||||
- "eq": ["status_code", 500]
|
||||
- sum_status_code: ["status_code", 5]
|
||||
- "eq": ["content.success", false]
|
||||
- {"check": "status_code", "comparator": "eq", "expect": 500}
|
||||
- {"check": "content.success", "comparator": "eq", "expect": false}
|
||||
|
||||
-
|
||||
name: create user which existed (skip unconditionally)
|
||||
skip: skip this test unconditionally
|
||||
times: 2
|
||||
request:
|
||||
url: http://127.0.0.1:5000/api/users/1000
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
device_sn: 'HZfFBh6tU59EdXJ'
|
||||
token: $token
|
||||
json:
|
||||
name: "user1"
|
||||
password: "123456"
|
||||
validate:
|
||||
- "eq": ["status_code", 500]
|
||||
- sum_status_code: ["status_code", 5]
|
||||
- "eq": ["content.success", false]
|
||||
- {"check": "status_code", "comparator": "eq", "expect": 500}
|
||||
- {"check": "content.success", "comparator": "eq", "expect": false}
|
||||
|
||||
-
|
||||
name: create user which existed (skip if condition)
|
||||
skipIf: ${skip_test_in_production_env()}
|
||||
times: 2
|
||||
request:
|
||||
url: http://127.0.0.1:5000/api/users/1000
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
device_sn: 'HZfFBh6tU59EdXJ'
|
||||
token: $token
|
||||
json:
|
||||
name: "user1"
|
||||
password: "123456"
|
||||
validate:
|
||||
- "eq": ["status_code", 500]
|
||||
- sum_status_code: ["status_code", 5]
|
||||
- "eq": ["content.success", false]
|
||||
- {"check": "status_code", "comparator": "eq", "expect": 500}
|
||||
- {"check": "content.success", "comparator": "eq", "expect": false}
|
||||
|
||||
-
|
||||
name: create user which existed (skip unless condition)
|
||||
skipUnless: ${skip_test_in_production_env()}
|
||||
times: 2
|
||||
request:
|
||||
url: http://127.0.0.1:5000/api/users/1000
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
device_sn: 'HZfFBh6tU59EdXJ'
|
||||
token: $token
|
||||
json:
|
||||
name: "user1"
|
||||
password: "123456"
|
||||
validate:
|
||||
- "eq": ["status_code", 500]
|
||||
- sum_status_code: ["status_code", 5]
|
||||
- "eq": ["content.success", false]
|
||||
- {"check": "status_code", "comparator": "eq", "expect": 500}
|
||||
- {"check": "content.success", "comparator": "eq", "expect": false}
|
||||
@@ -1,62 +0,0 @@
|
||||
config:
|
||||
name: "create user testcases."
|
||||
variables:
|
||||
user_agent: 'iOS/10.3'
|
||||
device_sn: ${gen_random_string(15)}
|
||||
os_platform: 'ios'
|
||||
app_version: '2.8.6'
|
||||
base_url: ${get_base_url()}
|
||||
|
||||
teststeps:
|
||||
-
|
||||
name: get token
|
||||
request:
|
||||
url: /api/get-token
|
||||
method: POST
|
||||
headers:
|
||||
user_agent: $user_agent
|
||||
device_sn: $device_sn
|
||||
os_platform: $os_platform
|
||||
app_version: $app_version
|
||||
json:
|
||||
sign: ${get_sign($device_sn, $os_platform, $app_version)}
|
||||
extract:
|
||||
token: content.token
|
||||
validate:
|
||||
- {"check": "status_code", "comparator": "eq", "expect": 200}
|
||||
- {"check": "content.token", "comparator": "len_eq", "expect": 16}
|
||||
|
||||
-
|
||||
name: create user which does not exist
|
||||
variables:
|
||||
user_name: "user1"
|
||||
user_password: "123456"
|
||||
request:
|
||||
url: /api/users/1000
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
device_sn: $device_sn
|
||||
token: $token
|
||||
json:
|
||||
name: $user_name
|
||||
password: $user_password
|
||||
validate:
|
||||
- {"check": "status_code", "comparator": "eq", "expect": 201}
|
||||
- {"check": "content.success", "comparator": "eq", "expect": true}
|
||||
|
||||
-
|
||||
name: create user which does not exist
|
||||
request:
|
||||
url: /api/users/1000
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
device_sn: $device_sn
|
||||
token: $token
|
||||
json:
|
||||
name: "user1"
|
||||
password: "123456"
|
||||
validate:
|
||||
- {"check": "status_code", "comparator": "eq", "expect": 500}
|
||||
- {"check": "content.success", "comparator": "eq", "expect": false}
|
||||
@@ -1,147 +0,0 @@
|
||||
config:
|
||||
name: "user management testcase."
|
||||
variables:
|
||||
user_agent: 'iOS/10.3'
|
||||
device_sn: ${gen_random_string(15)}
|
||||
os_platform: 'ios'
|
||||
app_version: '2.8.6'
|
||||
base_url: ${get_base_url()}
|
||||
export:
|
||||
- token
|
||||
|
||||
teststeps:
|
||||
-
|
||||
name: get token with $user_agent, $app_version
|
||||
api: api/get_token.yml
|
||||
extract:
|
||||
token: content.token
|
||||
validate:
|
||||
- "eq": ["status_code", 200]
|
||||
- "len_eq": ["content.token", 16]
|
||||
- "contains": [{"a": 1, "b": 2}, "b"]
|
||||
|
||||
-
|
||||
name: reset all users
|
||||
api: api/reset_all.yml
|
||||
variables:
|
||||
token: $token
|
||||
validate:
|
||||
- {"check": "status_code", "expect": 200}
|
||||
- {"check": "content.success", "expect": true}
|
||||
|
||||
-
|
||||
name: get user that does not exist
|
||||
api: api/get_user.yml
|
||||
variables:
|
||||
uid: 1000
|
||||
token: $token
|
||||
validate:
|
||||
- {"check": "status_code", "expect": 404}
|
||||
- {"check": "content.success", "expect": false}
|
||||
|
||||
-
|
||||
name: create user which does not exist
|
||||
variables:
|
||||
uid: 1000
|
||||
user_name: "user1"
|
||||
user_password: "123456"
|
||||
token: $token
|
||||
api: api/create_user.yml
|
||||
validate:
|
||||
- {"check": "status_code", "expect": 201}
|
||||
- {"check": "content.success", "expect": true}
|
||||
|
||||
-
|
||||
name: get user that has been created
|
||||
api: api/get_user.yml
|
||||
variables:
|
||||
uid: 1000
|
||||
token: $token
|
||||
validate:
|
||||
- {"check": "status_code", "expect": 200}
|
||||
- {"check": "content.success", "expect": true}
|
||||
- {"check": "content.data.password", "expect": "123456"}
|
||||
|
||||
-
|
||||
name: create user which exists
|
||||
variables:
|
||||
uid: 1000
|
||||
user_name: "user1"
|
||||
user_password: "123456"
|
||||
token: $token
|
||||
api: api/create_user.yml
|
||||
validate:
|
||||
- {"check": "status_code", "expect": 500}
|
||||
- {"check": "content.success", "expect": false}
|
||||
|
||||
-
|
||||
name: update user which exists
|
||||
variables:
|
||||
uid: 1000
|
||||
user_name: "user1"
|
||||
user_password: "654321"
|
||||
token: $token
|
||||
api: api/update_user.yml
|
||||
validate:
|
||||
- {"check": "status_code", "expect": 200}
|
||||
- {"check": "content.success", "expect": true}
|
||||
|
||||
-
|
||||
name: get user that has been updated
|
||||
api: api/get_user.yml
|
||||
variables:
|
||||
uid: 1000
|
||||
token: $token
|
||||
validate:
|
||||
- {"check": "status_code", "expect": 200}
|
||||
- {"check": "content.success", "expect": true}
|
||||
- {"check": "content.data.password", "expect": "654321"}
|
||||
|
||||
-
|
||||
name: get users
|
||||
api: api/get_users.yml
|
||||
variables:
|
||||
token: $token
|
||||
validate:
|
||||
- {"check": "status_code", "expect": 200}
|
||||
- {"check": "content.count", "expect": 1}
|
||||
|
||||
-
|
||||
name: delete user that exists
|
||||
api: api/delete_user.yml
|
||||
variables:
|
||||
uid: 1000
|
||||
token: $token
|
||||
validate:
|
||||
- {"check": "status_code", "expect": 200}
|
||||
- {"check": "content.success", "expect": true}
|
||||
|
||||
-
|
||||
name: get users
|
||||
api: api/get_users.yml
|
||||
variables:
|
||||
token: $token
|
||||
validate:
|
||||
- {"check": "status_code", "expect": 200}
|
||||
- {"check": "content.count", "expect": 0}
|
||||
|
||||
-
|
||||
name: create user which has been deleted
|
||||
variables:
|
||||
uid: 1000
|
||||
user_name: "user1"
|
||||
user_password: "123456"
|
||||
token: $token
|
||||
api: api/create_user.yml
|
||||
validate:
|
||||
- {"check": "status_code", "expect": 201}
|
||||
- {"check": "content.success", "expect": true}
|
||||
|
||||
-
|
||||
name: get users
|
||||
api: api/get_users.yml
|
||||
variables:
|
||||
token: $token
|
||||
validate:
|
||||
- {"check": "status_code", "expect": 200}
|
||||
- {"check": "content.count", "expect": 1}
|
||||
@@ -1,65 +0,0 @@
|
||||
config:
|
||||
name: "create user testcases."
|
||||
variables:
|
||||
device_sn: 'HZfFBh6tU59EdXJ'
|
||||
base_url: ${get_base_url()}
|
||||
|
||||
teststeps:
|
||||
-
|
||||
name: get token
|
||||
variables:
|
||||
user_agent: 'iOS/10.3'
|
||||
os_platform: 'ios'
|
||||
app_version: '2.8.6'
|
||||
sign: 5188962c489d1a35effa99e9346dd5efd4fdabad
|
||||
request:
|
||||
url: /api/get-token
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
user_agent: $user_agent
|
||||
device_sn: $device_sn
|
||||
os_platform: $os_platform
|
||||
app_version: $app_version
|
||||
json:
|
||||
sign: $sign
|
||||
extract:
|
||||
token: content.token
|
||||
validate:
|
||||
- {"check": "status_code", "comparator": "eq", "expect": 200}
|
||||
- {"check": "content.token", "comparator": "len_eq", "expect": 16}
|
||||
|
||||
-
|
||||
name: create user which does not exist
|
||||
variables:
|
||||
user_name: "user1"
|
||||
user_password: "123456"
|
||||
request:
|
||||
url: /api/users/1000
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
device_sn: $device_sn
|
||||
token: $token
|
||||
json:
|
||||
name: $user_name
|
||||
password: $user_password
|
||||
validate:
|
||||
- {"check": "status_code", "comparator": "eq", "expect": 201}
|
||||
- {"check": "content.success", "comparator": "eq", "expect": true}
|
||||
|
||||
-
|
||||
name: create user which does not exist
|
||||
request:
|
||||
url: /api/users/1000
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
device_sn: $device_sn
|
||||
token: $token
|
||||
json:
|
||||
name: "user1"
|
||||
password: "123456"
|
||||
validate:
|
||||
- {"check": "status_code", "comparator": "eq", "expect": 500}
|
||||
- {"check": "content.success", "comparator": "eq", "expect": false}
|
||||
@@ -1,4 +0,0 @@
|
||||
UserName=test
|
||||
Password=654321
|
||||
PROJECT_KEY=AAABBBCCC
|
||||
content_type=application/json; charset=UTF-8
|
||||
@@ -1,4 +0,0 @@
|
||||
user_agent
|
||||
iOS/10.1
|
||||
iOS/10.2
|
||||
iOS/10.3
|
||||
|
@@ -1,172 +0,0 @@
|
||||
import os
|
||||
import random
|
||||
import string
|
||||
import time
|
||||
import uuid
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from tests.api_server import HTTPBIN_SERVER, gen_md5, get_sign
|
||||
|
||||
BASE_URL = "http://127.0.0.1:5000"
|
||||
|
||||
|
||||
def get_httpbin_server():
|
||||
return HTTPBIN_SERVER
|
||||
|
||||
|
||||
def get_base_url():
|
||||
return BASE_URL
|
||||
|
||||
|
||||
def get_default_request():
|
||||
return {
|
||||
"base_url": BASE_URL,
|
||||
"headers": {
|
||||
"content-type": "application/json"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def setup_testcase(variables):
|
||||
logger.info(f"setup_testcase, variables: {variables}")
|
||||
variables["request_id_prefix"] = str(int(time.time()))
|
||||
|
||||
|
||||
def teardown_testcase():
|
||||
logger.info(f"teardown_testcase.")
|
||||
|
||||
|
||||
def setup_teststep(request, variables):
|
||||
logger.info(f"setup_teststep, request: {request}, variables: {variables}")
|
||||
request.setdefault("headers", {})
|
||||
request_id_prefix = variables["request_id_prefix"]
|
||||
request["headers"]["HRUN-Request-ID"] = request_id_prefix + "-" + str(uuid.uuid4())
|
||||
|
||||
|
||||
def teardown_teststep(response):
|
||||
logger.info(f"teardown_teststep, response status code: {response.status_code}")
|
||||
|
||||
|
||||
def sum_two(m, n):
|
||||
return m + n
|
||||
|
||||
|
||||
def sum_status_code(status_code, expect_sum):
|
||||
""" sum status code digits
|
||||
e.g. 400 => 4, 201 => 3
|
||||
"""
|
||||
sum_value = 0
|
||||
for digit in str(status_code):
|
||||
sum_value += int(digit)
|
||||
|
||||
assert sum_value == expect_sum
|
||||
|
||||
|
||||
def is_status_code_200(status_code):
|
||||
return status_code == 200
|
||||
|
||||
|
||||
os.environ["TEST_ENV"] = "PRODUCTION"
|
||||
|
||||
|
||||
def skip_test_in_production_env():
|
||||
""" skip this test in production environment
|
||||
"""
|
||||
return os.environ["TEST_ENV"] == "PRODUCTION"
|
||||
|
||||
|
||||
def get_user_agent():
|
||||
return ["iOS/10.1", "iOS/10.2"]
|
||||
|
||||
|
||||
def gen_app_version():
|
||||
return [
|
||||
{"app_version": "2.8.5"},
|
||||
{"app_version": "2.8.6"}
|
||||
]
|
||||
|
||||
|
||||
def get_account():
|
||||
return [
|
||||
{"username": "user1", "password": "111111"},
|
||||
{"username": "user2", "password": "222222"}
|
||||
]
|
||||
|
||||
|
||||
def get_account_in_tuple():
|
||||
return [("user1", "111111"), ("user2", "222222")]
|
||||
|
||||
|
||||
def gen_random_string(str_len):
|
||||
random_char_list = []
|
||||
for _ in range(str_len):
|
||||
random_char = random.choice(string.ascii_letters + string.digits)
|
||||
random_char_list.append(random_char)
|
||||
|
||||
random_string = ''.join(random_char_list)
|
||||
return random_string
|
||||
|
||||
|
||||
def setup_hook_add_kwargs(request):
|
||||
request["key"] = "value"
|
||||
|
||||
|
||||
def setup_hook_remove_kwargs(request):
|
||||
request.pop("key")
|
||||
|
||||
|
||||
def teardown_hook_sleep_N_secs(response, n_secs):
|
||||
""" sleep n seconds after request
|
||||
"""
|
||||
if response.status_code == 200:
|
||||
time.sleep(0.1)
|
||||
else:
|
||||
time.sleep(n_secs)
|
||||
|
||||
|
||||
def hook_print(msg):
|
||||
print(msg)
|
||||
|
||||
|
||||
def modify_request_json(request, os_platform):
|
||||
request["json"]["os_platform"] = os_platform
|
||||
|
||||
|
||||
def setup_hook_httpntlmauth(request):
|
||||
if "httpntlmauth" in request:
|
||||
from requests_ntlm import HttpNtlmAuth
|
||||
auth_account = request.pop("httpntlmauth")
|
||||
request["auth"] = HttpNtlmAuth(
|
||||
auth_account["username"], auth_account["password"])
|
||||
|
||||
|
||||
def alter_response(response):
|
||||
response.status_code = 500
|
||||
response.headers["Content-Type"] = "html/text"
|
||||
response.json["headers"]["Host"] = "127.0.0.1:8888"
|
||||
response.new_attribute = "new_attribute_value"
|
||||
response.new_attribute_dict = {
|
||||
"key": 123
|
||||
}
|
||||
|
||||
def alter_response_302(response):
|
||||
response.status_code = 500
|
||||
response.headers["Content-Type"] = "html/text"
|
||||
response.text = "abcdef"
|
||||
response.new_attribute = "new_attribute_value"
|
||||
response.new_attribute_dict = {
|
||||
"key": 123
|
||||
}
|
||||
|
||||
|
||||
def alter_response_error(response):
|
||||
# NameError
|
||||
not_defined_variable
|
||||
|
||||
|
||||
def gen_variables():
|
||||
return {
|
||||
"var_a": 1,
|
||||
"var_b": 2
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
name: rpc api
|
||||
base_url: http://httpbin.org
|
||||
variables:
|
||||
expected_status_code: 200
|
||||
request:
|
||||
url: /headers
|
||||
method: GET
|
||||
validate:
|
||||
- eq: ["status_code", $expected_status_code]
|
||||
- eq: [content.headers.Host, "httpbin.org"]
|
||||
@@ -1,11 +0,0 @@
|
||||
|
||||
name: 302 redirect
|
||||
request:
|
||||
url: https://httpbin.org/redirect-to
|
||||
params:
|
||||
url: https://github.com
|
||||
status_code: 302
|
||||
method: GET
|
||||
verify: False
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
@@ -1,13 +0,0 @@
|
||||
name: 302 redirect
|
||||
request:
|
||||
url: https://httpbin.org/redirect-to
|
||||
params:
|
||||
url: https://github.com
|
||||
status_code: 302
|
||||
method: GET
|
||||
verify: False
|
||||
teardown_hooks:
|
||||
- ${alter_response_302($response)}
|
||||
validate:
|
||||
- eq: ["status_code", 500]
|
||||
- eq: ["text","abcdef"]
|
||||
@@ -1,11 +0,0 @@
|
||||
|
||||
name: get headers
|
||||
base_url: http://httpbin.org
|
||||
variables:
|
||||
expected_status_code: 200
|
||||
request:
|
||||
url: /headers
|
||||
method: GET
|
||||
validate:
|
||||
- eq: ["status_code", $expected_status_code]
|
||||
- eq: [content.headers.Host, "httpbin.org"]
|
||||
@@ -1,91 +0,0 @@
|
||||
config:
|
||||
name: basic test with httpbin
|
||||
base_url: https://httpbin.org/
|
||||
|
||||
teststeps:
|
||||
-
|
||||
name: headers
|
||||
request:
|
||||
url: /headers
|
||||
method: GET
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
- eq: [content.headers.Host, "httpbin.org"]
|
||||
|
||||
-
|
||||
name: user-agent
|
||||
request:
|
||||
url: /user-agent
|
||||
method: GET
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
- startswith: [content.user-agent, "python-requests"]
|
||||
|
||||
-
|
||||
name: get without params
|
||||
request:
|
||||
url: /get
|
||||
method: GET
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
- eq: [content.args, {}]
|
||||
|
||||
-
|
||||
name: get with params in url
|
||||
request:
|
||||
url: /get?a=1&b=2
|
||||
method: GET
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
- eq: [content.args, {'a': '1', 'b': '2'}]
|
||||
|
||||
-
|
||||
name: get with params in params field
|
||||
request:
|
||||
url: /get
|
||||
params:
|
||||
a: 1
|
||||
b: 2
|
||||
method: GET
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
- eq: [content.args, {'a': '1', 'b': '2'}]
|
||||
|
||||
-
|
||||
name: set cookie
|
||||
request:
|
||||
url: /cookies/set?name=value
|
||||
method: GET
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
# - eq: [cookies.name, "value"]
|
||||
|
||||
-
|
||||
name: extract cookie
|
||||
request:
|
||||
url: /cookies
|
||||
method: GET
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
# - eq: [cookies.name, "value"]
|
||||
|
||||
-
|
||||
name: post data
|
||||
request:
|
||||
url: /post
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
data: abc
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
|
||||
-
|
||||
name: validate content length
|
||||
request:
|
||||
url: /spec.json
|
||||
method: GET
|
||||
validate:
|
||||
- len_eq: ["content", 9]
|
||||
- len_eq: ["json", 9]
|
||||
- len_eq: ["text", 9]
|
||||
@@ -1,38 +0,0 @@
|
||||
config:
|
||||
name: basic test with httpbin
|
||||
base_url: ${get_httpbin_server()}
|
||||
setup_hooks:
|
||||
- ${hook_print(setup)}
|
||||
teardown_hooks:
|
||||
- ${hook_print(teardown)}
|
||||
|
||||
teststeps:
|
||||
-
|
||||
name: headers
|
||||
variables:
|
||||
a: 123
|
||||
request:
|
||||
url: /headers
|
||||
method: GET
|
||||
setup_hooks:
|
||||
- ${setup_hook_add_kwargs($request)}
|
||||
- ${setup_hook_remove_kwargs($request)}
|
||||
teardown_hooks:
|
||||
- ${teardown_hook_sleep_N_secs($response, 1)}
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
- contained_by: [content.headers.Host, "${get_httpbin_server()}"]
|
||||
|
||||
-
|
||||
name: alter response
|
||||
request:
|
||||
url: /headers
|
||||
method: GET
|
||||
teardown_hooks:
|
||||
- ${alter_response($response)}
|
||||
validate:
|
||||
- eq: ["status_code", 500]
|
||||
- eq: ["headers.content-type", "html/text"]
|
||||
- eq: [json.headers.Host, "127.0.0.1:8888"]
|
||||
- eq: [content.headers.Host, "127.0.0.1:8888"]
|
||||
- eq: [text.headers.Host, "127.0.0.1:8888"]
|
||||
@@ -1,37 +0,0 @@
|
||||
config:
|
||||
name: load images
|
||||
base_url: ${get_httpbin_server()}
|
||||
|
||||
teststeps:
|
||||
-
|
||||
name: get png image
|
||||
request:
|
||||
url: /image/png
|
||||
method: GET
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
|
||||
-
|
||||
name: get jpeg image
|
||||
request:
|
||||
url: /image/jpeg
|
||||
method: GET
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
|
||||
-
|
||||
name: get webp image
|
||||
request:
|
||||
url: /image/webp
|
||||
method: GET
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
|
||||
-
|
||||
name: get svg image
|
||||
request:
|
||||
url: /image/svg
|
||||
method: GET
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
config:
|
||||
name: test upload file with httpbin
|
||||
base_url: ${get_httpbin_server()}
|
||||
|
||||
teststeps:
|
||||
-
|
||||
name: upload file
|
||||
variables:
|
||||
file_path: "data/test.env"
|
||||
m_encoder: ${multipart_encoder(file=$file_path)}
|
||||
request:
|
||||
url: /post
|
||||
method: POST
|
||||
headers:
|
||||
Content-Type: ${multipart_content_type($m_encoder)}
|
||||
data: $m_encoder
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
- startswith: ["content.files.file", "UserName=test"]
|
||||
|
||||
-
|
||||
name: upload file with keyword
|
||||
request:
|
||||
url: /post
|
||||
method: POST
|
||||
upload:
|
||||
file: "data/test.env"
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
- startswith: ["content.files.file", "UserName=test"]
|
||||
@@ -1,35 +0,0 @@
|
||||
config:
|
||||
name: basic test with httpbin
|
||||
base_url: http://httpbin.org/
|
||||
|
||||
teststeps:
|
||||
-
|
||||
name: validate response with json path
|
||||
request:
|
||||
url: /get
|
||||
params:
|
||||
a: 1
|
||||
b: 2
|
||||
method: GET
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
- eq: ["json.args.a", '1']
|
||||
- eq: ["json.args.b", '2']
|
||||
validate_script:
|
||||
- "assert status_code == 200"
|
||||
|
||||
|
||||
-
|
||||
name: validate response with python script
|
||||
request:
|
||||
url: /get
|
||||
params:
|
||||
a: 1
|
||||
b: 2
|
||||
method: GET
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
validate_script:
|
||||
- "assert status_code == 201"
|
||||
- "a = response_json.get('args').get('a')"
|
||||
- "assert a == '1'"
|
||||
@@ -1,778 +0,0 @@
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import time
|
||||
|
||||
from httprunner import exceptions, loader, parser, report
|
||||
from httprunner.api import HttpRunner
|
||||
from tests.api_server import HTTPBIN_SERVER
|
||||
from tests.base import ApiServerUnittest
|
||||
|
||||
|
||||
class TestHttpRunner(ApiServerUnittest):
|
||||
|
||||
def setUp(self):
|
||||
self.testcase_cli_path = "tests/data/demo_testcase_cli.yml"
|
||||
testcases = [{
|
||||
'config': {
|
||||
'name': 'testcase description',
|
||||
'request': {
|
||||
'base_url': '',
|
||||
'headers': {'User-Agent': 'python-requests/2.18.4'}
|
||||
},
|
||||
'variables': []
|
||||
},
|
||||
"teststeps": [
|
||||
{
|
||||
'name': '/api/get-token',
|
||||
'request': {
|
||||
'url': 'http://127.0.0.1:5000/api/get-token',
|
||||
'method': 'POST',
|
||||
'headers': {'Content-Type': 'application/json', 'app_version': '2.8.6',
|
||||
'device_sn': 'FwgRiO7CNA50DSU', 'os_platform': 'ios', 'user_agent': 'iOS/10.3'},
|
||||
'json': {'sign': '9c0c7e51c91ae963c833a4ccbab8d683c4a90c98'}
|
||||
},
|
||||
'extract': [
|
||||
{'token': 'content.token'}
|
||||
],
|
||||
'validate': [
|
||||
{'eq': ['status_code', 200]},
|
||||
{'eq': ['headers.Content-Type', 'application/json']},
|
||||
{'eq': ['content.success', True]}
|
||||
]
|
||||
},
|
||||
{
|
||||
'name': '/api/users/1000',
|
||||
'request': {
|
||||
'url': 'http://127.0.0.1:5000/api/users/1000',
|
||||
'method': 'POST',
|
||||
'headers': {'Content-Type': 'application/json',
|
||||
'device_sn': 'FwgRiO7CNA50DSU','token': '$token'},
|
||||
'json': {'name': 'user1', 'password': '123456'}
|
||||
},
|
||||
'validate': [
|
||||
{'eq': ['status_code', 201]},
|
||||
{'eq': ['headers.Content-Type', 'application/json']},
|
||||
{'eq': ['content.success', True]},
|
||||
{'eq': ['content.msg', 'user created successfully.']}
|
||||
]
|
||||
}
|
||||
]
|
||||
}]
|
||||
self.tests_mapping = {
|
||||
"testcases": testcases
|
||||
}
|
||||
self.runner = HttpRunner(failfast=True)
|
||||
self.reset_all()
|
||||
|
||||
def reset_all(self):
|
||||
url = "%s/api/reset-all" % self.host
|
||||
headers = self.get_authenticated_headers()
|
||||
return self.api_client.get(url, headers=headers)
|
||||
|
||||
def test_text_run_times(self):
|
||||
summary = self.runner.run(self.testcase_cli_path)
|
||||
self.assertEqual(summary["stat"]["testcases"]["total"], 1)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["total"], 10)
|
||||
|
||||
def test_text_run_times_invalid(self):
|
||||
testcases = [
|
||||
{
|
||||
"config": {
|
||||
'name': "post data",
|
||||
'variables': []
|
||||
},
|
||||
"teststeps": [
|
||||
{
|
||||
"name": "post data",
|
||||
"times": "1.5",
|
||||
"request": {
|
||||
"url": "{}/post".format(HTTPBIN_SERVER),
|
||||
"method": "POST",
|
||||
"headers": {
|
||||
"User-Agent": "python-requests/2.18.4",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
"data": "abc"
|
||||
},
|
||||
"validate": [
|
||||
{"eq": ["status_code", 200]}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
tests_mapping = {
|
||||
"testcases": testcases
|
||||
}
|
||||
with self.assertRaises(exceptions.ParamsError):
|
||||
self.runner.run_tests(tests_mapping)
|
||||
|
||||
def test_text_skip(self):
|
||||
summary = self.runner.run(self.testcase_cli_path)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["skipped"], 4)
|
||||
|
||||
def test_save_variables_output(self):
|
||||
testcases = [
|
||||
{
|
||||
"config": {
|
||||
'name': "post data",
|
||||
'variables': {
|
||||
"var1": "abc",
|
||||
"var2": "def"
|
||||
},
|
||||
"export": ["status_code", "req_data"]
|
||||
},
|
||||
"teststeps": [
|
||||
{
|
||||
"name": "post data",
|
||||
"request": {
|
||||
"url": "{}/post".format(HTTPBIN_SERVER),
|
||||
"method": "POST",
|
||||
"headers": {
|
||||
"User-Agent": "python-requests/2.18.4",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
"data": "$var1"
|
||||
},
|
||||
"extract": {
|
||||
"status_code": "status_code",
|
||||
"req_data": "content.data"
|
||||
},
|
||||
"validate": [
|
||||
{"eq": ["status_code", 200]}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
tests_mapping = {
|
||||
"testcases": testcases
|
||||
}
|
||||
self.runner.run_tests(tests_mapping)
|
||||
vars_out = self.runner.get_vars_out()
|
||||
self.assertIsInstance(vars_out, list)
|
||||
self.assertEqual(vars_out[0]["in"]["var1"], "abc")
|
||||
self.assertEqual(vars_out[0]["in"]["var2"], "def")
|
||||
self.assertEqual(vars_out[0]["out"]["status_code"], 200)
|
||||
self.assertEqual(vars_out[0]["out"]["req_data"], "abc")
|
||||
|
||||
def test_save_variables_output_with_parameters(self):
|
||||
testcase_file_path = os.path.join(
|
||||
os.getcwd(), 'tests/testsuites/create_users_with_parameters.yml')
|
||||
self.runner.run(testcase_file_path)
|
||||
vars_out = self.runner.get_vars_out()
|
||||
self.assertIsInstance(vars_out, list)
|
||||
self.assertEqual(len(vars_out), 6)
|
||||
self.assertEqual(vars_out[0]["in"]["uid"], 101)
|
||||
self.assertEqual(vars_out[0]["in"]["device_sn"], "TESTSUITE_X1")
|
||||
token1 = vars_out[0]["out"]["session_token"]
|
||||
self.assertEqual(len(token1), 16)
|
||||
self.assertEqual(vars_out[5]["in"]["uid"], 103)
|
||||
self.assertEqual(vars_out[5]["in"]["device_sn"], "TESTSUITE_X2")
|
||||
token2 = vars_out[0]["out"]["session_token"]
|
||||
self.assertEqual(len(token2), 16)
|
||||
self.assertEqual(token1, token2)
|
||||
|
||||
def test_html_report(self):
|
||||
runner = HttpRunner(failfast=True)
|
||||
summary = runner.run(self.testcase_cli_path)
|
||||
self.assertEqual(summary["stat"]["testcases"]["total"], 1)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["total"], 10)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["skipped"], 4)
|
||||
|
||||
report_save_dir = os.path.join(os.getcwd(), 'reports', "demo")
|
||||
report.gen_html_report(summary, report_dir=report_save_dir)
|
||||
self.assertGreater(len(os.listdir(report_save_dir)), 0)
|
||||
shutil.rmtree(report_save_dir)
|
||||
|
||||
def test_html_report_with_fixed_report_file(self):
|
||||
runner = HttpRunner(failfast=True)
|
||||
summary = runner.run(self.testcase_cli_path)
|
||||
self.assertEqual(summary["stat"]["testcases"]["total"], 1)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["total"], 10)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["skipped"], 4)
|
||||
|
||||
report_file = os.path.join(os.getcwd(), 'reports', "demo", "test.html")
|
||||
report.gen_html_report(summary, report_file=report_file)
|
||||
report_save_dir = os.path.dirname(report_file)
|
||||
self.assertEqual(len(os.listdir(report_save_dir)), 1)
|
||||
self.assertTrue(os.path.isfile(report_file))
|
||||
shutil.rmtree(report_save_dir)
|
||||
|
||||
def test_log_file(self):
|
||||
log_file_path = os.path.join(os.getcwd(), 'reports', "test_log_file.log")
|
||||
runner = HttpRunner(failfast=True, log_file=log_file_path)
|
||||
runner.run(self.testcase_cli_path)
|
||||
self.assertTrue(os.path.isfile(log_file_path))
|
||||
os.remove(log_file_path)
|
||||
|
||||
def test_run_testcases(self):
|
||||
summary = self.runner.run_tests(self.tests_mapping)
|
||||
self.assertTrue(summary["success"])
|
||||
self.assertEqual(summary["stat"]["testcases"]["total"], 1)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["total"], 2)
|
||||
self.assertIn("details", summary)
|
||||
self.assertIn("records", summary["details"][0])
|
||||
|
||||
def test_run_yaml_upload(self):
|
||||
summary = self.runner.run("tests/httpbin/upload.yml")
|
||||
self.assertTrue(summary["success"])
|
||||
self.assertEqual(summary["stat"]["testcases"]["total"], 1)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["total"], 2)
|
||||
self.assertIn("details", summary)
|
||||
self.assertIn("records", summary["details"][0])
|
||||
|
||||
def test_run_post_data(self):
|
||||
testcases = [
|
||||
{
|
||||
"config": {
|
||||
'name': "post data",
|
||||
'variables': []
|
||||
},
|
||||
"teststeps": [
|
||||
{
|
||||
"name": "post data",
|
||||
"request": {
|
||||
"url": "{}/post".format(HTTPBIN_SERVER),
|
||||
"method": "POST",
|
||||
"headers": {
|
||||
"User-Agent": "python-requests/2.18.4",
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
"data": "abc"
|
||||
},
|
||||
"validate": [
|
||||
{"eq": ["status_code", 200]}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
tests_mapping = {
|
||||
"testcases": testcases
|
||||
}
|
||||
summary = self.runner.run_tests(tests_mapping)
|
||||
self.assertTrue(summary["success"])
|
||||
self.assertEqual(summary["stat"]["testcases"]["total"], 1)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["total"], 1)
|
||||
resp_json = json.loads(summary["details"][0]["records"][0]["meta_datas"]["data"][0]["response"]["body"])
|
||||
self.assertEqual(
|
||||
resp_json["data"],
|
||||
"abc"
|
||||
)
|
||||
|
||||
def test_html_report_repsonse_image(self):
|
||||
runner = HttpRunner(failfast=True)
|
||||
summary = runner.run("tests/httpbin/load_image.yml")
|
||||
|
||||
report_save_dir = os.path.join(os.getcwd(), 'reports', "demo")
|
||||
report_path = report.gen_html_report(summary, report_dir=report_save_dir)
|
||||
self.assertTrue(os.path.isfile(report_path))
|
||||
shutil.rmtree(report_save_dir)
|
||||
|
||||
def test_testcase_layer_with_api(self):
|
||||
summary = self.runner.run("tests/testcases/setup.yml")
|
||||
self.assertTrue(summary["success"])
|
||||
self.assertEqual(summary["details"][0]["records"][0]["name"], "get token (setup)")
|
||||
self.assertEqual(summary["stat"]["testcases"]["total"], 1)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["total"], 2)
|
||||
|
||||
def test_testcase_layer_with_testcase(self):
|
||||
summary = self.runner.run("tests/testsuites/create_users.yml")
|
||||
self.assertTrue(summary["success"])
|
||||
self.assertEqual(summary["stat"]["testcases"]["total"], 2)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["total"], 4)
|
||||
|
||||
def test_validate_script(self):
|
||||
summary = self.runner.run("tests/httpbin/validate.yml")
|
||||
self.assertFalse(summary["success"])
|
||||
|
||||
def test_run_httprunner_with_hooks(self):
|
||||
testcase_file_path = os.path.join(
|
||||
os.getcwd(), 'tests/httpbin/hooks.yml')
|
||||
start_time = time.time()
|
||||
summary = self.runner.run(testcase_file_path)
|
||||
end_time = time.time()
|
||||
self.assertTrue(summary["success"])
|
||||
self.assertLess(end_time - start_time, 60)
|
||||
|
||||
def test_run_httprunner_with_teardown_hooks_alter_response(self):
|
||||
testcases = [
|
||||
{
|
||||
"config": {"name": "test teardown hooks"},
|
||||
"teststeps": [
|
||||
{
|
||||
"name": "test teardown hooks",
|
||||
"request": {
|
||||
"url": "{}/headers".format(HTTPBIN_SERVER),
|
||||
"method": "GET",
|
||||
"data": "abc"
|
||||
},
|
||||
"teardown_hooks": [
|
||||
"${alter_response($response)}"
|
||||
],
|
||||
"validate": [
|
||||
{"eq": ["status_code", 500]},
|
||||
{"eq": ["headers.content-type", "html/text"]},
|
||||
{"eq": ["json.headers.Host", "127.0.0.1:8888"]},
|
||||
{"eq": ["content.headers.Host", "127.0.0.1:8888"]},
|
||||
{"eq": ["text.headers.Host", "127.0.0.1:8888"]},
|
||||
{"eq": ["new_attribute", "new_attribute_value"]},
|
||||
{"eq": ["new_attribute_dict", {"key": 123}]},
|
||||
{"eq": ["new_attribute_dict.key", 123]}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
tests_mapping = {
|
||||
"project_mapping": loader.load_project_data("tests"),
|
||||
"testcases": testcases
|
||||
}
|
||||
summary = self.runner.run_tests(tests_mapping)
|
||||
self.assertTrue(summary["success"])
|
||||
|
||||
def test_run_httprunner_with_teardown_hooks_not_exist_attribute(self):
|
||||
testcases = [
|
||||
{
|
||||
"config": {
|
||||
"name": "test teardown hooks"
|
||||
},
|
||||
"teststeps": [
|
||||
{
|
||||
"name": "test teardown hooks",
|
||||
"request": {
|
||||
"url": "{}/headers".format(HTTPBIN_SERVER),
|
||||
"method": "GET",
|
||||
"data": "abc"
|
||||
},
|
||||
"teardown_hooks": [
|
||||
"${alter_response($response)}"
|
||||
],
|
||||
"validate": [
|
||||
{"eq": ["attribute_not_exist", "new_attribute"]}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
tests_mapping = {
|
||||
"project_mapping": loader.load_project_data("tests"),
|
||||
"testcases": testcases
|
||||
}
|
||||
summary = self.runner.run_tests(tests_mapping)
|
||||
self.assertFalse(summary["success"])
|
||||
self.assertEqual(summary["stat"]["teststeps"]["errors"], 1)
|
||||
|
||||
def test_run_httprunner_with_teardown_hooks_error(self):
|
||||
testcases = [
|
||||
{
|
||||
"config": {
|
||||
"name": "test teardown hooks"
|
||||
},
|
||||
"teststeps": [
|
||||
{
|
||||
"name": "test teardown hooks",
|
||||
"request": {
|
||||
"url": "{}/headers".format(HTTPBIN_SERVER),
|
||||
"method": "GET",
|
||||
"data": "abc"
|
||||
},
|
||||
"teardown_hooks": [
|
||||
"${alter_response_error($response)}"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
tests_mapping = {
|
||||
"project_mapping": loader.load_project_data("tests"),
|
||||
"testcases": testcases
|
||||
}
|
||||
summary = self.runner.run_tests(tests_mapping)
|
||||
self.assertFalse(summary["success"])
|
||||
self.assertEqual(summary["stat"]["teststeps"]["errors"], 1)
|
||||
|
||||
def test_run_api(self):
|
||||
path = "tests/httpbin/api/get_headers.yml"
|
||||
summary = self.runner.run(path)
|
||||
self.assertTrue(summary["success"])
|
||||
self.assertEqual(summary["stat"]["testcases"]["total"], 1)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["total"], 1)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["successes"], 1)
|
||||
|
||||
def test_request_302_logs(self):
|
||||
path = "tests/httpbin/api/302_redirect.yml"
|
||||
summary = self.runner.run(path)
|
||||
self.assertTrue(summary["success"])
|
||||
self.assertEqual(summary["stat"]["testcases"]["total"], 1)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["total"], 1)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["successes"], 1)
|
||||
|
||||
req_resp_data = summary["details"][0]["records"][0]["meta_datas"]["data"]
|
||||
self.assertEqual(len(req_resp_data), 2)
|
||||
self.assertEqual(req_resp_data[0]["response"]["status_code"], 302)
|
||||
self.assertEqual(req_resp_data[1]["response"]["status_code"], 200)
|
||||
|
||||
def test_request_302_logs_teardown_hook(self):
|
||||
path = "tests/httpbin/api/302_redirect_teardown_hook.yml"
|
||||
summary = self.runner.run(path)
|
||||
self.assertTrue(summary["success"])
|
||||
self.assertEqual(summary["stat"]["testcases"]["total"], 1)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["total"], 1)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["successes"], 1)
|
||||
|
||||
req_resp_data = summary["details"][0]["records"][0]["meta_datas"]["data"]
|
||||
self.assertEqual(len(req_resp_data), 2)
|
||||
self.assertEqual(req_resp_data[0]["response"]["status_code"], 302)
|
||||
self.assertEqual(req_resp_data[1]["response"]["status_code"], 500)
|
||||
|
||||
def test_request_with_params(self):
|
||||
path = "tests/httpbin/api/302_redirect.yml"
|
||||
summary = self.runner.run(path)
|
||||
self.assertTrue(summary["success"])
|
||||
self.assertEqual(summary["stat"]["testcases"]["total"], 1)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["total"], 1)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["successes"], 1)
|
||||
|
||||
req_resp_data = summary["details"][0]["records"][0]["meta_datas"]["data"]
|
||||
self.assertEqual(len(req_resp_data), 2)
|
||||
self.assertIn(
|
||||
"url=https%3A%2F%2Fgithub.com",
|
||||
req_resp_data[0]["request"]["url"]
|
||||
)
|
||||
|
||||
def test_run_api_folder(self):
|
||||
api_folder = "tests/httpbin/api/"
|
||||
summary = self.runner.run(api_folder)
|
||||
print(summary["stat"]["testcases"]["total"])
|
||||
print(len(summary["details"]))
|
||||
self.assertTrue(summary["success"])
|
||||
self.assertEqual(summary["stat"]["testcases"]["total"], 3)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["total"], 3)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["successes"], 3)
|
||||
self.assertEqual(len(summary["details"]), 3)
|
||||
self.assertEqual(summary["details"][0]["stat"]["total"], 1)
|
||||
self.assertEqual(summary["details"][1]["stat"]["total"], 1)
|
||||
self.assertEqual(summary["details"][2]["stat"]["total"], 1)
|
||||
|
||||
def test_run_testcase_template_variables(self):
|
||||
testcase_file_path = os.path.join(
|
||||
os.getcwd(), 'tests/data/demo_testcase_variables.yml')
|
||||
summary = self.runner.run(testcase_file_path)
|
||||
self.assertTrue(summary["success"])
|
||||
|
||||
def test_run_testcase_template_import_functions(self):
|
||||
testcase_file_path = os.path.join(
|
||||
os.getcwd(), 'tests/data/demo_testcase_functions.yml')
|
||||
summary = self.runner.run(testcase_file_path)
|
||||
self.assertTrue(summary["success"])
|
||||
|
||||
def test_run_testcase_layered(self):
|
||||
testcase_file_path = os.path.join(
|
||||
os.getcwd(), 'tests/data/demo_testcase_layer.yml')
|
||||
summary = self.runner.run(testcase_file_path)
|
||||
self.assertTrue(summary["success"])
|
||||
self.assertEqual(len(summary["details"]), 1)
|
||||
|
||||
def test_run_testcase_output(self):
|
||||
testcase_file_path = os.path.join(
|
||||
os.getcwd(), 'tests/data/demo_testcase_layer.yml')
|
||||
summary = self.runner.run(testcase_file_path)
|
||||
self.assertTrue(summary["success"])
|
||||
self.assertIn("token", summary["details"][0]["in_out"]["out"])
|
||||
# TODO: add
|
||||
# self.assertIn("user_agent", summary["details"][0]["in_out"]["in"])
|
||||
|
||||
def test_run_testcase_with_variables_mapping(self):
|
||||
testcase_file_path = os.path.join(
|
||||
os.getcwd(), 'tests/data/demo_testcase_layer.yml')
|
||||
variables_mapping = {
|
||||
"app_version": '2.9.7'
|
||||
}
|
||||
summary = self.runner.run(testcase_file_path, mapping=variables_mapping)
|
||||
self.assertTrue(summary["success"])
|
||||
self.assertIn("token", summary["details"][0]["in_out"]["out"])
|
||||
# TODO: add
|
||||
# self.assertGreater(len(summary["details"][0]["in_out"]["in"]), 3)
|
||||
|
||||
def test_run_testcase_with_parameters(self):
|
||||
testcase_file_path = os.path.join(
|
||||
os.getcwd(), 'tests/testsuites/create_users_with_parameters.yml')
|
||||
summary = self.runner.run(testcase_file_path)
|
||||
self.assertTrue(summary["success"])
|
||||
self.assertEqual(len(summary["details"]), 3 * 2)
|
||||
|
||||
self.assertEqual(summary["stat"]["testcases"]["total"], 6)
|
||||
self.assertEqual(summary["stat"]["teststeps"]["total"], 3 * 2 * 2)
|
||||
self.assertEqual(
|
||||
summary["details"][0]["name"],
|
||||
"create user 101 and check result for TESTSUITE_X1."
|
||||
)
|
||||
self.assertEqual(
|
||||
summary["details"][5]["name"],
|
||||
"create user 103 and check result for TESTSUITE_X2."
|
||||
)
|
||||
self.assertEqual(
|
||||
summary["details"][0]["stat"]["total"],
|
||||
2
|
||||
)
|
||||
records_name_list = [
|
||||
summary["details"][i]["records"][1]["meta_datas"][1]["name"]
|
||||
for i in range(6)
|
||||
]
|
||||
self.assertEqual(
|
||||
set(records_name_list),
|
||||
{
|
||||
"create user 101 for TESTSUITE_X1",
|
||||
"create user 101 for TESTSUITE_X2",
|
||||
"create user 102 for TESTSUITE_X1",
|
||||
"create user 102 for TESTSUITE_X2",
|
||||
"create user 103 for TESTSUITE_X1",
|
||||
"create user 103 for TESTSUITE_X2"
|
||||
}
|
||||
)
|
||||
|
||||
def test_validate_response_content(self):
|
||||
testcase_file_path = os.path.join(
|
||||
os.getcwd(), 'tests/httpbin/basic.yml')
|
||||
summary = self.runner.run(testcase_file_path)
|
||||
self.assertTrue(summary["success"])
|
||||
|
||||
def test_html_report_xss(self):
|
||||
testcases = [
|
||||
{
|
||||
"config": {
|
||||
'name': "post data"
|
||||
},
|
||||
"teststeps": [
|
||||
{
|
||||
"name": "post data",
|
||||
"request": {
|
||||
"url": "{}/anything".format(HTTPBIN_SERVER),
|
||||
"method": "POST",
|
||||
"headers": {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
"json": {
|
||||
'success': False,
|
||||
"person": "<img src=x onerror=alert(1)>"
|
||||
}
|
||||
},
|
||||
"validate": [
|
||||
{"eq": ["status_code", 200]}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
tests_mapping = {
|
||||
"testcases": testcases
|
||||
}
|
||||
summary = self.runner.run(tests_mapping)
|
||||
report_path = report.gen_html_report(summary)
|
||||
with open(report_path) as f:
|
||||
content = f.read()
|
||||
m = re.findall(
|
||||
re.escape(""person": "<img src=x onerror=alert(1)>""),
|
||||
content
|
||||
)
|
||||
self.assertEqual(len(m), 2)
|
||||
|
||||
|
||||
class TestApi(ApiServerUnittest):
|
||||
|
||||
def test_testcase_loader(self):
|
||||
testcase_path = "tests/testcases/setup.yml"
|
||||
tests_mapping = loader.load_cases(testcase_path)
|
||||
|
||||
project_mapping = tests_mapping["project_mapping"]
|
||||
self.assertIsInstance(project_mapping, dict)
|
||||
self.assertIn("PWD", project_mapping)
|
||||
self.assertIn("functions", project_mapping)
|
||||
self.assertIn("env", project_mapping)
|
||||
|
||||
testcases = tests_mapping["testcases"]
|
||||
self.assertIsInstance(testcases, list)
|
||||
self.assertEqual(len(testcases), 1)
|
||||
testcase_config = testcases[0]["config"]
|
||||
self.assertEqual(testcase_config["name"], "setup and reset all.")
|
||||
self.assertIn("path", testcases[0])
|
||||
|
||||
testcase_tests = testcases[0]["teststeps"]
|
||||
self.assertEqual(len(testcase_tests), 2)
|
||||
self.assertIn("api", testcase_tests[0])
|
||||
self.assertEqual(testcase_tests[0]["name"], "get token (setup)")
|
||||
self.assertIsInstance(testcase_tests[0]["variables"], dict)
|
||||
self.assertIn("api_def", testcase_tests[0])
|
||||
self.assertEqual(testcase_tests[0]["api_def"]["request"]["url"], "/api/get-token")
|
||||
|
||||
def test_testcase_parser(self):
|
||||
testcase_path = "tests/testcases/setup.yml"
|
||||
tests_mapping = loader.load_cases(testcase_path)
|
||||
|
||||
parsed_testcases = parser.parse_tests(tests_mapping)
|
||||
|
||||
self.assertEqual(len(parsed_testcases), 1)
|
||||
|
||||
self.assertIn("variables", parsed_testcases[0]["config"])
|
||||
self.assertEqual(len(parsed_testcases[0]["teststeps"]), 2)
|
||||
|
||||
test_dict1 = parsed_testcases[0]["teststeps"][0]
|
||||
self.assertEqual(test_dict1["name"], "get token (setup)")
|
||||
self.assertNotIn("api_def", test_dict1)
|
||||
self.assertEqual(test_dict1["variables"]["device_sn"], "TESTCASE_SETUP_XXX")
|
||||
self.assertEqual(test_dict1["request"]["url"], "/api/get-token")
|
||||
self.assertEqual(test_dict1["request"]["verify"], False)
|
||||
|
||||
test_dict2 = parsed_testcases[0]["teststeps"][1]
|
||||
self.assertEqual(test_dict2["request"]["verify"], False)
|
||||
|
||||
def test_testcase_add_tests(self):
|
||||
testcase_path = "tests/testcases/setup.yml"
|
||||
tests_mapping = loader.load_cases(testcase_path)
|
||||
|
||||
testcases = parser.parse_tests(tests_mapping)
|
||||
runner = HttpRunner()
|
||||
test_suite = runner._add_tests(testcases)
|
||||
|
||||
self.assertEqual(len(test_suite._tests), 1)
|
||||
teststeps = test_suite._tests[0].teststeps
|
||||
self.assertEqual(teststeps[0]["name"], "get token (setup)")
|
||||
self.assertEqual(teststeps[0]["variables"]["device_sn"], "TESTCASE_SETUP_XXX")
|
||||
self.assertIn("api", teststeps[0])
|
||||
|
||||
def test_testcase_complex_verify(self):
|
||||
testcase_path = "tests/testcases/create_user.yml"
|
||||
tests_mapping = loader.load_cases(testcase_path)
|
||||
testcases = parser.parse_tests(tests_mapping)
|
||||
teststeps = testcases[0]["teststeps"]
|
||||
|
||||
# testcases/setup.yml
|
||||
teststep0 = teststeps[0]
|
||||
self.assertEqual(teststep0["teststeps"][0]["request"]["verify"], False)
|
||||
self.assertEqual(teststep0["teststeps"][1]["request"]["verify"], False)
|
||||
|
||||
# testcases/create_user.yml
|
||||
teststep1 = teststeps[1]
|
||||
self.assertEqual(teststep1["teststeps"][0]["request"]["verify"], True)
|
||||
self.assertEqual(teststep1["teststeps"][1]["request"]["verify"], True)
|
||||
self.assertEqual(teststep1["teststeps"][2]["request"]["verify"], True)
|
||||
|
||||
def test_testcase_simple_run_suite(self):
|
||||
testcase_path = "tests/testcases/setup.yml"
|
||||
tests_mapping = loader.load_cases(testcase_path)
|
||||
testcases = parser.parse_tests(tests_mapping)
|
||||
runner = HttpRunner()
|
||||
test_suite = runner._add_tests(testcases)
|
||||
tests_results = runner._run_suite(test_suite)
|
||||
self.assertEqual(len(tests_results[0][1].records), 2)
|
||||
|
||||
def test_testcase_complex_run_suite(self):
|
||||
for testcase_path in [
|
||||
"tests/testcases/create_user.yml",
|
||||
"tests/testcases/create_user.json"
|
||||
]:
|
||||
tests_mapping = loader.load_cases(testcase_path)
|
||||
testcases = parser.parse_tests(tests_mapping)
|
||||
runner = HttpRunner()
|
||||
test_suite = runner._add_tests(testcases)
|
||||
tests_results = runner._run_suite(test_suite)
|
||||
self.assertEqual(len(tests_results[0][1].records), 2)
|
||||
|
||||
results = tests_results[0][1]
|
||||
self.assertEqual(
|
||||
results.records[0]["name"],
|
||||
"setup and reset all (override) for TESTCASE_CREATE_XXX."
|
||||
)
|
||||
self.assertEqual(
|
||||
results.records[1]["name"],
|
||||
"create user and check result."
|
||||
)
|
||||
|
||||
def test_testsuite_loader(self):
|
||||
testcase_path = "tests/testsuites/create_users.yml"
|
||||
tests_mapping = loader.load_cases(testcase_path)
|
||||
|
||||
project_mapping = tests_mapping["project_mapping"]
|
||||
self.assertIsInstance(project_mapping, dict)
|
||||
self.assertIn("PWD", project_mapping)
|
||||
self.assertIn("functions", project_mapping)
|
||||
self.assertIn("env", project_mapping)
|
||||
|
||||
testsuites = tests_mapping["testsuites"]
|
||||
self.assertIsInstance(testsuites, list)
|
||||
self.assertEqual(len(testsuites), 1)
|
||||
|
||||
self.assertIn("path", testsuites[0])
|
||||
testsuite_config = testsuites[0]["config"]
|
||||
self.assertEqual(testsuite_config["name"], "create users with uid")
|
||||
|
||||
testcases = testsuites[0]["testcases"]
|
||||
self.assertEqual(len(testcases), 2)
|
||||
self.assertIn("create user 1000 and check result.", testcases)
|
||||
testcase_tests = testcases["create user 1000 and check result."]
|
||||
self.assertIn("testcase_def", testcase_tests)
|
||||
self.assertEqual(testcase_tests["name"], "create user 1000 and check result.")
|
||||
self.assertIsInstance(testcase_tests["testcase_def"], dict)
|
||||
self.assertEqual(testcase_tests["testcase_def"]["config"]["name"], "create user and check result.")
|
||||
self.assertEqual(len(testcase_tests["testcase_def"]["teststeps"]), 2)
|
||||
self.assertEqual(
|
||||
testcase_tests["testcase_def"]["teststeps"][0]["name"],
|
||||
"setup and reset all (override) for $device_sn."
|
||||
)
|
||||
|
||||
def test_testsuite_parser(self):
|
||||
testcase_path = "tests/testsuites/create_users.yml"
|
||||
tests_mapping = loader.load_cases(testcase_path)
|
||||
|
||||
parsed_testcases = parser.parse_tests(tests_mapping)
|
||||
self.assertEqual(len(parsed_testcases), 2)
|
||||
self.assertEqual(len(parsed_testcases[0]["teststeps"]), 2)
|
||||
|
||||
testcase1 = parsed_testcases[0]["teststeps"][0]
|
||||
self.assertIn("setup and reset all (override)", testcase1["config"]["name"].raw_string)
|
||||
teststeps = testcase1["teststeps"]
|
||||
self.assertNotIn("testcase_def", testcase1)
|
||||
self.assertEqual(len(teststeps), 2)
|
||||
self.assertEqual(
|
||||
teststeps[0]["request"]["url"],
|
||||
"/api/get-token"
|
||||
)
|
||||
|
||||
def test_testsuite_add_tests(self):
|
||||
testcase_path = "tests/testsuites/create_users.yml"
|
||||
tests_mapping = loader.load_cases(testcase_path)
|
||||
|
||||
testcases = parser.parse_tests(tests_mapping)
|
||||
runner = HttpRunner()
|
||||
test_suite = runner._add_tests(testcases)
|
||||
|
||||
self.assertEqual(len(test_suite._tests), 2)
|
||||
tests = test_suite._tests[0].teststeps
|
||||
self.assertIn("setup and reset all (override)", tests[0]["config"]["name"].raw_string)
|
||||
|
||||
def test_testsuite_run_suite(self):
|
||||
testcase_path = "tests/testsuites/create_users.yml"
|
||||
tests_mapping = loader.load_cases(testcase_path)
|
||||
|
||||
testcases = parser.parse_tests(tests_mapping)
|
||||
|
||||
runner = HttpRunner()
|
||||
test_suite = runner._add_tests(testcases)
|
||||
tests_results = runner._run_suite(test_suite)
|
||||
|
||||
self.assertEqual(len(tests_results[0][1].records), 2)
|
||||
|
||||
results = tests_results[0][1]
|
||||
self.assertIn(
|
||||
"setup and reset all (override)",
|
||||
results.records[0]["name"]
|
||||
)
|
||||
self.assertEqual(
|
||||
results.records[1]["name"],
|
||||
"create user and check result."
|
||||
)
|
||||
@@ -1,112 +0,0 @@
|
||||
from tests.base import ApiServerUnittest
|
||||
|
||||
|
||||
class TestApiServer(ApiServerUnittest):
|
||||
|
||||
def setUp(self):
|
||||
super(TestApiServer, self).setUp()
|
||||
self.headers = self.get_authenticated_headers()
|
||||
self.reset_all()
|
||||
|
||||
def tearDown(self):
|
||||
super(TestApiServer, self).tearDown()
|
||||
|
||||
def test_index(self):
|
||||
resp = self.api_client.get(self.host)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
def reset_all(self):
|
||||
url = "%s/api/reset-all" % self.host
|
||||
return self.api_client.get(url, headers=self.headers)
|
||||
|
||||
def get_users(self):
|
||||
url = "%s/api/users" % self.host
|
||||
return self.api_client.get(url, headers=self.headers)
|
||||
|
||||
def create_user(self, uid, name, password):
|
||||
url = "%s/api/users/%d" % (self.host, uid)
|
||||
data = {
|
||||
'name': name,
|
||||
'password': password
|
||||
}
|
||||
return self.api_client.post(url, headers=self.headers, json=data)
|
||||
|
||||
def get_user(self, uid):
|
||||
url = "%s/api/users/%d" % (self.host, uid)
|
||||
return self.api_client.get(url, headers=self.headers)
|
||||
|
||||
def update_user(self, uid, name, password):
|
||||
url = "%s/api/users/%d" % (self.host, uid)
|
||||
data = {
|
||||
'name': name,
|
||||
'password': password
|
||||
}
|
||||
return self.api_client.put(url, headers=self.headers, json=data)
|
||||
|
||||
def delete_user(self, uid):
|
||||
url = "%s/api/users/%d" % (self.host, uid)
|
||||
return self.api_client.delete(url, headers=self.headers)
|
||||
|
||||
def test_reset_all(self):
|
||||
resp = self.reset_all()
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(True, resp.json()['success'])
|
||||
|
||||
def test_create_user_not_existed(self):
|
||||
resp = self.create_user(1000, 'user1', '123456')
|
||||
self.assertEqual(201, resp.status_code)
|
||||
self.assertEqual(True, resp.json()['success'])
|
||||
|
||||
def test_create_user_existed(self):
|
||||
resp = self.create_user(1000, 'user1', '123456')
|
||||
resp = self.create_user(1000, 'user1', '123456')
|
||||
self.assertEqual(500, resp.status_code)
|
||||
|
||||
def test_get_users_empty(self):
|
||||
resp = self.get_users()
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(resp.json()['count'], 0)
|
||||
|
||||
def test_get_users_not_empty(self):
|
||||
resp = self.create_user(1000, 'user1', '123456')
|
||||
resp = self.get_users()
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(resp.json()['count'], 1)
|
||||
|
||||
resp = self.create_user(1001, 'user2', '123456')
|
||||
resp = self.get_users()
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(resp.json()['count'], 2)
|
||||
|
||||
def test_get_user_not_existed(self):
|
||||
resp = self.get_user(1000)
|
||||
self.assertEqual(404, resp.status_code)
|
||||
self.assertEqual(resp.json()['success'], False)
|
||||
|
||||
def test_get_user_existed(self):
|
||||
self.create_user(1000, 'user1', '123456')
|
||||
resp = self.get_user(1000)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(resp.json()['success'], True)
|
||||
|
||||
def test_update_user_not_existed(self):
|
||||
resp = self.update_user(1000, 'user1', '123456')
|
||||
self.assertEqual(404, resp.status_code)
|
||||
self.assertEqual(resp.json()['success'], False)
|
||||
|
||||
def test_update_user_existed(self):
|
||||
self.create_user(1000, 'user1', '123456')
|
||||
resp = self.update_user(1000, 'user2', '123456')
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(resp.json()['data']['name'], 'user2')
|
||||
|
||||
def test_delete_user_not_existed(self):
|
||||
resp = self.delete_user(1000)
|
||||
self.assertEqual(404, resp.status_code)
|
||||
self.assertEqual(resp.json()['success'], False)
|
||||
|
||||
def test_delete_user_existed(self):
|
||||
self.create_user(1000, 'leo', '123456')
|
||||
resp = self.delete_user(1000)
|
||||
self.assertEqual(200, resp.status_code)
|
||||
self.assertEqual(resp.json()['success'], True)
|
||||
@@ -1,80 +0,0 @@
|
||||
from httprunner.client import HttpSession
|
||||
from tests.api_server import HTTPBIN_SERVER
|
||||
from tests.base import ApiServerUnittest
|
||||
|
||||
|
||||
class TestHttpClient(ApiServerUnittest):
|
||||
def setUp(self):
|
||||
super(TestHttpClient, self).setUp()
|
||||
self.api_client = HttpSession()
|
||||
self.headers = self.get_authenticated_headers()
|
||||
self.reset_all()
|
||||
|
||||
def tearDown(self):
|
||||
super(TestHttpClient, self).tearDown()
|
||||
|
||||
def reset_all(self):
|
||||
url = "%s/api/reset-all" % self.host
|
||||
headers = self.get_authenticated_headers()
|
||||
return self.api_client.get(url, headers=headers)
|
||||
|
||||
def test_request_with_full_url(self):
|
||||
url = "%s/api/users/1000" % self.host
|
||||
data = {
|
||||
'name': 'user1',
|
||||
'password': '123456'
|
||||
}
|
||||
resp = self.api_client.post(url, json=data, headers=self.headers)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
self.assertEqual(True, resp.json()['success'])
|
||||
|
||||
def test_request_without_base_url(self):
|
||||
url = "{}/api/users/1000".format(self.host)
|
||||
data = {
|
||||
'name': 'user1',
|
||||
'password': '123456'
|
||||
}
|
||||
resp = self.api_client.post(url, json=data, headers=self.headers)
|
||||
self.assertEqual(201, resp.status_code)
|
||||
self.assertEqual(True, resp.json()['success'])
|
||||
|
||||
def test_request_post_data(self):
|
||||
url = "{}/api/users/1000".format(self.host)
|
||||
data = {
|
||||
'name': 'user1',
|
||||
'password': '123456'
|
||||
}
|
||||
resp = self.api_client.post(url, json=data, headers=self.headers)
|
||||
# b'{"name": "user1", "password": "123456"}'
|
||||
self.assertIn(b'"name": "user1"', resp.request.body)
|
||||
self.assertIn(b'"password": "123456"', resp.request.body)
|
||||
resp = self.api_client.post(url, data=data, headers=self.headers)
|
||||
# name=user1&password=123456
|
||||
self.assertIn("name=user1", resp.request.body)
|
||||
self.assertIn("&", resp.request.body)
|
||||
self.assertIn("password=123456", resp.request.body)
|
||||
|
||||
def test_request_with_cookies(self):
|
||||
url = "{}/api/users/1000".format(self.host)
|
||||
cookies = {
|
||||
"a": "1",
|
||||
"b": "2"
|
||||
}
|
||||
resp = self.api_client.get(url, cookies=cookies, headers=self.headers)
|
||||
self.assertEqual(resp.request._cookies["a"], "1")
|
||||
self.assertEqual(resp.request._cookies["b"], "2")
|
||||
|
||||
def test_request_redirect(self):
|
||||
url = "{}/redirect-to?url=https%3A%2F%2Fgithub.com&status_code=302".format(HTTPBIN_SERVER)
|
||||
cookies = {
|
||||
"a": "1",
|
||||
"b": "2"
|
||||
}
|
||||
resp = self.api_client.get(url, cookies=cookies, headers=self.headers, verify=False)
|
||||
raw_request = resp.history[0].request
|
||||
self.assertEqual(raw_request._cookies["a"], "1")
|
||||
self.assertEqual(raw_request._cookies["b"], "2")
|
||||
redirect_request = resp.request
|
||||
self.assertEqual(redirect_request.url, "https://github.com")
|
||||
self.assertEqual(redirect_request._cookies["a"], "1")
|
||||
self.assertEqual(redirect_request._cookies["b"], "2")
|
||||
@@ -1,388 +0,0 @@
|
||||
import requests
|
||||
|
||||
from httprunner import exceptions, response
|
||||
from tests.api_server import HTTPBIN_SERVER
|
||||
from tests.base import ApiServerUnittest
|
||||
|
||||
|
||||
class TestResponse(ApiServerUnittest):
|
||||
|
||||
def test_parse_response_object_json(self):
|
||||
url = "http://127.0.0.1:5000/api/users"
|
||||
resp = requests.get(url)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
self.assertTrue(hasattr(resp_obj, 'status_code'))
|
||||
self.assertTrue(hasattr(resp_obj, 'headers'))
|
||||
self.assertTrue(hasattr(resp_obj, 'content'))
|
||||
self.assertIn('Content-Type', resp_obj.headers)
|
||||
self.assertIn('Content-Length', resp_obj.headers)
|
||||
self.assertIn('success', resp_obj.json)
|
||||
|
||||
def test_parse_response_object_content(self):
|
||||
url = "http://127.0.0.1:5000/"
|
||||
resp = requests.get(url)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
self.assertEqual(bytes, type(resp_obj.content))
|
||||
|
||||
def test_extract_response_status_code(self):
|
||||
resp = requests.get(url="{}/status/200".format(HTTPBIN_SERVER))
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_status_code": "status_code"}
|
||||
]
|
||||
extract_binds_dict = resp_obj.extract_response(extract_binds_list)
|
||||
|
||||
self.assertEqual(
|
||||
extract_binds_dict["resp_status_code"],
|
||||
200
|
||||
)
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_status_code": "status_code.xx"}
|
||||
]
|
||||
with self.assertRaises(exceptions.ParamsError):
|
||||
resp_obj.extract_response(extract_binds_list)
|
||||
|
||||
def test_extract_response_encoding_ok_reason_url(self):
|
||||
resp = requests.get(url="{}/status/200".format(HTTPBIN_SERVER))
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_encoding": "encoding"},
|
||||
{"resp_ok": "ok"},
|
||||
{"resp_reason": "reason"},
|
||||
{"resp_url": "url"}
|
||||
]
|
||||
extract_binds_dict = resp_obj.extract_response(extract_binds_list)
|
||||
|
||||
self.assertEqual(extract_binds_dict["resp_encoding"], "utf-8")
|
||||
self.assertEqual(extract_binds_dict["resp_ok"], True)
|
||||
self.assertEqual(extract_binds_dict["resp_reason"], "OK")
|
||||
self.assertEqual(extract_binds_dict["resp_url"], "{}/status/200".format(HTTPBIN_SERVER))
|
||||
|
||||
extract_binds_list = [{"resp_encoding": "encoding.xx"}]
|
||||
with self.assertRaises(exceptions.ParamsError):
|
||||
resp_obj.extract_response(extract_binds_list)
|
||||
|
||||
extract_binds_list = [{"resp_ok": "ok.xx"}]
|
||||
with self.assertRaises(exceptions.ParamsError):
|
||||
resp_obj.extract_response(extract_binds_list)
|
||||
|
||||
extract_binds_list = [{"resp_reason": "reason.xx"}]
|
||||
with self.assertRaises(exceptions.ParamsError):
|
||||
resp_obj.extract_response(extract_binds_list)
|
||||
|
||||
extract_binds_list = [{"resp_url": "url.xx"}]
|
||||
with self.assertRaises(exceptions.ParamsError):
|
||||
resp_obj.extract_response(extract_binds_list)
|
||||
|
||||
def test_extract_response_cookies(self):
|
||||
resp = requests.get(
|
||||
url="{}/cookies".format(HTTPBIN_SERVER),
|
||||
headers={
|
||||
"accept": "application/json"
|
||||
}
|
||||
)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_cookies": "cookies"}
|
||||
]
|
||||
extract_binds_dict = resp_obj.extract_response(extract_binds_list)
|
||||
self.assertEqual(
|
||||
extract_binds_dict["resp_cookies"],
|
||||
{}
|
||||
)
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_cookies": "cookies.xx"}
|
||||
]
|
||||
with self.assertRaises(exceptions.ExtractFailure):
|
||||
resp_obj.extract_response(extract_binds_list)
|
||||
|
||||
def test_extract_response_elapsed(self):
|
||||
resp = requests.post(
|
||||
url="{}/anything".format(HTTPBIN_SERVER),
|
||||
json={
|
||||
'success': False,
|
||||
"person": {
|
||||
"name": {
|
||||
"first_name": "Leo",
|
||||
"last_name": "Lee",
|
||||
},
|
||||
"age": 29,
|
||||
"cities": ["Guangzhou", "Shenzhen"]
|
||||
}
|
||||
}
|
||||
)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_elapsed": "elapsed"}
|
||||
]
|
||||
with self.assertRaises(exceptions.ParamsError):
|
||||
resp_obj.extract_response(extract_binds_list)
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_elapsed_microseconds": "elapsed.microseconds"},
|
||||
{"resp_elapsed_seconds": "elapsed.seconds"},
|
||||
{"resp_elapsed_days": "elapsed.days"},
|
||||
{"resp_elapsed_total_seconds": "elapsed.total_seconds"}
|
||||
]
|
||||
extract_binds_dict = resp_obj.extract_response(extract_binds_list)
|
||||
self.assertGreater(extract_binds_dict["resp_elapsed_microseconds"], 1000)
|
||||
self.assertLess(extract_binds_dict["resp_elapsed_seconds"], 60)
|
||||
self.assertEqual(extract_binds_dict["resp_elapsed_days"], 0)
|
||||
self.assertGreater(extract_binds_dict["resp_elapsed_total_seconds"], 0)
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_elapsed": "elapsed.years"}
|
||||
]
|
||||
with self.assertRaises(exceptions.ParamsError):
|
||||
resp_obj.extract_response(extract_binds_list)
|
||||
|
||||
def test_extract_response_headers(self):
|
||||
resp = requests.get(url="{}/status/200".format(HTTPBIN_SERVER))
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_headers": "headers"},
|
||||
{"resp_headers_content_type": "headers.Content-Type"},
|
||||
{"resp_headers_content_type_lowercase": "headers.content-type"}
|
||||
]
|
||||
extract_binds_dict = resp_obj.extract_response(extract_binds_list)
|
||||
self.assertIn("Content-Type", extract_binds_dict["resp_headers"])
|
||||
self.assertIn("text/html", extract_binds_dict["resp_headers_content_type"])
|
||||
self.assertIn("text/html", extract_binds_dict["resp_headers_content_type_lowercase"])
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_headers_xxx": "headers.xxx"}
|
||||
]
|
||||
with self.assertRaises(exceptions.ExtractFailure):
|
||||
resp_obj.extract_response(extract_binds_list)
|
||||
|
||||
def test_extract_response_body_json(self):
|
||||
resp = requests.post(
|
||||
url="{}/anything".format(HTTPBIN_SERVER),
|
||||
json={
|
||||
'success': False,
|
||||
"person": {
|
||||
"name": {
|
||||
"first_name": "Leo",
|
||||
"last_name": "Lee",
|
||||
},
|
||||
"age": 29,
|
||||
"cities": ["Guangzhou", "Shenzhen"]
|
||||
}
|
||||
}
|
||||
)
|
||||
# resp.json()
|
||||
# {
|
||||
# "args": {},
|
||||
# "data": "{\"success\": false, \"person\": {\"name\": {\"first_name\": \"Leo\", \"last_name\": \"Lee\"}, \"age\": 29, \"cities\": [\"Guangzhou\", \"Shenzhen\"]}}",
|
||||
# "files": {},
|
||||
# "form": {},
|
||||
# "headers": {
|
||||
# "Accept": "*/*",
|
||||
# "Accept-Encoding": "gzip, deflate",
|
||||
# "Connection": "keep-alive",
|
||||
# "Content-Length": "129",
|
||||
# "Content-Type": "application/json",
|
||||
# "Host": HTTPBIN_SERVER,
|
||||
# "User-Agent": "python-requests/2.18.4"
|
||||
# },
|
||||
# "json": {
|
||||
# "person": {
|
||||
# "age": 29,
|
||||
# "cities": [
|
||||
# "Guangzhou",
|
||||
# "Shenzhen"
|
||||
# ],
|
||||
# "name": {
|
||||
# "first_name": "Leo",
|
||||
# "last_name": "Lee"
|
||||
# }
|
||||
# },
|
||||
# "success": false
|
||||
# },
|
||||
# "method": "POST",
|
||||
# "origin": "127.0.0.1",
|
||||
# "url": "{}/anything".format(HTTPBIN_SERVER)
|
||||
# }
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_headers_content_type": "headers.content-type"},
|
||||
{"resp_content_body_success": "json.json.success"},
|
||||
{"resp_content_content_success": "content.json.success"},
|
||||
{"resp_content_text_success": "text.json.success"},
|
||||
{"resp_content_person_first_name": "content.json.person.name.first_name"},
|
||||
{"resp_content_cities_1": "content.json.person.cities.1"}
|
||||
]
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
extract_binds_dict = resp_obj.extract_response(extract_binds_list)
|
||||
|
||||
self.assertEqual(
|
||||
extract_binds_dict["resp_headers_content_type"],
|
||||
"application/json"
|
||||
)
|
||||
self.assertEqual(
|
||||
extract_binds_dict["resp_content_body_success"],
|
||||
False
|
||||
)
|
||||
self.assertEqual(
|
||||
extract_binds_dict["resp_content_content_success"],
|
||||
False
|
||||
)
|
||||
self.assertEqual(
|
||||
extract_binds_dict["resp_content_text_success"],
|
||||
False
|
||||
)
|
||||
self.assertEqual(
|
||||
extract_binds_dict["resp_content_person_first_name"],
|
||||
"Leo"
|
||||
)
|
||||
self.assertEqual(
|
||||
extract_binds_dict["resp_content_cities_1"],
|
||||
"Shenzhen"
|
||||
)
|
||||
|
||||
def test_extract_response_body_html(self):
|
||||
resp = requests.get(url=HTTPBIN_SERVER)
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_content": "content"}
|
||||
]
|
||||
extract_binds_dict = resp_obj.extract_response(extract_binds_list)
|
||||
|
||||
self.assertIsInstance(extract_binds_dict["resp_content"], str)
|
||||
self.assertIn("httpbin.org", extract_binds_dict["resp_content"])
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_content": "content.xxx"}
|
||||
]
|
||||
with self.assertRaises(exceptions.ExtractFailure):
|
||||
resp_obj.extract_response(extract_binds_list)
|
||||
|
||||
def test_extract_response_others(self):
|
||||
resp = requests.get(url="{}/status/200".format(HTTPBIN_SERVER))
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_others_encoding": "encoding"},
|
||||
{"resp_others_history": "history"}
|
||||
]
|
||||
with self.assertRaises(exceptions.ParamsError):
|
||||
resp_obj.extract_response(extract_binds_list)
|
||||
|
||||
def test_extract_response_fail(self):
|
||||
resp = requests.post(
|
||||
url="{}/anything".format(HTTPBIN_SERVER),
|
||||
json={
|
||||
'success': False,
|
||||
"person": {
|
||||
"name": {
|
||||
"first_name": "Leo",
|
||||
"last_name": "Lee",
|
||||
},
|
||||
"age": 29,
|
||||
"cities": ["Guangzhou", "Shenzhen"]
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_content_dict_key_error": "content.not_exist"}
|
||||
]
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
|
||||
with self.assertRaises(exceptions.ExtractFailure):
|
||||
resp_obj.extract_response(extract_binds_list)
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_content_list_index_error": "content.person.cities.3"}
|
||||
]
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
|
||||
with self.assertRaises(exceptions.ExtractFailure):
|
||||
resp_obj.extract_response(extract_binds_list)
|
||||
|
||||
def test_extract_response_json_string(self):
|
||||
resp = requests.post(
|
||||
url="{}/anything".format(HTTPBIN_SERVER),
|
||||
data="abc"
|
||||
)
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_content_body": "content.data"}
|
||||
]
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
|
||||
extract_binds_dict = resp_obj.extract_response(extract_binds_list)
|
||||
self.assertEqual(
|
||||
extract_binds_dict["resp_content_body"],
|
||||
"abc"
|
||||
)
|
||||
|
||||
def test_extract_text_response(self):
|
||||
resp = requests.post(
|
||||
url="{}/anything".format(HTTPBIN_SERVER),
|
||||
data="LB123abcRB789"
|
||||
)
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_content_key1": "LB123(.*)RB789"},
|
||||
{"resp_content_key2": "LB[\d]*(.*)RB[\d]*"},
|
||||
{"resp_content_key3": "LB[\d]*(.*)9"}
|
||||
]
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
|
||||
extract_binds_dict = resp_obj.extract_response(extract_binds_list)
|
||||
self.assertEqual(
|
||||
extract_binds_dict["resp_content_key1"],
|
||||
"abc"
|
||||
)
|
||||
self.assertEqual(
|
||||
extract_binds_dict["resp_content_key2"],
|
||||
"abc"
|
||||
)
|
||||
self.assertEqual(
|
||||
extract_binds_dict["resp_content_key3"],
|
||||
"abcRB78"
|
||||
)
|
||||
|
||||
def test_extract_text_response_exception(self):
|
||||
resp = requests.post(
|
||||
url="{}/anything".format(HTTPBIN_SERVER),
|
||||
data="LB123abcRB789"
|
||||
)
|
||||
extract_binds_list = [
|
||||
{"resp_content_key1": "LB123.*RB789"}
|
||||
]
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
with self.assertRaises(exceptions.ParamsError):
|
||||
resp_obj.extract_response(extract_binds_list)
|
||||
|
||||
def test_extract_response_empty(self):
|
||||
resp = requests.post(
|
||||
url="{}/anything".format(HTTPBIN_SERVER),
|
||||
data="abc"
|
||||
)
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_content_body": "content.data"}
|
||||
]
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
extract_binds_dict = resp_obj.extract_response(extract_binds_list)
|
||||
self.assertEqual(
|
||||
extract_binds_dict["resp_content_body"],
|
||||
'abc'
|
||||
)
|
||||
|
||||
extract_binds_list = [
|
||||
{"resp_content_body": "content.data.def"}
|
||||
]
|
||||
resp_obj = response.ResponseObject(resp)
|
||||
with self.assertRaises(exceptions.ExtractFailure):
|
||||
resp_obj.extract_response(extract_binds_list)
|
||||
@@ -1,7 +0,0 @@
|
||||
import unittest
|
||||
|
||||
from httprunner import validator
|
||||
|
||||
|
||||
class TestValidator(unittest.TestCase):
|
||||
pass
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"id": "create_user",
|
||||
"variables": {
|
||||
"device_sn": "TESTCASE_CREATE_XXX",
|
||||
"uid": 9001
|
||||
},
|
||||
"output": [
|
||||
"session_token"
|
||||
],
|
||||
"base_url": "http://127.0.0.1:5000",
|
||||
"name": "create user and check result."
|
||||
},
|
||||
"teststeps": [
|
||||
{
|
||||
"testcase": "testcases/setup.yml",
|
||||
"extract": [
|
||||
"session_token"
|
||||
],
|
||||
"name": "setup and reset all (override) for $device_sn."
|
||||
},
|
||||
{
|
||||
"testcase": "testcases/deps/check_and_create.yml",
|
||||
"variables": {
|
||||
"token": "$session_token"
|
||||
},
|
||||
"name": "create user and check result."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
config:
|
||||
name: "create user and check result."
|
||||
id: create_user
|
||||
base_url: "http://127.0.0.1:5000"
|
||||
variables:
|
||||
uid: 9001
|
||||
device_sn: "TESTCASE_CREATE_XXX"
|
||||
export:
|
||||
- session_token
|
||||
|
||||
teststeps:
|
||||
-
|
||||
name: setup and reset all (override) for $device_sn.
|
||||
testcase: testcases/setup.yml
|
||||
extract:
|
||||
- session_token
|
||||
-
|
||||
name: create user and check result.
|
||||
variables:
|
||||
token: $session_token
|
||||
testcase: testcases/deps/check_and_create.yml
|
||||
@@ -1,40 +0,0 @@
|
||||
config:
|
||||
name: "create user and check result."
|
||||
id: create_and_check
|
||||
base_url: "http://127.0.0.1:5000"
|
||||
variables:
|
||||
uid: 9001
|
||||
device_sn: "TESTCASE_CREATE_XXX"
|
||||
|
||||
teststeps:
|
||||
-
|
||||
name: make sure user $uid does not exist
|
||||
api: api/get_user.yml
|
||||
variables:
|
||||
uid: $uid
|
||||
token: $token
|
||||
validate:
|
||||
- eq: ["status_code", 404]
|
||||
- eq: ["content.success", false]
|
||||
|
||||
-
|
||||
name: create user $uid for $device_sn
|
||||
api: api/create_user.yml
|
||||
variables:
|
||||
user_name: "user1"
|
||||
user_password: "123456"
|
||||
uid: $uid
|
||||
token: $token
|
||||
validate:
|
||||
- eq: ["status_code", 201]
|
||||
- eq: ["content.success", true]
|
||||
|
||||
-
|
||||
name: check if user $uid exists
|
||||
api: api/get_user.yml
|
||||
variables:
|
||||
uid: $uid
|
||||
token: $token
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
- eq: ["content.success", true]
|
||||
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"name": "setup and reset all.",
|
||||
"base_url": "http://127.0.0.1:5000",
|
||||
"variables": {
|
||||
"device_sn": "TESTCASE_SETUP_XXX",
|
||||
"app_version": "2.8.6",
|
||||
"os_platform": "ios",
|
||||
"user_agent": "iOS/10.3"
|
||||
},
|
||||
"id": "setup_and_reset",
|
||||
"verify": false,
|
||||
"output": [
|
||||
"session_token"
|
||||
]
|
||||
},
|
||||
"teststeps": [
|
||||
{
|
||||
"name": "get token (setup)",
|
||||
"api": "api/get_token.yml",
|
||||
"variables": {
|
||||
"device_sn": "$device_sn",
|
||||
"app_version": "2.8.6",
|
||||
"os_platform": "ios",
|
||||
"user_agent": "iOS/10.3"
|
||||
},
|
||||
"extract": {
|
||||
"session_token": "content.token"
|
||||
},
|
||||
"validate": [
|
||||
{"eq": ["status_code", 200]},
|
||||
{"len_eq": ["content.token", 16]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "reset all users",
|
||||
"api": "api/reset_all.yml",
|
||||
"variables": {
|
||||
"token": "$session_token"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
config:
|
||||
name: "setup and reset all."
|
||||
id: setup_and_reset
|
||||
variables:
|
||||
user_agent: 'iOS/10.3'
|
||||
device_sn: "TESTCASE_SETUP_XXX"
|
||||
os_platform: 'ios'
|
||||
app_version: '2.8.6'
|
||||
base_url: "http://127.0.0.1:5000"
|
||||
verify: False
|
||||
export:
|
||||
- session_token
|
||||
|
||||
teststeps:
|
||||
-
|
||||
name: get token (setup)
|
||||
api: api/get_token.yml
|
||||
variables:
|
||||
user_agent: 'iOS/10.3'
|
||||
device_sn: $device_sn
|
||||
os_platform: 'ios'
|
||||
app_version: '2.8.6'
|
||||
extract:
|
||||
session_token: content.token
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
- len_eq: ["content.token", 16]
|
||||
-
|
||||
name: reset all users
|
||||
api: api/reset_all.yml
|
||||
variables:
|
||||
token: $session_token
|
||||
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"variables": {
|
||||
"device_sn": "${gen_random_string(15)}",
|
||||
"var_b": "$var_a",
|
||||
"var_a": "${gen_random_string(5)}"
|
||||
},
|
||||
"name": "create users with uid",
|
||||
"base_url": "http://127.0.0.1:5000"
|
||||
},
|
||||
"testcases": [
|
||||
{
|
||||
"name": "create user 1000 and check result.",
|
||||
"testcase": "testcases/create_user.yml",
|
||||
"variables": {
|
||||
"var_d": "$var_c",
|
||||
"var_c": "${gen_random_string(5)}",
|
||||
"uid": 1000
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "create user 1001 and check result.",
|
||||
"testcase": "testcases/create_user.yml",
|
||||
"variables": {
|
||||
"var_d": "$var_c",
|
||||
"var_c": "${gen_random_string(5)}",
|
||||
"uid": 1001
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
config:
|
||||
name: create users with uid
|
||||
variables:
|
||||
device_sn: ${gen_random_string(15)}
|
||||
var_a: ${gen_random_string(5)}
|
||||
var_b: $var_a
|
||||
base_url: "http://127.0.0.1:5000"
|
||||
|
||||
testcases:
|
||||
-
|
||||
name: create user 1000 and check result.
|
||||
testcase: testcases/create_user.yml
|
||||
variables:
|
||||
uid: 1000
|
||||
var_c: ${gen_random_string(5)}
|
||||
var_d: $var_c
|
||||
|
||||
-
|
||||
name: create user 1001 and check result.
|
||||
testcase: testcases/create_user.yml
|
||||
variables:
|
||||
uid: 1001
|
||||
var_c: ${gen_random_string(5)}
|
||||
var_d: $var_c
|
||||
@@ -1,16 +0,0 @@
|
||||
config:
|
||||
name: create users with parameters
|
||||
variables:
|
||||
device_sn: ${gen_random_string(15)}
|
||||
base_url: "http://127.0.0.1:5000"
|
||||
|
||||
testcases:
|
||||
-
|
||||
name: create user $uid and check result for $device_sn.
|
||||
testcase: testcases/create_user.yml
|
||||
variables:
|
||||
uid: 1000
|
||||
device_sn: TESTSUITE_XXX
|
||||
parameters:
|
||||
uid: [101, 102, 103]
|
||||
device_sn: [TESTSUITE_X1, TESTSUITE_X2]
|
||||
Reference in New Issue
Block a user