本項(xiàng)目實(shí)現(xiàn)了對(duì)Daily Cost的接口測(cè)試:
- Python+Requests 發(fā)送和處理HTTP協(xié)議的請(qǐng)求接口
- Pytest 作為測(cè)試執(zhí)行器
- YAML 管理測(cè)試數(shù)據(jù)
- Allure 來(lái)生成測(cè)試報(bào)告。
本項(xiàng)目是參考了pytestDemo做了自己的實(shí)現(xiàn)。
1. 項(xiàng)目結(jié)構(gòu)及安裝部署
項(xiàng)目結(jié)構(gòu)
- api: 接口封裝層,如封裝HTTP接口為Python接口
- commom: 從文件中讀取數(shù)據(jù)等各種工具類(lèi)
- core: requests 請(qǐng)求方法封裝、關(guān)鍵字返回結(jié)果類(lèi)
- config: 環(huán)境、數(shù)據(jù)庫(kù)連接等配置
- data: 測(cè)試數(shù)據(jù)文件管理
- operation: 關(guān)鍵字封裝層,如把多個(gè)Python接口封裝為關(guān)鍵字
- pytest.ini: pytest 配置文件
- requirements.txt: 相關(guān)依賴(lài)包文件
- testcases: 測(cè)試用例
- api_test: 單接口測(cè)試
- scenario_test: 場(chǎng)景/業(yè)務(wù)流程測(cè)試
安裝部署
- 部署Daily Cost應(yīng)用:教程
- 下載本測(cè)試項(xiàng)目源代碼 ,通過(guò)pip安裝相應(yīng)依賴(lài)
pip3 install -r requirements.txt
,根據(jù)實(shí)際情況修改setting.ini中的相應(yīng)內(nèi)容 - 輸入
pytest
運(yùn)行測(cè)試 - 如果想要使用Allure查看生成的測(cè)試報(bào)告,需要先安裝Allure服務(wù):
brew install allure
2. 環(huán)境配置
- 在config-setting.ini文件中定義
api_root_url
- 在common-read_data.py中實(shí)現(xiàn)load_ini()方法讀取配置文件
- 在需要使用
api_root_url
的地方調(diào)用load_ini(data_file_path)
,讀取對(duì)應(yīng)的value
3. 封裝HTTP請(qǐng)求
- 封裝requests請(qǐng)求方法:將requests中發(fā)送GET、POST、PUT、DELETE等方法封裝到RestClient類(lèi)中
- 定義被測(cè)API接口Request:在api文件夾中根據(jù)domain創(chuàng)建對(duì)應(yīng)請(qǐng)求的集合類(lèi),如
class User(RestClient)
,并定義各接口信息,如登錄接口:
def login(self, **kwargs):
return self.post("/login", **kwargs)
4. 關(guān)鍵字封裝
關(guān)鍵字應(yīng)當(dāng)是具有一定業(yè)務(wù)意義的。在封裝關(guān)鍵字的時(shí)候,可以只封裝一個(gè)接口,也可以調(diào)用多個(gè)接口來(lái)完成。
比如我們要測(cè)試記一筆,在接口調(diào)用成功后接口只會(huì)返回賬單的ID,還需要調(diào)用查詢(xún)賬單明細(xì)接口,來(lái)幫助判斷每個(gè)字段是否與輸入時(shí)的一致,那么我們可以這樣來(lái)進(jìn)行測(cè)試:
- 首先,將
記一筆-查看明細(xì)
的操作封裝為一個(gè)關(guān)鍵字,在這個(gè)關(guān)鍵字中依次調(diào)用記一筆和查詢(xún)賬單明細(xì)結(jié)果,并可以自定義關(guān)鍵字的返回結(jié)果 - 接著,在編寫(xiě)測(cè)試用例的時(shí)候,直接調(diào)用關(guān)鍵字來(lái)進(jìn)行測(cè)試,這時(shí)就可以關(guān)鍵字的返回結(jié)果,斷言的時(shí)候,也可以直接對(duì)關(guān)鍵字返回結(jié)果進(jìn)行斷言
再比如查詢(xún)?cè)露荣~單統(tǒng)計(jì)結(jié)果,一個(gè)接口就可以獨(dú)立完成業(yè)務(wù)查詢(xún)操作,我們?cè)陉P(guān)鍵字中只調(diào)用這一個(gè)接口即可。
回到本項(xiàng)目,具體的代碼邏輯如下:
- 在operation文件夾中,還是按照domain分文件來(lái)組織各關(guān)鍵字
- 在core中定義關(guān)鍵字返回的數(shù)據(jù)結(jié)構(gòu)類(lèi)
ResultBase
- 定義關(guān)鍵字,在調(diào)用對(duì)應(yīng)API請(qǐng)求時(shí)需要明確傳遞接口請(qǐng)求參數(shù),并定義返回結(jié)果
def bill_monthly_stat(date, token):
header = {
"Content-Type": "application/json",
"Authorization": "Bearer " + token
}
param = {"date": date}
res = bill_details.get_bill_monthly(params=param, headers=header)
return ResultBase(res)
本項(xiàng)目中的關(guān)鍵字中都只封裝了一個(gè)請(qǐng)求。
5. 單接口測(cè)試
以記一筆
接口為例。
- 定義接口及關(guān)鍵字
// api -> bill.py : 定義接口
def create_new_bill(self, **kwargs):
return self.post("/bill", **kwargs)
// operation -> bill.py : 定義關(guān)鍵字
def bill_create(category_id, type, amount, note, date, token):
payload = {
"categoryId": category_id,
"type": type,
"amount": amount,
"note": note,
"date": date
}
header = {
"Content-Type": "application/json",
"Authorization": "Bearer " + token
}
res = bill.create_new_bill(json=payload, headers=header)
return ResultBase(res)
- 接口測(cè)試類(lèi)
// testcases -> api_test -> bill -> test_bill_create.py
class TestBillCreate():
@mark.smoke
@mark.parametrize('category_id, type, amount, note, date, status_code, message',
[
("5442d3b8-9d4a-4654-bf0b-d2249efef190", "EXPENSE", 100.01, "note1111test", "2021-12-01", 200, "操作成功"),
("66c22fad-be9d-481d-a445-c57d266bf938", "INCOME", 1000.01, "note1111test", "2021-12-01", 200, "操作成功")
])
def test_bill_create_success(self, category_id, type, amount, note, date, status_code, message, token):
result = bill_create(category_id, type, amount, note, date, token)
assert result.response.status_code == status_code
assert result.message == message
assert result.response.json()["data"]["id"]
-
@mark.smoke
是使用了pytest的mark標(biāo)記功能,運(yùn)行時(shí)使用命令pytest -m smoke
只運(yùn)行標(biāo)記為smoke的用例 -
@mark.parametrize
是pytest的變量參數(shù)化功能,可以實(shí)現(xiàn)數(shù)據(jù)驅(qū)動(dòng)測(cè)試,如上所示有兩條參數(shù)化數(shù)據(jù),則該用例會(huì)應(yīng)用這兩條數(shù)據(jù)共執(zhí)行兩次 - 調(diào)用bill_create時(shí)有一個(gè)
token
參數(shù),它實(shí)際上是在conftest.py
文件中定義的 - pytest中的assert使用的是python內(nèi)置的斷言庫(kù)
6. YAML文件管理測(cè)試數(shù)據(jù)
在上面的例子中我們?cè)谑褂?code>@mark.parametrize時(shí)直接將具體的測(cè)試數(shù)據(jù)寫(xiě)在了用例上方。為了后期修改維護(hù)效率更高,我們通常會(huì)將測(cè)試數(shù)據(jù)和用例分離,即可以采用yaml文件來(lái)單獨(dú)管理測(cè)試數(shù)據(jù),conftest.py可以幫助數(shù)據(jù)的讀取。
- 定義yaml文件:data -> api_test_data.yml
test_bill_create_success:
# category_id, type, amount, note, date, status_code, message
- ["5442d3b8-9d4a-4654-bf0b-d2249efef190", "EXPENSE", 100.01, "note1111test", "2021-12-01", 200, "操作成功"]
- ["66c22fad-be9d-481d-a445-c57d266bf938", "INCOME", 1000.01, "note1111test", "2021-12-01", 200, "操作成功"]
-
key
為測(cè)試用例對(duì)應(yīng)的函數(shù)名test_bill_create_success
-
-
表示value是數(shù)組 -
conftest.py
中讀取對(duì)應(yīng)的測(cè)試數(shù)據(jù)
import pytest
import os
from common.read_data import data
BASE_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
def get_data(yaml_file_name):
try:
data_file_path = os.path.join(BASE_PATH, "data", yaml_file_name)
yaml_data = data.load_yaml(data_file_path)
except Exception as ex:
pytest.skip(str(ex))
else:
return yaml_data
api_data = get_data("api_test_data.yml")
- 參數(shù)化時(shí)從yaml文件中讀取數(shù)據(jù)
@mark.parametrize('category_id, type, amount, note, date, status_code, message',
api_data["test_bill_create_success"])
7. API場(chǎng)景測(cè)試
在做API測(cè)試時(shí),除了單個(gè)接口輸入輸出的校驗(yàn),由多個(gè)接口串聯(lián)成的業(yè)務(wù)場(chǎng)景的測(cè)試也是必不可少的。
簡(jiǎn)單的,我們以登錄后進(jìn)入首頁(yè)為例,接口調(diào)用為:登錄 -> 查詢(xún)當(dāng)月賬單明細(xì)列表 -> 查詢(xún)當(dāng)月賬單統(tǒng)計(jì)值。
- 定義場(chǎng)景測(cè)試類(lèi)
// testcases -> scenario_test -> test_get_one_month_bill.py
import allure
import pytest
from operation.user import login_user
from operation.bill import one_month_bill_list_get_by_date, bill_monthly_stat
@pytest.mark.core
class TestGetOneMonthBill:
@allure.title("01: user[yuxiaomeng] login")
@allure.story('story_1')
def test_user_login(self, core_env):
result = login_user('yuxiaomeng', '20211030.y')
assert result.status_code == 200
assert result.data["token"]
core_env["token"] = result.data["token"]
@allure.title("02: get homepage info - bill details list")
@allure.story('story_1')
def test_get_current_month_monthly_bill_list(self, core_env):
result = one_month_bill_list_get_by_date(core_env["date"], core_env["token"])
assert result.status_code == 200
assert len(result.data) == 2
assert result.data[0]["date"] == "2021-11-11"
assert result.data[0]["expense"] == 510.5
@allure.title("03: get homepage info - bill monthly statistics ")
@allure.story('story_1')
def test_get_current_month_bill(self, core_env):
result = bill_monthly_stat(core_env["date"], core_env["token"])
assert result.status_code == 200
assert result.data["expense"]
- 其中
core_env
用于在接口間傳遞測(cè)試數(shù)據(jù)
// testcases -> scenario_test -> conftest.py
import pytest
@pytest.fixture(scope='session')
def core_env():
return {"date": "2021-11"}
8. Allure生成測(cè)試報(bào)告
allure-pytest的詳細(xì)使用方法可以參考官方文檔。在這里只做簡(jiǎn)單介紹。
- 運(yùn)行測(cè)試時(shí)加上--alluredir參數(shù)可以生存報(bào)告到指定的文件夾:
pytest --alluredir=/tmp/my_allure_results
- 運(yùn)行完后查看報(bào)告:
allure serve /tmp/my_allure_results
END配套學(xué)習(xí)資源分享
最后:?為了回饋鐵桿粉絲們,我給大家整理了完整的軟件測(cè)試視頻學(xué)習(xí)教程,朋友們?nèi)绻枰梢宰孕忻赓M(fèi)領(lǐng)取?【保證100%免費(fèi)】
軟件測(cè)試面試文檔
我們學(xué)習(xí)必然是為了找到高薪的工作,下面這些面試題是來(lái)自阿里、騰訊、字節(jié)等一線(xiàn)互聯(lián)網(wǎng)大廠最新的面試資料,并且有字節(jié)大佬給出了權(quán)威的解答,刷完這一套面試資料相信大家都能找到滿(mǎn)意的工作。
全套資料獲取方式:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-708747.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-708747.html
到了這里,關(guān)于接口自動(dòng)化測(cè)試:Python+Pytest+Requests+Allure的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!