pytest:用例之間共享參數

一般情況下自動化用例只需要登錄一次就行了,每個接口請求時使用同一個token即可。

實現有3種方法:

方法1:使用系統變量

屬於python內置方法,簡單,但是用例之間會有很多參數需要傳遞,不能區分是哪個用例的變量

conftest.py文件中定義登錄請求,作用域設置爲全局scope="session",執行時只需登錄一次,獲取到cookie後將其存入到系統變量,後續可進行全局使用
使用os.environ將字符串存入系統變量(注意此處只能接受str,不能接受字典)

@pytest.fixture(scope="session", autouse=True)
def get_token():
    """
    :return: 返回接口所需token
    """
    payload = {"name":hello,"pwd":123456}
    headers = settings.HEADERS
    response = requests.post(settings.host + settings.get_token_uri, data=payload, headers=headers)
    log.logger.info(f"登錄接口返回:{response.text}")
    os.environ["token"] = json.loads(response.text)["data"]["accessToken"]

 讀取系統變量:

headers['Authorization'] = "Bearer " + os.getenv("token")

方法2:自定義方法

可以支持每個用例對應參數,避免參數名重複

編寫模塊:dependency_variable.py

import json
from simple_settings import settings


def set_dependency_variable(case_name, dependency_data):
    """
    寫入依賴數據
    :param case_name: 用例名
    :param dependency_data: 其他用例需要依賴的數據
    :return:
    """
    with open(settings.BASE_PATH + "/" + "common/dependency_data.json", "r") as f:
        dependency_data_dict = json.load(f)
        dependency_data_dict[case_name] = dependency_data
        f.close()
    with open(settings.BASE_PATH + "/" + "common/dependency_data.json", "w") as r:
        json.dump(dependency_data_dict, r)
        r.close()


def get_dependency_variable(depends_case, dynamic_variable):
    """
    取依賴用例的參數
    :param depends_case: 依賴的用例方法名
    :param dynamic_variable: 需要動態替換的參數
    :return: dynamic_variable:返回動態參數值
    """
    with open(settings.BASE_PATH + "/" + "common/dependency_data.json", "r") as f:
        dependency_data_dict = json.load(f)
        dynamic_variable = dependency_data_dict[depends_case][dynamic_variable]
        f.close()
        return dynamic_variable

使用時,按照python正常的調用方法即可

# 寫入後續會用到的被依賴參數,第二個參數可以是字典,其中可存儲多個參數供後續用例使用
set_dependency_variable(case_name, {"userID": json.loads(res.text)["data"]["userID"]})

# 讀取依賴參數,第一個參數爲用例名
userID= get_dependency_variable("test_edec_search", "userID")

 

方法3:使用tmpdir_factory方法

使用pytest的tmpdir和tmpdir_factory兩個夾具函數,同樣是通過conftest文件來實現。仍然是先來看下官方文檔針對這兩個方法的說明:

 

 

 簡單來說,這兩個方法的作用就是爲每個測試方法創建一個臨時目錄用於存儲自定義的文件,這個臨時目錄會默認保存3個sessions,之後就會按照創建的順序刪除舊的目錄。看下官方的例子:

# content of test_tmpdir.py
def test_create_file(tmpdir):
    p = tmpdir.mkdir("sub").join("hello.txt")
    p.write("content")
    assert p.read() == "content"
    assert len(tmpdir.listdir()) == 1
    assert 0
# contents of conftest.py
import pytest
 
 
@pytest.fixture(scope="session")
def image_file(tmpdir_factory):
    img = compute_expensive_image()
    fn = tmpdir_factory.mktemp("data").join("img.png")
    img.save(str(fn))
    return fn
 
 
# contents of test_image.py
def test_histogram(image_file):
    img = load_image(image_file)
    # compute and test histogram

在實際項目中的使用:

仍是在conftest.py文件中自定義一個夾具函數,返回結果是一個元組,p是tmpdir_factory方法返回的對象,轉爲字符串之後就是文件存儲的路徑。

自定義一個名爲“apitest-tmp-dir”的文件夾用於存儲文件

# conftest.py
 
@pytest.fixture
def tmp_factory(tmpdir_factory):
    """
    生成臨時目錄
    """
    p = tmpdir_factory.mktemp('apitest-tmp-dir')
    logger.info("當前臨時文件的目錄爲:" + str(p))
    return p, str(p)

在測試方法中的使用

 
# test_get_set.py
 
import requests
import pytest
import json
 
 
def test_set(tmp_factory):
    res = requests.get("http://www.baidu.com")
    status_code = res.status_code
    logger.info(f"返回狀態碼:{status_code}")
 
    logger.debug(tmp_factory)
    # 創建test_set.txt文件
    a = tmp_factory[0].join("test_set.txt")
    # 將需要的內容寫入到文件中
    a.write({"status_code": status_code})
    
    # 使用read()方法獲取文件中的內容
    logger.debug(a.read())
 
 
 
if __name__ == '__main__':
    pytest.main(['-sv', 'test_get_set.py'])

返回結果: 

test_get_set.py::test_set 2021-12-24 18:24:39.292 | INFO     | cases.conftest:tmp_factory:150 - 當前臨時文件的目錄爲:/private/var/folders/_f/1d0lt83x1599bf6mcfppbwp40000gn/T/pytest-of-j/pytest-19/apitest-tmp-dir0

2021-12-24 18:24:39.347 | INFO     | cases.test_get_set:test_set:32 - 返回狀態碼:200

2021-12-24 18:24:39.347 | DEBUG    | cases.test_get_set:test_set:34 - (local('/private/var/folders/_f/1d0lt83x1599bf6mcfppbwp40000gn/T/pytest-of-j/pytest-19/apitest-tmp-dir0'), '/private/var/folders/_f/1d0lt83x1599bf6mcfppbwp40000gn/T/pytest-of-j/pytest-19/apitest-tmp-dir0')

2021-12-24 18:24:39.348 | DEBUG    | cases.test_get_set:test_set:38 - {'status_code': 200}

PASSED



============================== 1 passed in 0.07s ==============================

創建的文件:

pytest用例間參數傳遞的兩種實現方式是怎樣的

可以看到,tmpdir_factory會自動爲我們創建一個目錄,名字是`tmp_factory`方法中自定義的名稱後面加0,同時它的上級目錄會自動從pytest-0遞增

說下這個辦法的優缺點:

  • 先說優點,這種數據存儲是直接寫入到文件,因此即使運行結束後也可以訪問,而不像第一種方法存儲的內容會隨着用例運行的結束而消失

  • 再說缺點,因爲這個臨時目錄最多隻能保存3個,因此如果用例很多時,那麼就可能存在文件被自動刪除的風險。不過這個貌似可以通過修改默認配置來解決,可以繼續研究下。

  • 缺點二,上面的例子中,直接通過a.read()就訪問到了文件中的內容,這是因爲內容的存儲與讀取全是在一個方法內,因此可以直接調用。如果是A方法存結果,在B中需要讀取,那麼便不能直接使用read()方法了(因爲每個方法都會創建一個目錄,並且默認的讀取地址都是這個方法自己創建的目錄)。就需要我們自己去單獨封裝一個讀取文件的方法了,實現起來也不難而且tmpdir本身的這些方法也是對os.path一些方法的二次封裝。

話說回來,都需要我自己去封裝一個讀取文件的方法了,爲啥不乾脆把讀、寫都自己來做呢?這樣是否刪除文件、刪除幾個、什麼時候刪除就完全由自己定義了啊,貌似會更方便。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章