change: remove unittests with flask mock server

This commit is contained in:
debugtalk
2020-05-15 23:15:03 +08:00
parent 0e5ca838fb
commit 94757c7bdd
50 changed files with 2 additions and 3008 deletions

View File

@@ -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
View File

@@ -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"},

View File

@@ -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"

View File

@@ -1,3 +0,0 @@
UserName=debugtalk
Password=123456
PROJECT_KEY=ABCDEFGH

View File

View File

@@ -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]

View File

@@ -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]

View File

@@ -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()}"]

View File

@@ -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"]

View File

@@ -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]

View File

@@ -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]

View File

@@ -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]

View File

@@ -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]

View File

@@ -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

View File

@@ -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

View File

@@ -1,4 +0,0 @@
username,password
test1,111111
test2,222222
test3,333333
1 username password
2 test1 111111
3 test2 222222
4 test3 333333

View File

@@ -1,4 +0,0 @@
app_version
2.8.5
2.8.6
1 app_version
2 2.8.5
3 2.8.6

View File

@@ -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]

View File

@@ -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"]

View File

@@ -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}

View File

@@ -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}

View File

@@ -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}

View File

@@ -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}

View File

@@ -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}

View File

@@ -1,4 +0,0 @@
UserName=test
Password=654321
PROJECT_KEY=AAABBBCCC
content_type=application/json; charset=UTF-8

View File

@@ -1,4 +0,0 @@
user_agent
iOS/10.1
iOS/10.2
iOS/10.3
1 user_agent
2 iOS/10.1
3 iOS/10.2
4 iOS/10.3

View File

@@ -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
}

View File

@@ -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"]

View File

@@ -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]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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]

View File

@@ -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"]

View File

@@ -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]

View File

@@ -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"]

View File

@@ -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'"

View File

@@ -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("&#34;person&#34;: &#34;&lt;img src=x onerror=alert(1)&gt;&#34;"),
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."
)

View File

@@ -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)

View File

@@ -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")

View File

@@ -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)

View File

View File

@@ -1,7 +0,0 @@
import unittest
from httprunner import validator
class TestValidator(unittest.TestCase):
pass

View File

@@ -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."
}
]
}

View File

@@ -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

View File

@@ -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]

View File

@@ -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"
}
}
]
}

View File

@@ -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

View File

@@ -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
}
}
]
}

View File

@@ -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

View File

@@ -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]