apiAutoTest£º×Ô¶¯»¯²âÊÔÖеÄÊý¾ÝÒÀÀµ´¦Àí
Ôʼ°æ±¾
¼òÊ飺https://www.jianshu.com/p/6bfaca87a93b
²©¿ÍÔ°£º/zy7y/p/13426816.html
testerhome£ºhttps://testerhome.com/topics/25003
×îÐÂÓÃÀý½ØÍ¼ÒÔ¼°ÓÃÀýÌîд¸ñʽ
Êý¾ÝÒÀÀµ/·¾¶²ÎÊýÒÀÀµ
365betÌåÓýÔÚÏßÀí½âµÄ²ÎÊýÒÀÀµ/½Ó¿ÚÒÀÀµ¾ÍÊǽӿڽøÐйØÁª²Ù×÷£¬±ÈÈçÓÐЩ²éѯ½Ó¿ÚÐèÒªµÇ¼֮ºó²Å¿ÉÒÔ²Ù×÷£¬ÄÇô365betÌåÓýÔÚÏßÃǾÍÐèÒªÄõ½tokenÖ®ÀàµÄ¶«Î÷£¬ÕâÒ»²¿·Ö¶«Î÷ÊǷŵ½headerÖеģ¬apiAutoTestÎ§ÈÆµÄÖ»Óз¾¶²ÎÊýÒÀÀµ£¬ÇëÇóÊý¾ÝÒÀÀµ
-
·¾¶²ÎÊýÒÀÀµ
Æ©Èç˵ÏÖÔÚµÄrestful£¬Ò»¸öusers½Ó¿Ú£¬Â·ÓÉÒ»°ãÕâÑùµÄ
users
ËûµÄÇëÇó·½Ê½ÊÇget£¬Õâ¸ö·ÓÉ365betÌåÓýÔÚÏßÃǰÑËûÈÏΪÊDzéËùÓÐÓû§£¬Èç¹û²éijһ¸öÓû§¿ÉÄÜÊÇÕâÑùµÄusers/:id
Ò²ÊǸögetÇëÇó£¬ÕâÀïÕâ¸öidÏë±í´ïµÄÒâ˼ÊÇÕâÀïÓиöÐèÒª¸öÓû§idµÄ²ÎÊý£¬±ÈÈç1-500ÀïÃæµÄÈ365betÌåÓýÔÚÏßâ1¸ö£¬Ò²¾ÍÊÇ˵Õâ¸öidÊǿɱäµÄ£¬¿ÉÒԴӵǼ½Ó¿ÚµÄ·µ»ØÏìӦȡһ¸ö½ÐuserIdµÄÖµ -
ÇëÇó²ÎÊýÒÀÀµ
Õâ¸öÓ¦¸ÃºÃÀí½âЩ£¬¾ÍÊÇ˵֧¸¶½Ó¿ÚÐèÒªµÄ¶©µ¥id£¬ÊÇ´ÓÉÏÒ»²½Ìá½»¶©µ¥½Ó¿Ú·µ»ØµÄÏìÓ¦¶©µ¥id
¾Ù¸öÀý×Ó
¼ÙÉèÏÖÔÚÓиöʵ¼ÊÏìÓ¦½á¹û×ÖµäÈçÏÂ
{"case_002": {
"data": {
"id": 500,
"username": "admin",
"mobile": "12345678",
}},
"case_005": {
"data": {
"id": 511,
"create_time": 1605711095
},
}
}
-
excelÖнӿÚ·¾¶ÄÚÈÝ£º
users/&$.case_005.data.id&/state/&$.case_005.data.careate_time&
´úÂëÄÚ²¿½âÎöºóÈçÏÂ:
users/511/state/1605711095
&$.case_005.data.id&
´ú±í´ÓÏìÓ¦×ÖµäÖÐÌáÈ¡case_005×ÖµäÖÐdata×ÖµäÖеÄidµÄÖµ£¬ÌáÈ¡³öÀ´µÄ½á¹ûÊÇ511 -
excelÖÐÇëÇó²ÎÊýÄÚÈÝÈçÏÂ:
{ "pagenum": 1, "pagesize": "12", "data": &$.case_005.data&, "userId": &$.case_002.data.id& }
´úÂëÄÚ²¿½âÎöºóÈçÏÂ:
{ "pagenum": 1, "pagesize": "12", "data": { "id": 511, "create_time": 1605711095 }, "userId": 500 }
Æäʵ²»ÄÑ¿´³öÆäÖйæÔò&jsonpathÌáÈ¡Óï·¨&
£¬Èç¹ûÄãÐèÒªµÄÄÚÈÝÊÇ×Ö·û´®ÀàÐÍ£¬Ö»ÐèÒªÕâÑù"&jsonpathÌáÈ¡Óï·¨&"
ÉÏ´«Îļþ
ÓÃÀýÖÐÊéд¸ñʽ£¬ÔÚÉÏ´«ÎļþÀ¸
# µ¥ÎļþÉÏ´«ÔÚexcelÖÐд·¨
{"½Ó¿ÚÖнÓÊÜÎļþ¶ÔÏóµÄ²ÎÊýÃû": "Îļþ·¾¶µØÖ·"}
# ¶àÎļþÉÏ´«ÔÚexcelÖÐд·¨
{"½Ó¿ÚÖнÓÊÜÎļþ¶ÔÏóµÄ²ÎÊýÃû": ["Îļþ·¾¶1", "Îļþ·¾¶2"]}
Ô¤ÆÚ½á¹û
ÓÃÀýÊéд¸ñʽ
# ¶ÏÑÔÒ»¸öÄÚÈÝ
{"jsonpathÌáÈ¡±í´ïʽ": Ô¤ÆÚ½á¹ûÄÚÈÝ}
# ¶à¸ö¶ÏÑÔ
{"jsonpathÌáÈ¡±í´ïʽ1": Ô¤ÆÚ½á¹ûÄÚÈÝ1,"jsonpathÌáÈ¡±í´ïʽ2": Ô¤ÆÚ½á¹ûÄÚÈÝ2}
ÆäËûÓÅ»¯
- config.yamlÎļþÖÐÐÂÔö¿ÉÅäÖóõʼheader£¬ÕûÌå´úÂëÓÅ»¯£¬Ïà±È֮ǰ£¬Í¬Ñù²âÊÔÓÃÀýÖ´ÐÐÏ£¬¿ìÁË2s×óÓÒ
- ½«ÅäÖÃÎļþ¶ÁÈ¡£¬ÓÃÀý¶ÁÈ¡ÕûºÏÔÚ
read_file.py
Ï - ÒÆ³ý±¨¸æÑ¹Ëõ·½·¨
- ¼õÉÙÈÕÖ¾ÐÅÏ¢
ÏÖÒÀÀµ´¦Àí´úÂë
tools/init.py
#!/usr/bin/env/python3
# -*- coding:utf-8 -*-
"""
@project: apiAutoTest
@author: zy7y
@file: __init__.py
@ide: PyCharm
@time: 2020/7/31
"""
import json
import re
import allure
from jsonpath import jsonpath
from loguru import logger
def extractor(obj: dict, expr: str = '.') -> object:
"""
¸ù¾Ý±í´ïʽÌáÈ¡×ÖµäÖеÄvalue£¬±í´ïʽ, . ÌáÈ¡×ÖµäËùÓÐÄÚÈÝ£¬ $.case Ìáȡһ¼¶×Öµäcase£¬ $.case.data ÌáÈ¡case×ÖµäϵÄdata
:param obj :json/dictÀàÐÍÊý¾Ý
:param expr: ±í´ïʽ, . ÌáÈ¡×ÖµäËùÓÐÄÚÈÝ£¬ $.case Ìáȡһ¼¶×Öµäcase£¬ $.case.data ÌáÈ¡case×ÖµäϵÄdata
$.0.1 ÌáÈ¡×ÖµäÖеĵÚÒ»¸öÁбíÖеĵڶþ¸öµÄÖµ
"""
try:
result = jsonpath(obj, expr)[0]
except Exception as e:
logger.error(f'ÌáÈ¡²»µ½ÄÚÈÝ£¬¶ª¸øÄãÒ»¸ö´íÎó£¡{e}')
result = None
return result
def rep_expr(content: str, data: dict, expr: str = '&(.*?)&') -> str:
"""´ÓÇëÇó²ÎÊýµÄ×Ö·û´®ÖУ¬Ê¹ÓÃÕýÔòµÄ·½·¨ÕÒ³öºÏÊʵÄ×Ö·û´®ÄÚÈݲ¢½øÐÐÌæ»»
:param content: ÔʼµÄ×Ö·û´®ÄÚÈÝ
:param data: ÔÚ¸ÃÏîÄ¿ÖÐÒ»°ãΪÏìÓ¦×ֵ䣬´Ó×Öµäȡֵ³öÀ´
:param expr: ²éÕÒÓõÄÕýÔò±í´ïʽ
return content£º Ìæ»»±í´ïʽºóµÄ×Ö·û´®
"""
for ctt in re.findall(expr, content):
content = content.replace(f'&{ctt}&', str(extractor(data, ctt)))
return content
def convert_json(dict_str: str) -> dict:
"""
:param dict_str: ³¤µÃÏñ×ÖµäµÄ×Ö·û´®
return json¸ñʽµÄÄÚÈÝ
"""
try:
if 'None' in dict_str:
dict_str = dict_str.replace('None', 'null')
elif 'True' in dict_str:
dict_str = dict_str.replace('True', 'true')
elif 'False' in dict_str:
dict_str = dict_str.replace('False', 'false')
dict_str = json.loads(dict_str)
except Exception as e:
if 'null' in dict_str:
dict_str = dict_str.replace('null', 'None')
elif 'true' in dict_str:
dict_str = dict_str.replace('true', 'True')
elif 'False' in dict_str:
dict_str = dict_str.replace('false', 'False')
dict_str = eval(dict_str)
logger.error(e)
return dict_str
def allure_title(title: str) -> None:
"""allureÖÐÏÔʾµÄÓÃÀý±êÌâ"""
allure.dynamic.title(title)
def allure_step(step: str, var: str) -> None:
"""
:param step: ²½Öè¼°¸½¼þÃû³Æ
:param var: ¸½¼þÄÚÈÝ
"""
with allure.step(step):
allure.attach(json.dumps(var, ensure_ascii=False, indent=4), step, allure.attachment_type.TEXT)
tools/data_process.py
#!/usr/bin/env/python3
# -*- coding:utf-8 -*-
"""
@project: apiAutoTest
@author: zy7y
@file: data_process.py
@ide: PyCharm
@time: 2020/11/18
"""
from tools import logger, extractor, convert_json, rep_expr, allure_step
from tools.read_file import ReadFile
class DataProcess:
response_dict = {}
header = ReadFile.read_config('$.request_headers')
have_token = header.copy()
@classmethod
def save_response(cls, key: str, value: object) -> None:
"""
±£´æÊµ¼ÊÏìÓ¦
:param key: ±£´æ×ÖµäÖеÄkey£¬Ò»°ãʹÓÃÓÃÀý±àºÅ
:param value: ±£´æ×ÖµäÖеÄvalue£¬Ê¹ÓÃjsonÏìÓ¦
"""
cls.response_dict[key] = value
logger.info(f'Ìí¼Ókey: {key}, ¶ÔÓ¦value: {value}')
@classmethod
def handle_path(cls, path_str: str) -> str:
"""·¾¶²ÎÊý´¦Àí
:param path_str: ´øÌáÈ¡±í´ïʽµÄ×Ö·û´® /&$.case_005.data.id&/state/&$.case_005.data.create_time&
ÉÏÊöÄÚÈÝ365ÌåÓýͶע£¬´ÓÏìÓ¦×ÖµäÖÐÌáÈ¡µ½case_005×ÖµäÀïdata×ÖµäÀïidµÄÖµ£¬¼ÙÉèÊÇ500£¬ºóÃæ&$.case_005.data.create_time& ÀàËÆ£¬×îÖÕÌáÈ¡½á¹û
return /511/state/1605711095
"""
# /&$.case.data.id&/state/&$.case_005.data.create_time&
return rep_expr(path_str, cls.response_dict)
@classmethod
def handle_header(cls, token: str) -> dict:
"""´¦Àíheader
:param token: д£º дÈëtokenµ½headerÖУ¬ ¶Á£º ʹÓôøtokenµÄheader£¬ ¿Õ£ºÊ¹Óò»´øtokenµÄheader
return
"""
if token == '¶Á':
return cls.have_token
else:
return cls.header
@classmethod
def handler_files(cls, file_obj: str) -> object:
"""file¶ÔÏó´¦Àí·½·¨
:param file_obj: ÉÏ´«ÎļþʹÓ㬸ñʽ£º½Ó¿ÚÖÐÎļþ²ÎÊýµÄÃû³Æ:"Îļþ·¾¶µØÖ·"/["ÎļþµØÖ·1", "ÎļþµØÖ·2"]
ʵÀý- µ¥¸öÎļþ: &file&D:
"""
if file_obj == '':
return
for k, v in convert_json(file_obj).items():
# ¶àÎļþÉÏ´«
if isinstance(v, list):
files = []
for path in v:
files.append((k, (open(path, 'rb'))))
else:
# µ¥ÎļþÉÏ´«
files = {k: open(v, 'rb')}
return files
@classmethod
def handle_data(cls, variable: str) -> dict:
"""ÇëÇóÊý¾Ý´¦Àí
:param variable: ÇëÇóÊý¾Ý£¬´«ÈëµÄÊÇ¿Éת»»×Öµä/jsonµÄ×Ö·û´®,ÆäÖпÉÒÔ°üº¬±äÁ¿±í´ïʽ
return ´¦ÀíÖ®ºóµÄjson/dictÀàÐ͵Ä×ÖµäÊý¾Ý
"""
if variable == '':
return
data = rep_expr(variable, cls.response_dict)
variable = convert_json(data)
return variable
@classmethod
def assert_result(cls, response: dict, expect_str: str):
""" Ô¤ÆÚ½á¹ûʵ¼Ê½á¹û¶ÏÑÔ·½·¨
:param response: ʵ¼ÊÏìÓ¦×Öµä
:param expect_str: Ô¤ÆÚÏìÓ¦ÄÚÈÝ£¬´ÓexcelÖжÁÈ¡
return None
"""
expect_dict = convert_json(expect_str)
index = 0
for k, v in expect_dict.items():
actual = extractor(response, k)
index += 1
logger.info(f'µÚ{index}¸ö¶ÏÑÔ,ʵ¼Ê½á¹û:{actual} | Ô¤ÆÚ½á¹û:{v} \n¶ÏÑÔ½á¹û {actual == v}')
allure_step(f'µÚ{index}¸ö¶ÏÑÔ', f'ʵ¼Ê½á¹û:{actual} = Ô¤ÆÚ½á¹û:{v}')
assert actual == v
Ô´ÂëµØÖ·
master: ·Ö֧Ϊ×îдúÂë
version1.0: ·Ö֧Ϊ֮ǰ¿ªÔ´µÄ´úÂ루ͨ¹ý×Öµäµü´úµÄ·½Ê½À´´¦ÀíÊý¾ÝÒÀÀµ£©
Https://gitee.com/zy7y/apiAutoTest.git
Https://github.com/zy7y/apiAutoTest.git
ºóÐø´òËã
ĿǰÔÚ¹«Ë¾ÕýÔÚ×ö½Ó¿Ú²âÊÔ£¬ËµÊµ»°Ò²ÊÇÃþË÷×ÅÀ´£¬ÒÔÉϵÄÓÅ»¯Ïî¶¼ÊÇʵ¼Ê×öµÄ¹ý³ÌÖÐͻȻÏëµ½µÄ£¬È»ºó¾Í¸üÐÂÁË
- ½ÓÈëÓÃÀýǰºóÖÃSQL£¬ ǰÖÃSQLĿǰÏëµÄÊÇÏÖÔÚÏîÄ¿ÖÐÓöµ½µÄÎÊÌ⣬ÓÐЩ½Ó¿ÚûÓзµ»ØÐèÒªµÄÊý¾Ý£¬ÕâÀï¾ÍÒªÓÃǰÖÃSQL²éѯµÄ½á¹û´«µ½ÇëÇóÊý¾ÝÀïÃæÁË£¬ºóÖÃSQLÖ÷ÒªÊÇÇëÇóºó²é¿´Êý¾Ý¿âÖеÄÊý¾ÝÊÇ·ñ±ä¶¯£¬ÐγÉÊý¾Ý¿â¶ÏÑÔ 2020/12/08 Íê³É £¬ ÖÁ´Ë apiAutoTest Ó¦¸Ã²»»á ÔÙÓдó¸üÐÂ~~~ лл ¿´Õâ¸öDemoµÄÈË
- Æóҵ΢ÐÅÍÆËÍ£ºÄ¿Ç°ÏîÄ¿ÖÐÔ¤ÏëµÄЧ¹û£¬ÊǺó¶ËÈËÔ±Ìá½»´úÂ룬×Ô¶¯²¿ÊðÖ®ºó£¬Í¨¹ýgitlab-ci Æô¶¯²âÊÔ´úÂ룬½øÐнӿڲâÊÔÍê³ÉÖ®ºó²É¼¯allureÖеIJâÊÔ½á¹ûÒ»ÓÐÒì³£/ʧ°ÜÓÃÀý¾Í·¢ËÍÓʼþ²¢½øÐÐÆóҵ΢ÐÅÍÆË͸øÁìµ¼ Õâ¸öÆäʵ¾ÍÊÇÖØÐ·¢ËÍÇëÇó~
- .... ¾Í²»ËµÁË»¹ÓкܶàÓÅ»¯ÏÄÜÁ¦²»¹»ºÃºÃ³äµç°É£¬¡«¡«
ÖÂл
лл¸÷λ¶ÔapiAutoTestµÄ°ïÖú£¬Ð»Ð»¡«¡«¡«