Time will tell.
一权悟、Fixture介紹
fixture
是 Pytest 特有的功能酪刀,它用pytest.fixture
標識储狭,定義在函數(shù)前面胚泌。在編寫測試函數(shù)的時候鞍帝,可以將此函數(shù)名稱做為傳入?yún)?shù)丈莺, Pytest 將會以依賴注入方式且预,將該函數(shù)的返回值作為測試函數(shù)的傳入?yún)?shù)蜈项。
fixture
有明確的名字定硝,在其他函數(shù)瘪菌,模塊撒会,類或整個工程調用它時會被激活。
fixture
是基于模塊來執(zhí)行的师妙,每個 fixture 的名字就可以觸發(fā)一個fixture
的函數(shù)诵肛,它自身也可以調用其他的fixture
。
我們可以把fixture
看做是資源默穴,在你的測試用例執(zhí)行之前需要去配置這些資源怔檩,執(zhí)行完后需要去釋放資源。比如 module類型的fixture
蓄诽,適合于那些許多測試用例都只需要執(zhí)行一次的操作薛训。
fixture
還提供了參數(shù)化功能,根據(jù)配置和不同組件來選擇不同的參數(shù)仑氛。
fixture
主要的目的是為了提供一種可靠和可重復性的手段去運行那些最基本的測試內容许蓖。比如在測試網站的功能時,每個測試用例都要登錄和退出调衰,利用fixture
就可以只做一次膊爪,否則每個測試用例都要做這兩步也是冗余。
二嚎莉、Fixture基礎實例
把一個函數(shù)定義為 Fixture 很簡單米酬,只要在函數(shù)聲明之前加上@pytest.fixture
。其他函數(shù)要來調用這個Fixture
趋箩,只用把它當做一個輸入的參數(shù)即可赃额。
代碼:
import pytest
@pytest.fixture()
def before():
print '\nBefore each test'
def test_1(before):
print 'test_1()'
def test_2(before):
print 'test_2()'
assert 0 # For test purpose
結果:
(wda_python) bash-3.2$ pytest -q test_smtpsimple.py
.F [100%]
================================================================ FAILURES ================================================================
_________________________________________________________________ test_2 _________________________________________________________________
before = None
def test_2(before):
print 'test_2()'
> assert 0 # For test purpose
E assert 0
test_smtpsimple.py:12: AssertionError
--------------------------------------------------------- Captured stdout setup ----------------------------------------------------------
Before each test
---------------------------------------------------------- Captured stdout call ----------------------------------------------------------
test_2()
1 failed, 1 passed in 0.09 seconds
(wda_python) bash-3.2$
三加派、調用fixture
在測試用例中直接調用它,例如上面的基礎實例跳芳。
用
fixture decorator
調用fixture
芍锦。
可以用以下3種不同的方式來寫,我只變化了函數(shù)名字和類名字飞盆,內容沒有變娄琉。
第一種是每個函數(shù)前聲明,第二種是封裝在類里吓歇,類里的每個成員函數(shù)聲明孽水,第三種是封裝在類里在前聲明。在可以看到3種不同方式的運行結果都是一樣城看。
import pytest
@pytest.fixture()
def before():
print '\nBefore each test'
@pytest.mark.usefixtures("before")
def test_1():
print 'test_1()'
@pytest.mark.usefixtures("before")
def test_2():
print 'test_2()'
class Test1:
@pytest.mark.usefixtures("before")
def test_3(self):
print 'test_3()'
@pytest.mark.usefixtures("before")
def test_4(self):
print 'test_4()'
@pytest.mark.usefixtures("before")
class Test2:
def test_5(self):
print 'test_5()'
def test_6(self):
print 'test_6()'
我們用pytest -v -s test_module.py
運行詳細模式測試并打印輸出:
================================================== test session starts ===================================================
platform darwin -- Python 2.7.15, pytest-4.1.0, py-1.7.0, pluggy-0.8.0 -- /Users/jackey/Documents/iOS/code/iOS-Auto/MyPyEnv/wda_python/bin/python2.7
cachedir: .pytest_cache
rootdir: /Users/jackey/Documents/iOS/code/iOS-Auto/Agent_Test, inifile:
collected 6 items
test_smtpsimple.py::test_1
Before each test
test_1()
PASSED
test_smtpsimple.py::test_2
Before each test
test_2()
PASSED
test_smtpsimple.py::Test1::test_3
Before each test
test_3()
PASSED
test_smtpsimple.py::Test1::test_4
Before each test
test_4()
PASSED
test_smtpsimple.py::Test2::test_5
Before each test
test_5()
PASSED
test_smtpsimple.py::Test2::test_6
Before each test
test_6()
PASSED
================================================ 6 passed in 0.06 seconds ================================================
(wda_python) bash-3.2$
- pytest fixture scope
fixture在創(chuàng)建的時候有一個關鍵字參數(shù) scope:
scope='session'
女气,它將只運行一次,不管它在哪里定義测柠。
scope='class'
表示每個類會運行一次炼鞠。
scope='module'
表示每個module的所有test只運行一次。
scope='function'
表示每個test都運行轰胁, scope的默認值谒主。
實例代碼:
import pytest
import time
@pytest.fixture(scope="module")
def mod_header(request):
print '\n------------------'
print 'module : %s' % request.module.__name__
print '-------------------'
@pytest.fixture(scope="function")
def func_header(request):
print '\n------------------'
print 'function: %s' % request.module.__name__
print 'time: %s' % time.asctime()
print '-------------------'
def test_1(mod_header,func_header):
print 'in test_1()'
def test_2(mod_header,func_header):
print 'in test_2()'
結果:
================================================== test session starts ===================================================
platform darwin -- Python 2.7.15, pytest-4.1.0, py-1.7.0, pluggy-0.8.0 -- /Users/jackey/Documents/iOS/code/iOS-Auto/MyPyEnv/wda_python/bin/python2.7
cachedir: .pytest_cache
rootdir: /Users/jackey/Documents/iOS/code/iOS-Auto/Agent_Test, inifile:
collected 2 items
test_smtpsimple.py::test_1
------------------
module : test_smtpsimple
-------------------
------------------
function: test_smtpsimple
time: Sun Jan 13 12:19:25 2019
-------------------
in test_1()
PASSED
test_smtpsimple.py::test_2
------------------
function: test_smtpsimple
time: Sun Jan 13 12:19:25 2019
-------------------
in test_2()
PASSED
================================================ 2 passed in 0.04 seconds ================================================
(wda_python) bash-3.2$
可以看到module
在整個 module 中只執(zhí)行了一次。
-
用 autos 調用 fixture
ixture decorator 一個 optional 的參數(shù)是
autouse
软吐,默認設置為False
瘩将。當默認為False吟税,就可以選擇用上面兩種方式來試用fixture凹耙。
當設置為True時,在一個session內的所有的test都會自動調用這個 fixture肠仪。
權限大肖抱,責任也大,所以該功能用時也要謹慎小心异旧。
上面的例子可以這樣寫意述,效果也是一樣的:
import pytest
import time
@pytest.fixture(scope="module", autouse=True)
def mod_header(request):
print '\n------------------'
print 'module : %s' % request.module.__name__
print '-------------------'
@pytest.fixture(scope="function", autouse=True)
def func_header(request):
print '\n------------------'
print 'function: %s' % request.module.__name__
print 'time: %s' % time.asctime()
print '-------------------'
def test_1():
print 'in test_1()'
def test_2():
print 'in test_2()'
結果:
================================================== test session starts ===================================================
platform darwin -- Python 2.7.15, pytest-4.1.0, py-1.7.0, pluggy-0.8.0 -- /Users/jackey/Documents/iOS/code/iOS-Auto/MyPyEnv/wda_python/bin/python2.7
cachedir: .pytest_cache
rootdir: /Users/jackey/Documents/iOS/code/iOS-Auto/Agent_Test, inifile:
collected 2 items
test_smtpsimple.py::test_1
------------------
module : test_smtpsimple
-------------------
------------------
function: test_smtpsimple
time: Sun Jan 13 12:34:59 2019
-------------------
in test_1()
PASSED
test_smtpsimple.py::test_2
------------------
function: test_smtpsimple
time: Sun Jan 13 12:34:59 2019
-------------------
in test_2()
PASSED
================================================ 2 passed in 0.04 seconds ================================================
(wda_python) bash-3.2$
-
fixture 返回值
在上面的例子中,fixture 返回值都是默認
None
吮蛹,我們可以選擇讓 fixture 返回我們需要的東西荤崇。如果你的 fixture 需要配置一些數(shù)據(jù),讀個文件潮针,或者連接一個數(shù)據(jù)庫术荤,那么你可以讓 fixture 返回這些數(shù)據(jù)或資源。如何帶參數(shù)每篷,可以把參數(shù)賦值給
params
瓣戚,默認是None
端圈。對于param
里面的每個值,fixture
都會去調用執(zhí)行一次子库,就像執(zhí)行 for 循環(huán)一樣把params
里的值遍歷一次舱权。
import pytest
@pytest.fixture(params=[1,2,3])
def test_data(request):
return request.param
def test_not_2(test_data):
print 'test_data: %s' % test_data
assert test_data != 2
結果:
========================================================== test session starts ===========================================================
platform darwin -- Python 2.7.15, pytest-4.1.0, py-1.7.0, pluggy-0.8.0 -- /Users/jackey/Documents/iOS/code/iOS-Auto/MyPyEnv/wda_python/bin/python2.7
cachedir: .pytest_cache
rootdir: /Users/jackey/Documents/iOS/code/iOS-Auto/Agent_Test, inifile:
collected 3 items
test_smtpsimple.py::test_not_2[1] test_data: 1
PASSED
test_smtpsimple.py::test_not_2[2] test_data: 2
FAILED
test_smtpsimple.py::test_not_2[3] test_data: 3
PASSED
================================================================ FAILURES ================================================================
_____________________________________________________________ test_not_2[2] ______________________________________________________________
test_data = 2
def test_not_2(test_data):
print 'test_data: %s' % test_data
> assert test_data != 2
E assert 2 != 2
test_smtpsimple.py:9: AssertionError
=================================================== 1 failed, 2 passed in 0.09 seconds ===================================================
(wda_python) bash-3.2$
可以看到test_not_2
里面把用test_data
里面定義的3個參數(shù)運行里三次。
-
conftest.py配置
如果我們要實現(xiàn)一個測試場景: 用例1需要先登錄仑嗅, 用例2不需要先登錄宴倍,用例3需要先登錄。腳本我們可能會這樣寫:
#coding: utf-8
import pytest
@pytest.fixture()
def login():
print '輸入賬號无畔、密碼登錄'
def test_step_1(login):
print '用例步驟1:登錄之后其它動作111'
def test_step_2(): #不需要登錄
print '用例步驟2: 不需要登錄啊楚, 操作222'
def test_step_3(login):
print '用例步驟3:登錄之后其它動作333'
if __name__ == "__main__":
pytest.main(["-s", "test_smtpsimple.py"])
結果:
========================================================== test session starts ===========================================================
platform darwin -- Python 2.7.15, pytest-4.1.0, py-1.7.0, pluggy-0.8.0
rootdir: /Users/jackey/Documents/iOS/code/iOS-Auto/Agent_Test, inifile:
collected 3 items
test_smtpsimple.py 輸入賬號、密碼登錄
用例步驟1:登錄之后其它動作111
.用例步驟2: 不需要登錄浑彰, 操作222
.輸入賬號恭理、密碼登錄
用例步驟3:登錄之后其它動作333
.
======================================================== 3 passed in 0.05 seconds ========================================================
(wda_python) bash-3.2$
上面一個案例是在同一個.py
文件中,多個用例調用一個登陸功能郭变,如果有多個.py
的文件都需要調用這個登陸功能的話颜价,那就不能把登陸寫到用例里面去了。
此時應該要有一個配置文件诉濒,單獨管理一些預置的操作場景周伦,pytest 里面默認讀取conftest.py
里面的配置
conftest.py
配置需要注意以下點:
-
conftest.py
配置腳本名稱是固定的,不能改名稱未荒。 -
conftest.py
與運行的用例要在同一個pakage下专挪,并且有init.py文件。 - 不需要 import 導入
conftest.py
片排,pytest 用例會自動查找寨腔。
conftest.py
#coding: utf-8
from test_foocompare import Foo
import pytest
@pytest.fixture()
def login():
print '輸入賬號、密碼登錄'
test_simple.py
#coding: utf-8
import pytest
def test_step_1(login):
print '用例步驟1:登錄之后其它動作111'
def test_step_2(): #不需要登錄
print '用例步驟2: 不需要登錄率寡, 操作222'
def test_step_3(login):
print '用例步驟3:登錄之后其它動作333'
if __name__ == "__main__":
pytest.main(["-s", "test_smtps
結果:
========================================================== test session starts ===========================================================
platform darwin -- Python 2.7.15, pytest-4.1.0, py-1.7.0, pluggy-0.8.0
rootdir: /Users/jackey/Documents/iOS/code/iOS-Auto/Agent_Test, inifile:
collected 3 items
test_smtpsimple.py 輸入賬號迫卢、密碼登錄
用例步驟1:登錄之后其它動作111
用例步驟2: 不需要登錄, 操作222
.輸入賬號冶共、密碼登錄
用例步驟3:登錄之后其它動作333
======================================================== 3 passed in 0.04 seconds ========================================================
(wda_python) bash-3.2$
以上本章內容就分享到這里乾蛤,如果你對更多內容、Python自動化測試捅僵、面試題家卖、感興趣的話可以加入我們175317069一起學習。會有各項學習資源庙楚,更有行業(yè)深潛多年的技術人分析講解上荡。
祝愿你能成為一名優(yōu)秀的軟件測試工程師!
歡迎【評論】醋奠、【點贊】榛臼、【關注】~
Time will tell.(時間會證明一切)