![](/img/trans.png)
[英]Using pytest's parametrize, how can I skip the remaining tests if one test case fails?
[英]How to parametrize tests with json array test data using pytest in python?
我有一些測試用例和測試數據,其中測試數據采用 JSON 數組形式,如下所示:
{
"valid_data": [
{
"id": "1234",
"name": "John"
},
{
"id": "2234",
"name": "Mary"
},
{
"id": "3234",
"name": "Kenny"
},
],
"invalid_data": [
{
"id": "1234",
"name": "Mary"
},
{
"id": "2234",
"name": "Kenny"
},
{
"id": "3234",
"name": "John"
},
]
}
我現在正在測試一個 API,它將接受 JSON 作為輸入並以狀態代碼進行響應。 如果數據庫中的 id 和 name 匹配,它將響應 200 OK。 否則 400 錯誤請求。
所以這是我目前的測試用例:
def get_test_data(filename):
folder_path = os.path.abspath(Path(os.path.dirname(__file__)))
folder = os.path.join(folder_path, 'TestData')
jsonfile = os.path.join(folder, filename)
with open(jsonfile) as file:
data = json.load(file)
return data
def test_valid_ok(database_api):
data = get_test_data('test_data.json')
response = database_api.get_user_info(data)
assert requests.codes['ok'] == response.status_code
在我的 conftest 中,我剛剛聲明了方法database_api
並將 URL 作為參數,然后它將向 api 發送一個 post 請求。 對於這部分沒有問題,我已經測試過它工作正常。
但是,使用當前的結構和代碼,我只能在 json 文件中包含 1 個 json 數據。 我想要一個數據驅動的測試,它能夠根據我在 json 文件中的測試數據運行多次。
我已經檢查了 pytest 官方文檔和各種建議使用 pytest 參數化函數的在線資源,但我無法使用 json 文件正確處理。
謝謝如果有人可以幫忙!
您可以使用pytest_generate_tests掛鈎對動態數據進行參數化。
首先創建一個可以被測試函數調用的fixture,獲取測試數據。
# in conftest.py
@pytest.fixture()
def test_data(request):
return request.param
現在您可以對其進行參數化,以便為每個測試數據集調用它:
#in conftest.py
def pytest_generate_tests(metafunc):
testdata = get_test_data('test_data.json')
metafunc.parametrize('test_data', testdata, indirect=True)
該testdata
傳遞給parametrize
函數必須是一個列表。 所以你需要在傳遞之前稍微修改輸入數據。 我get_test_data
修改了get_test_data
函數。
#in conftest.py
def get_test_data(filename):
folder_path = os.path.abspath(os.path.dirname(__file__))
folder = os.path.join(folder_path, 'TestData')
jsonfile = os.path.join(folder, filename)
with open(jsonfile) as file:
data = json.load(file)
valid_data = [(item, 1) for item in data['valid_data']]
invalid_data = [(item, 0) for item in data['invalid_data']]
# data below is a list of tuples, with first element in the tuple being the
# arguments for the API call and second element specifies if this is a test
# from valid_data set or invalid_data. This can be used for putting in the
# appropriate assert statements for the API response.
data = valid_data + invalid_data
return data
現在您的測試功能可能如下所示:
#in test_API.py
def test_(test_data):
response = database_api.get_user_info(test_data[0])
# Add appropriate asserts.
# test_data[1] == 1 means 200 response should have been received
# test_data[1] == 0 means 400 response should have been received
我剛剛寫了一個名為parametrize_from_file
的包來解決這個問題。 以下是此示例的工作方式:
import parametrize_from_file
# If the JSON file has the same base name as the test module (e.g. "test_api.py"
# and "test_api.json"), this parameter isn't needed.
path_to_json_file = ...
@parametrize_from_file(path_to_json_file, 'valid_data')
def test_valid_data(id, name):
request = dict(id=id, name=name)
response = database_api.get_user_info(request)
assert response.status_code == 200
@parametrize_from_file(path_to_json_file, 'invalid_data')
def test_invalid_data(id, name):
request = dict(id=id, name=name)
response = database_api.get_user_info(request)
assert response.status_code == 400
您可以通過稍微重新組織 JSON 文件來稍微簡化此代碼:
# test_api.json
{
"test_id_name_requests": [
{
"request": {
"id": "1234",
"name": "John"
},
"status_code": 200
},
{
"request": {
"id": "2234",
"name": "Mary"
},
"status_code": 200
},
{
"request": {
"id": "3234",
"name": "Kenny"
},
"status_code": 200
},
{
"request": {
"id": "1234",
"name": "Mary"
},
"status_code": 400
},
{
"request": {
"id": "2234",
"name": "Kenny"
},
"status_code": 400
},
{
"request": {
"id": "3234",
"name": "John"
},
"status_code": 400
},
],
}
有了這個文件,只需要一個測試函數,不需要給@parametrize_from_file
裝飾器提供參數:
# test_api.py
import parametrize_from_file
@parametrize_from_file
def test_id_name_requests(request, status_code):
response = database_api.get_user_info(request)
assert response.status_code == status_code
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.