Cách Thực Hiện
Tình Huống Yêu Cầu:
- Công ty sử dụng chữ ký số cho các giao diện microservices. Khi sử dụng Postman để kiểm thử, mỗi lần đều cần chỉnh sửa mã nguồn để tắt tạm thời việc kiểm tra chữ ký, nhưng điều này làm cho các microservices khác không thể gọi dịch vụ đó.
- Các tham số giao diện lấy từ ELK cần được định dạng JSON. Thông thường, tôi sử dụng Sublime Text + PrettyJson plugin, nhưng với các giao diện dạng form, cần phải sao chép từng tham số và giá trị, rất bất tiện.
Nguyên Lý Thực Hiện:
- Sublime Text 3 có thể tùy chỉnh hệ thống biên dịch.
- Python xử lý dữ liệu JSON một cách dễ dàng.
- Sử dụng Python để thực hiện thuật toán chữ ký.
- Thư viện requests để gửi yêu cầu giao diện.
Mục Tiêu:
- Sử dụng tệp dữ liệu JSON để điều khiển, hỗ trợ nhiều giao diện trong một tệp JSON.
- Hỗ trợ các phương thức GET/POST/DELETE/...
- Hỗ trợ các yêu cầu dạng form và JSON.
- Hỗ trợ headers, cookies, params, data, files, timeout.
- Hỗ trợ phụ thuộc session và biến trung gian.
Định Dạng Tệp Dữ Liệu:
- Yêu cầu GET:
{ "url": "http://127.0.0.1:5000/api/user/logout/?name=John" }hoặc{ "url": "http://127.0.0.1:5000/api/user/logout/", "params": {"name": "John"} } - Yêu cầu POST dạng form:
{ "url": "http://127.0.0.1:5000/api/user/login/", "data": {"name": "John", "password": "123456"} } - Yêu cầu dạng JSON:
{ "url": "http://127.0.0.1:5000/api/user/reg/", "headers": {"Content-Type": "application/json"}, "data": { "name": "John991", "password": "123456"} }hoặc{ "url": "http://127.0.0.1:5000/api/user/reg/", "type": "json", "data": { "name": "John991", "password": "123456"} } - Định dạng xác nhận (ASSERT):
{ "url": "http://127.0.0.1:5000/api/user/login/", "data": {"name": "John", "password": "123456"}, "ASSERT": ["response.status_code == 200", "'success' in response.text"] } - Cần chữ ký (SIGN):
{ "url": "http://127.0.0.1:5000/api/user/delUser/", "type": "json", "data": {"name": "John"}, "SIGN": true } - Nhiều giao diện, phụ thuộc session, và biến trung gian (STORE):
[ { "url": "http://127.0.0.1:5000/api/user/getToken/", "method": "get", "params": {"appid": "136425"}, "STORE": {"token": "response.text.split('=')[1]"} }, { "url": "http://127.0.0.1:5000/api/user/updateUser/?token=%(token)s", "headers": {"Content-Type": "application/json"}, "data": {"name": "John", "password": "123456"} } ]
Thực Hiện Công Cụ:
sign.py
import hashlib
appid = 'user'
appsecret = 'NTA3ZTU2ZWM5ZmVkYTVmMDBkMDM3YTBi'
def md5(str):
m = hashlib.md5()
m.update(str.encode('utf8'))
return m.hexdigest()
def makeSign(params):
if not isinstance(params, dict):
print("Định dạng tham số không chính xác, phải là kiểu dictionary")
return None
if 'sign' in params:
params.pop('sign')
sign = ''
for key in sorted(params.keys()):
sign += f"{key}={str(params[key])}&"
sign = md5(sign + 'appsecret=' + appsecret)
params['sign'] = sign
return params
post_json.py
import json
import os
import requests
from sign import makeSign
timeout = 10
def postJson(path, timeout=60):
try:
with open(path, encoding='utf-8') as f:
apis = json.load(f)
except IOError as e:
print(e)
except json.decoder.JSONDecodeError:
print("Định dạng tệp JSON không chính xác")
if isinstance(apis, dict):
apis = [apis]
session = requests.session()
for api in apis:
str_api = json.dumps(api)
if '%' in str_api:
api = json.loads(str_api % globals())
url = api.get('url')
method = api.get('method')
type = api.get('type')
headers = api.get('headers')
cookies = api.get('cookies')
params = api.get('params')
data = api.get('data')
files = api.get('files')
_sign = api.get('SIGN')
_store = api.get('STORE')
_assert = api.get('ASSERT')
if _sign:
data = makeSign(data)
if type and type == 'json' or headers and 'json' in json.dumps(headers):
data = json.dumps(data)
if not method or method.lower() == 'post':
response = session.post(url=url, headers=headers, cookies=cookies, params=params, data=data, files=files, timeout=timeout)
elif not data or method.lower() == 'get':
response = session.get(url=url, headers=headers, cookies=cookies, params=params, timeout=timeout)
elif method.lower() == 'delete':
response = session.delete(url=url, headers=headers, cookies=cookies, params=params, data=data, files=files, timeout=timeout)
elif method.lower() == 'put':
response = session.put(url=url, headers=headers, cookies=cookies, params=params, data=data, files=files, timeout=timeout)
elif method.lower() == 'patch':
response = session.patch(url=url, headers=headers, cookies=cookies, params=params, data=data, files=files, timeout=timeout)
elif method.lower() == 'head':
response = session.head(url=url, headers=headers, cookies=cookies, params=params, data=data, files=files, timeout=timeout)
else:
print("Phương thức không được hỗ trợ")
if _store:
for key in _store:
globals()[key] = eval(_store[key])
try:
response_text = json.dumps(response.json(), ensure_ascii=False, indent=2)
except json.decoder.JSONDecodeError:
try:
response_text = response.text
except UnicodeEncodeError:
response_text = response.content
status = "PASS"
if _assert:
assert_results = []
for item in _assert:
try:
assert eval(item)
assert_results.append(f"PASS: <{item}>")
except AssertionError:
assert_results.append(f"FAIL: <{item}>")
status = "FAIL"
except Exception as e:
assert_results.append(f"ERROR: <{item}>\n{repr(e)}")
status = "ERROR"
print("=" * 80)
print("Yêu cầu:")
print(f"Url: {url}\nHeaders: {headers}\nData: {data if isinstance(data, str) else json.dumps(data)}")
print("-" * 80)
print("Phản hồi:")
print(response_text)
if _assert:
print("-" * 80)
print("Xác nhận:")
for assert_result in assert_results:
print(assert_result)
def main():
if len(sys.argv) != 2:
print("Thiếu tham số: tệp JSON")
else:
postJson(sys.argv[1])
if __name__ == "__main__":
main()
Tích Hợp Vào Sublime Text
- Sublime Text3 -> Tools -> Build System -> New Build System
- Sao chép đoạn mã sau, thay đổi đường dẫn Python và post_json.py, lưu thành PostJson.sublime-build
- Hệ thống Windows:
{ "cmd": ["python3", "C:/PostJson/post_json.py", "$file"], "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)", "selector": "source.json", "encoding": "cp936" } - Hệ thống Linux & Mac:
{ "cmd": ["/Library/Frameworks/Python.framework/Versions/3.6/bin/python3", "-u", "/Users/apple/Applications/PostJson/post_json.py", "$file"], "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)", "selector": "source.json", "env": {"PYTHONIOENCODING": "utf8"} }
Cách Sử Dụng
- Tạo tệp JSON mới trong Sublime Text3 và lưu dưới dạng *.json
{ "url": "http://127.0.0.1:5000/api/user/login/", "data": {"name": "John", "password": "123456"} } - Nhấn Ctrl + B để chạy
Chức Năng Mở Rộng
- Khám phá và thực thi hàng loạt test case
- Tạo báo cáo
- Tham số dòng lệnh:
- verbose: mức hiển thị: 1. Chỉ hiển thị kết quả test case 2. Chỉ hiển thị văn bản phản hồi (mặc định) 3. Hiển thị yêu cầu, phản hồi và thông tin xác nhận
- host: chỉ định địa chỉ máy chủ
- env: chỉ định môi trường
- timeout: chỉ định timeout
- html: chỉ định đường dẫn báo cáo HTML
- log: chỉ định đường dẫn log
- collect-only: chỉ liệt kê tất cả test case
To Do
- Hoàn thiện báo cáo kiểm thử
- Hỗ trợ so sánh cơ sở dữ liệu
- Hỗ trợ thực thi SQL, Shell, Cmd command, v.v.
- Sử dụng coroutine để thực hiện đồng bộ không đồng bộ
- Hỗ trợ thực thi phân tán
- Hỗ trợ thực thi theo lịch trình
- Thực hiện tích hợp liên tục