欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Pytest?fixture及conftest相關(guān)詳解

 更新時(shí)間:2022年09月15日 14:31:53   作者:大剛測試開發(fā)實(shí)戰(zhàn)???????  
這篇文章主要介紹了Pytest?fixture及conftest相關(guān)詳解,fixture是在測試函數(shù)運(yùn)行前后,由pytest執(zhí)行的外殼函數(shù),更多相關(guān)內(nèi)容需要的朋友可以參考一下

前言

fixture是在測試函數(shù)運(yùn)行前后,由pytest執(zhí)行的外殼函數(shù)。fixture中的代碼可以定制,滿足多變的測試需求,包括定義傳入測試中的數(shù)據(jù)集、配置測試前系統(tǒng)的初始狀態(tài)、為批量測試提供數(shù)據(jù)源等等。fixture是pytest的精髓所在,類似unittest中setup/teardown,但是比它們要強(qiáng)大、靈活很多,它的優(yōu)勢是可以跨文件共享。

一、Pytest fixture

1.pytest fixture幾個(gè)關(guān)鍵特性

  • 有獨(dú)立的命名,并通過聲明它們從測試函數(shù)、模塊、類或整個(gè)項(xiàng)目中的使用來激活
  • 按模塊化的方式實(shí)現(xiàn),每個(gè)fixture都可以互相調(diào)用
  • fixture可以實(shí)現(xiàn)unittest不能實(shí)現(xiàn)的功能,比如unittest中的測試用例和測試用例之間是無法傳遞參數(shù)和數(shù)據(jù)的,但是fixture卻可以解決這個(gè)問題
  • fixture的范圍從簡單的單元擴(kuò)展到復(fù)雜的功能測試,允許根據(jù)配置和組件選項(xiàng)對fixture和測試用例進(jìn)行參數(shù)化

2.Pytest fixture定義

  • 定義fixture跟定義普通函數(shù)差不多,唯一區(qū)別就是在函數(shù)上加個(gè)裝飾器@pytest.fixture(),fixture命名不要用test_開頭,跟用例區(qū)分開。用例才是test_開頭的命名;
  • fixture裝飾器里的scope有四個(gè)級別的參數(shù):function(不寫默認(rèn)這個(gè))、class、module、session;
  • fixture可以有返回值,如果沒有return,默認(rèn)會是None;用例調(diào)用fixture的返回值,就是直接把fixture的函數(shù)名稱作為參數(shù)傳入;
  • fixture可以返回一個(gè)元組、列表或字典;
  • 測試用例可傳單個(gè)、多個(gè)fixture參數(shù);
  • fixture與fixture間可相互調(diào)用;

3.Pytest fixture用法

1)用法一:作為參數(shù)使用

fixture的名字直接作為測試用例的參數(shù),用例調(diào)用fixture的返回值,直接將fixture的函數(shù)名稱當(dāng)做變量名稱;如果用例需要用到多個(gè)fixture的返回?cái)?shù)據(jù),fixture也可以返回一個(gè)元祖,list或字典,然后從里面取出對應(yīng)數(shù)據(jù)。

① 將fixture函數(shù)作為參數(shù)傳遞給測試用例

@pytest.fixture()
def login():
print("this is login fixture")
user = "chen"
pwd = 123456
return user, pwd

def test_login(login):
"""將fixture修飾的login函數(shù)作為參數(shù)傳遞給本用例"""
print(login)
assert login[0] == "chen"
assert login[1] == 123456
assert "chen" in str(login)

② 同一個(gè)用例中傳入多個(gè)fixture函數(shù)

@pytest.fixture()
def user():
user = "cris"
return user

@pytest.fixture()
def pwd():
pwd = "123456"
return pwd

def test_trans_fixture(user, pwd):
"""同一條用例中傳入多個(gè)fixture函數(shù)"""
print(user, pwd)
assert "cris" in str(user)
assert pwd == "123456"

③ fixture函數(shù)之間的相互傳遞

@pytest.fixture()
def user2():
user = "cris"
return user

@pytest.fixture()
def login_info(user2):
"""fixture與fixture函數(shù)之間的相互傳遞"""
pwd = "e10adc3949ba59abbe56e057f20f883e"
return user2, pwd

def test_assert_login_info(login_info):
print(login_info)
print(type(login_info))
assert login_info[0] == "cris"
assert login_info[1] == "e10adc3949ba59abbe56e057f20f883e"

2)用法二:提供靈活的類似setup和teardown功能

Pytest的fixture另一個(gè)強(qiáng)大的功能就是在函數(shù)執(zhí)行前后增加操作,類似setup和teardown操作,但是比setup和teardown的操作更加靈活;具體使用方式是同樣定義一個(gè)函數(shù),然后用裝飾器標(biāo)記為fixture,然后在此函數(shù)中使用一個(gè)yield語句,yield語句之前的就會在測試用例之前使用,yield之后的語句就會在測試用例執(zhí)行完成之后再執(zhí)行。

@pytest.fixture()
def run_function():
print("run before function...")
yield
print("run after function...")

def test_run_1(run_function):
print("case 1")

def test_run_2():
print("case 2")

def test_run_3(run_function):
print("case 3")

運(yùn)行結(jié)果如下:

常見的應(yīng)用場景:@pytest.fixture可以用在selenium中測試用例執(zhí)行前后打開、關(guān)閉瀏覽器的操作:

@pytest.fixture()
def fixture_driver():
driver = webdriver.Chrome()
yield driver
driver.quit()
def test_baidu(fixture_driver):
driver = fixture_driver
driver.get("http://www.baidu.com")
driver.find_element_by_id('kw').send_keys("python fixture")
driver.find_element_by_id('su').click()

3)用法三:利用pytest.mark.usefixtures疊加調(diào)用多個(gè)fixture

如果一個(gè)方法或者一個(gè)class用例想要同時(shí)調(diào)用多個(gè)fixture,可以使用@pytest.mark.usefixtures()進(jìn)行疊加。注意疊加順序,先執(zhí)行的放底層,后執(zhí)行的放上層。

需注意:

  • ① 與直接傳入fixture不同的是,@pytest.mark.usefixtures無法獲取到被fixture裝飾的函數(shù)的返回值;
  • ② @pytest.mark.usefixtures的使用場景是:被測試函數(shù)需要多個(gè)fixture做前后置工作時(shí)使用;
@pytest.fixture
def func_1():
print("用例前置操作---1")
yield
print("用例后置操作---1")

@pytest.fixture
def func_2():
print("用例前置操作---2")
yield
print("用例后置操作---2")

@pytest.fixture
def func_3():
print("用例前置操作---3")
yield
print("用例后置操作---3")

@pytest.mark.usefixtures("func_3") # 最后執(zhí)行func_3
@pytest.mark.usefixtures("func_2") # 再執(zhí)行func_1
@pytest.mark.usefixtures("func_1") # 先執(zhí)行func_1
def test_func():
print("這是測試用例")

執(zhí)行結(jié)果:

4)用法四:fixture自動使用autouse=True

當(dāng)用例很多的時(shí)候,每次都傳這個(gè)參數(shù),會很麻煩。fixture里面有個(gè)參數(shù)autouse,默認(rèn)是False沒開啟的,可以設(shè)置為True開啟自動使用fixture功能,這樣用例就不用每次都去傳參了,autouse設(shè)置為True,自動調(diào)用fixture功能。所有用例都會生效,包括類中的測試用例和類以外的測試用例

@pytest.fixture(autouse=True, scope="function")
def func_auto():
"""autouse為True時(shí),會作用于每一條用例"""
print("\n---用例前置操作---")
yield
print("---用例后置操作---")

# func_auto函數(shù)的autouse=True時(shí),無論是否使用usefixtures引用func_auto,都會執(zhí)行func_auto
@pytest.mark.usefixtures("func_auto")
def test_01():
print("case 1")

def test_02():
print("case 2")

class Test:
def test_03(self):
print("case 3")

執(zhí)行結(jié)果:

4.Pytest fixture四種作用域

fixture(scope='function',params=None,autouse=False,ids=None,name=None)

fixture里面有個(gè)scope參數(shù)可以控制fixture的作用范圍:

  • function:每一個(gè)函數(shù)或方法都會調(diào)用
  • class:每一個(gè)類調(diào)用一次,一個(gè)類中可以有多個(gè)方法
  • module:每一個(gè).py文件調(diào)用一次,該文件內(nèi)又有多個(gè)function和class
  • session:多個(gè)文件調(diào)用一次,可以跨.py文件調(diào)用(通常這個(gè)級別會結(jié)合conftest.py文件使用)

1)function級別

function默認(rèn)模式為@pytest.fixture() 函數(shù)級別,即scope="function",scope可以不寫。每一個(gè)函數(shù)或方法都會調(diào)用,每個(gè)測試用例執(zhí)行前都會執(zhí)行一次function級別的fixture。

# @pytest.fixture(scope="function")等價(jià)于@pytest.fixture()
@pytest.fixture(scope="function")
def func_auto():
"""用例級別fixture,作用域單個(gè)用例"""
print("\n---function級別的用例前置操作---")
yield
print("---function級別的用例后置操作---")

# test_01會引用func_auto函數(shù),test_02沒有用修飾器修飾,故不會引用
def test_func_auto_fixture_1(func_auto):
print("func 1 print")

def test_func_auto_fixture_2():
print("func 2 print")

2)class級別

fixture的scope值還可以是class,此時(shí)則fixture定義的動作就會在測試類class的所有用例之前和之后運(yùn)行,需注意:測試類中只要有一個(gè)測試用例的參數(shù)中使用了class級別的fixture,則在整個(gè)測試類的所有測試用例都會調(diào)用fixture函數(shù)

① 用例類中的測試用例調(diào)用fixture

執(zhí)行fixture定義的動作,以及此測試類的所有用例結(jié)束后同樣要運(yùn)行fixture指定的動作

@pytest.fixture(scope="class")
def class_auto():
"""類級別fixture,作用域整個(gè)類"""
print("\n---class級別的用例前置操作---")
yield
print("---class級別的用例后置操作---")

class TestClassAutoFixture:
# class級別的fixture任意一個(gè)用例引用即可
def test_class_auto_fixture_1(self, class_auto):
print("class 1 print")

def test_class_auto_fixture_2(self):
print("class 1 print")

測試類中的第1條測試用例引用了fixture修飾的函數(shù),則整個(gè)測試類的所有測試用例都會執(zhí)行fixture函數(shù)的前置操作,在所有用例執(zhí)行完成后,都會執(zhí)行fixture函數(shù)的后置操作。

② 用例類外的測試用例調(diào)用fixture

如果在類外的函數(shù)中去使用class級別的fixture,則此時(shí)在測試類外每個(gè)測試用例中,fixture跟function級別的fixture作用是一致的,即在類外的函數(shù)中引用了class級別的fixture,則在此函數(shù)之前和之后同樣去執(zhí)行fixture定義的對應(yīng)的操作。

def test_class_auto_fixture(class_auto):
print("class 1 print")

如下圖所示,測試類外的函數(shù)引用了class級別的fixture,則它的作用會等同于function級別的fixture,

運(yùn)行結(jié)果如下:

3)module級別

在Python中module即.py文件,當(dāng)fixture定義為module時(shí),則此fixture將在當(dāng)前文件中起作用。這里需要特別說明的是,當(dāng)fixture的scope定義為module時(shí),只要當(dāng)前文件中有一個(gè)測試用例使用了fixture,不管這個(gè)用例是在類外,還是在類中,都會在當(dāng)前文件(模塊)的所有測試用例執(zhí)行之前去執(zhí)行fixture定義的行為以及當(dāng)前文件的所有用例結(jié)束之后同樣去執(zhí)行fixture定義的對應(yīng)操作。

@pytest.fixture(scope="module")
def module_auto():
"""作用于整個(gè)py文件"""
print("\n---module級別的用例前置操作---")
yield
print("---module級別的用例后置操作---")

# 測試類外和測試類內(nèi)的函數(shù)方法都調(diào)用了module級別的fixture,但整個(gè)py文件只會生效一次fixture。
def test_module_scope_out_class(module_auto):
print("case scope 01")

class TestScope1:
def test_scope_01(self):
print("case scope 01")

def test_scope_02(self, module_auto):
print("case scope 02")

def test_scope_03(self):
print("case scope 03")

若類中的方法分別調(diào)用了class級別的fixture和module級別的fixture,則會兩個(gè)fixture都生效:

# 順序在前面fixture會先執(zhí)行
def test_scope_01(self, module_auto, class_auto):
print("case scope 01")

若類中的方法同時(shí)調(diào)用了function級別、class級別、module級別的fixture,則3種fixture會同時(shí)生效:

# 順序在前面fixture會先執(zhí)行
def test_scope_02(self, module_auto, class_auto, func_auto):
print("case scope 02")

4)session級別(使用conftest.py共享fixture)

當(dāng)fixture的scope定義為session時(shí),是指在當(dāng)前目錄下的所有用例之前和之后執(zhí)行fixture對應(yīng)的操作

fixture為session級別是可以跨.py模塊調(diào)用的,也就是當(dāng)我們有多個(gè).py文件的用例的時(shí)候,如果多個(gè)用例只需調(diào)用一次fixture,那就可以設(shè)置為scope="session",并且寫到conftest.py文件里

使用方式:

  • ① 定義測試用例文件
  • ② 在指定目錄下創(chuàng)建conftest.py(固定命名,不可修改)文件,然后在conftest.py文件中定義fixture方法,將scope指定為session,此時(shí)在當(dāng)前目錄下只要有一個(gè)用例使用了此fixture,則就會在當(dāng)前目錄下所有用例之前和之后會執(zhí)行fixture定義的對應(yīng)的操作。
@pytest.fixture(scope="session", )
def session_auto():
"""session級別的fixture,針對該目錄下的所有用例都生效"""
print("\n---session級別的用例前置操作---")
yield
print("---session級別的用例后置操作---")

定義了session級別的fixture,存放于該用例文件的同一個(gè)目錄下的conftest.py文件中,該目錄下的任一用例文件中的任一測試用例,引用了這個(gè)session級別的fixture,則這個(gè)session級別的fixture會針對這整個(gè)用例文件會生效。若存放在根目錄下,則針對整個(gè)工程的所有用例都會生效。

class TestSessionAutoFixture:
# session級別的fixture任意一個(gè)用例引用即可
def test_session_auto_fixture_1(self, session_auto):
print("session 1 print")

def test_session_auto_fixture_2(self):
print("session 1 print")
def test_session_auto_fixture():
print("session 1 print")

運(yùn)行結(jié)果如下:

5.Pytest fixture其他參數(shù)用法

1)ids參數(shù)-修改用例結(jié)果名稱

@pytest.mark.parametrize() 還提供了第三個(gè) ids 參數(shù)來自定義顯示結(jié)果。

stars = ["劉德華", "張學(xué)友", "黎明", "郭富城"]
# 利用列表生成式生成一個(gè)用例名稱的列表
ids = [f"test-case-vvxyksv9kd" for d in range(len(stars))]

@pytest.mark.parametrize("name", stars, ids=ids)
def test_multi_param(name):
print(f"my name is {name}")

注:ids生成的用例名稱數(shù)量一定要和用例數(shù)量一致,否則會報(bào)錯(cuò),

執(zhí)行結(jié)果如下:

2)name參數(shù)-重命名fixture函數(shù)名稱

@pytest.fixture(name="rename_get_user_info")
def get_user_info():
user_name = "周潤發(fā)"
print(user_name)

# 此處需傳入重命名后的fixture函數(shù)名
@pytest.mark.usefixtures("rename_get_user_info")
def test_parametrize_by_use_fixtures():
"""通過usefixtures裝飾器傳入fixture"""
print(f"test parametrize use fixtures")

def test_parametrize_by_fixture_name(rename_get_user_info):
"""將fixture函數(shù)名作為形參傳入"""
print(f"test parametrize use fixtures")

3)params參數(shù)-提供返回值供測試函數(shù)調(diào)用

示例一

@pytest.fixture(params=[{"name": "周潤發(fā)"}, {"age": 61}, {"height": 183}])
def fix_func(request): # request為內(nèi)建fixture
# 使用request.param作為返回值供測試函數(shù)調(diào)用,params的參數(shù)列表中包含了做少元素,該fixture就會被調(diào)用幾次,分別作用在每個(gè)測試函數(shù)上
return request.param # request.param為固定寫法

def test_fix_func(fix_func):
print(f"fixture函數(shù)fix_func的返回值為:{fix_func}")

"""打印結(jié)果如下:
fixture函數(shù)fix_func的返回值為:{'name': '周潤發(fā)'}
fixture函數(shù)fix_func的返回值為:{'age': 61}
fixture函數(shù)fix_func的返回值為:{'height': 183}
"""

示例二:

params = [
{"case_id": 1, "case_title": "驗(yàn)證正常添加車輛", "car_name": "蘇C99688", "car_type": 1, "origin": 1, "expected": "200"},
{"case_id": 2, "case_title": "驗(yàn)證添加重復(fù)車輛", "car_name": "蘇C99688", "car_type": 1, "origin": 1, "expected": "500"},
{"case_id": 3, "case_title": "驗(yàn)證車牌號為空", "car_name": "", "car_type": 2, "origin": 1, "expected": "500"}]

@pytest.fixture(params=params)
def add_car_params(request):
return request.param

def test_add_car(add_car_params):
print(f"{add_car_params['case_id']}-{add_car_params['case_title']}-{add_car_params['car_name']}")

"""
運(yùn)行結(jié)果如下:
1-驗(yàn)證正常添加車輛-蘇C99688
2-驗(yàn)證添加重復(fù)車輛-蘇C99688
3-驗(yàn)證車牌號為空-
"""

6.內(nèi)置fixture

1)tmpdir和tmpdir_factory

內(nèi)置的tmpdir和tmpdir_factory負(fù)責(zé)在測試開始運(yùn)行前創(chuàng)建臨時(shí)文件目錄,并在測試結(jié)束后刪除。如果測試代碼要對文件進(jìn)行讀/寫操作,那么可以使用tmpdir或tmpdir_factory來創(chuàng)建文件或目錄。單個(gè)測試使用tmpdir,多個(gè)測試使用tmpdir_factory。tmpdir的作用范圍是函數(shù)級別,tmpdir_factory的作用范圍是會話級別。

def test_tmpdir(tmpdir):
# tmpdir already has a path name associated with it
# join() extends the path to include a filename
# the file is created when it's written to
a_file = tmpdir.join('something.txt')

# you can create directories
a_sub_dir = tmpdir.mkdir('anything')

# you can create files in directories (created when written)
another_file = a_sub_dir.join('something_else.txt')

# this write creates 'something.txt'
a_file.write('contents may settle during shipping')

# this write creates 'anything/something_else.txt'
another_file.write('something different')

# you can read the files as well
assert a_file.read() == 'contents may settle during shipping'
assert another_file.read() == 'something different'

def test_tmpdir_factory(tmpdir_factory):
# you should start with making a directory
# a_dir acts like the object returned from the tmpdir fixture
a_dir = tmpdir_factory.mktemp('mydir')

# base_temp will be the parent dir of 'mydir'
# you don't have to use getbasetemp()
# using it here just to show that it's available
base_temp = tmpdir_factory.getbasetemp()
print('base:', base_temp)

# the rest of this test looks the same as the 'test_tmpdir()'
# example except I'm using a_dir instead of tmpdir

a_file = a_dir.join('something.txt')
a_sub_dir = a_dir.mkdir('anything')
another_file = a_sub_dir.join('something_else.txt')

a_file.write('contents may settle during shipping')
another_file.write('something different')

assert a_file.read() == 'contents may settle during shipping'
assert another_file.read() == 'something different'

2)pytestconfig

內(nèi)置的pytestconfig可以通過命令行參數(shù)、選項(xiàng)、配置文件、插件、運(yùn)行目錄等方式來控制pytest。pytestconfig是request.config的快捷方式,它在pytest文檔里有時(shí)候被稱為“pytest配置對象”。

要理解pytestconfig如何工作,可以添加一個(gè)自定義的命令行選項(xiàng),然后在測試中讀取該選項(xiàng)。

def pytest_addoption(parser):
""""添加一個(gè)命令行選項(xiàng)"""
parser.addoption(
"--env", default="test", choices=["dev", "test", "pre"], help="enviroment parameter")

以pytest_addoption添加的命令行選項(xiàng)必須通過插件來實(shí)現(xiàn),或者在項(xiàng)目頂層目錄的conftest.py文件中完成。它所在的conftest.py不能處于測試子目錄下。

上述是一個(gè)傳入測試環(huán)境的命令行選項(xiàng),接下來可以在測試用例中使用這些選項(xiàng)。

def test_option(pytestconfig):
print('the current environment is:', pytestconfig.getoption('env'))
# 運(yùn)行測試
pytest -s -q test_config.py::test_option

由于前面的pytest_addoption中定義的env的默認(rèn)參數(shù)是test,所以通過pytestconfig.getoption獲取到的env的值就是test:

3)其他內(nèi)置fixture

  • cache:作用是存儲一段測試會話的信息,在下一段測試會話中使用;
  • capsys:capsys 有兩個(gè)功能:允許使用代碼讀取 stdout 和 stderr;可以臨時(shí)禁制抓取日志輸出;
  • monkeypatch:可以在運(yùn)行期間對類或模塊進(jìn)行動態(tài)修改。在測試中,monkey patch 常用于替換被測試代碼的部分運(yùn)行環(huán)境,或者將輸入依賴或輸出依賴替換成更容易測試的對象或函數(shù);
  • doctest_namespace:doctest 模塊是 Python 標(biāo)準(zhǔn)庫的一部分,借助它,可以在函數(shù)的文檔字符串中放入示例代碼,并通過測試確保有效。你可以使用 --doctest-modules 標(biāo)識搜尋并運(yùn)行 doctest 測試用例;
  • recwarn:可以用來檢查待測代碼產(chǎn)生的警告信息;recwarn 的值就像是一個(gè)警告信息列表,列表里的每個(gè)警告信息都有4個(gè)屬性 category、message、filename、lineno。警告信息在測試開始后收集,如果你在意的警告信息出現(xiàn)在測試尾部,則可以在信息收集前使用 recwarn.clear() 清除不需要的內(nèi)容。除了 recwarn,pytest 還可以使用 pytest.warns() 來檢查警告信息。

二、Pytest conftest全局作用文件詳解

Pytest支持在測試的目錄中,創(chuàng)建conftest.py文件,進(jìn)行全局配置。

conftest.py文件須知:

  • 可以跨.py文件調(diào)用,有多個(gè).py文件調(diào)用時(shí),可讓conftest.py只調(diào)用了一次fixture,或調(diào)用多次fixture;
  • conftest.py與運(yùn)行的用例要在同一個(gè)pakage下,并且有__init__.py文件;
  • 不需要import導(dǎo)入conftest.py,pytest用例會自動識別該文件,放到項(xiàng)目的根目錄下就可以全局目錄調(diào)用了,如果放到某個(gè)package下,那就在package內(nèi)有效,可有多個(gè)conftest.py;
  • conftest.py配置腳本名稱是固定的,不能改名稱;
  • conftest.py文件不能被其他文件導(dǎo)入;
  • 所有同目錄測試文件運(yùn)行前都會執(zhí)行conftest.py文件;

到此這篇關(guān)于Pytest fixture及conftest相關(guān)詳解的文章就介紹到這了,更多相關(guān)Pytest fixture conftest內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論