簡體   English   中英

如何在python中使用pytest使用json數組測試數據參數化測試?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM