一. fixture介紹
fixture是pytest的一個閃光點,pytest要精通怎么能不學習fixture呢?跟着我一起深入學習fixture吧。其實unittest和nose都支持fixture,但是pytest做得更炫。 fixture是pytest特有的功能,它用pytest.fixture標識,定義在函數前面。在你編寫測試函數的時候,你可以將此函數名稱做為傳入參數,pytest將會以依賴注入方式,將該函數的返回值作為測試函數的傳入參數。 fixture有明確的名字,在其他函數,模塊,類或整個工程調用它時會被激活。 fixture是基於模塊來執行的,每個fixture的名字就可以觸發一個fixture的函數,它自身也可以調用其他的fixture。 我們可以把fixture看做是資源,在你的測試用例執行之前需要去配置這些資源,執行完后需要去釋放資源。比如module類型的fixture,適合於那些許多測試用例都只需要執行一次的操作。 fixture還提供了參數化功能,根據配置和不同組件來選擇不同的參數。 fixture主要的目的是為了提供一種可靠和可重復性的手段去運行那些最基本的測試內容。比如在測試網站的功能時,每個測試用例都要登錄和退出,利用fixture就可以只做一次,否則每個測試用例都要做這兩步也是冗余。
二. Fixture基礎實例入門
把一個函數定義為Fixture很簡單,只能在函數聲明之前加上“@pytest.fixture”。其他函數要來調用這個Fixture,只用把它當做一個輸入的參數即可。 test_fixture_basic.py
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
下面是運行結果,test_1和test_2運行之前都調用了before,也就是before執行了兩次。默認情況下,fixture是每個測試用例如果調用了該fixture就會執行一次的。
C:\Users\yatyang\PycharmProjects\pytest_example>pytest -v -s test_fixture_basic.py ============================= test session starts ============================= platform win32 -- Python 2.7.13, pytest-3.0.6, py-1.4.32, pluggy-0.4.0 -- C:\Python27\python.exe cachedir: .cache metadata: {'Python': '2.7.13', 'Platform': 'Windows-7-6.1.7601-SP1', 'Packages': {'py': '1.4.32', 'pytest': '3.0.6', 'pluggy': '0.4.0'}, 'JAVA_HOME': 'C:\\Program Files (x86)\\Java\\jd k1.7.0_01', 'Plugins': {'html': '1.14.2', 'metadata': '1.3.0'}} rootdir: C:\Users\PycharmProjects\pytest_example, inifile: plugins: metadata-1.3.0, html-1.14.2 collected 2 items test_fixture_basic.py::test_1 before each test test_1() PASSED test_fixture_basic.py::test_2 before each test test_2() FAILED ================================== FAILURES =================================== ___________________________________ test_2 ____________________________________ before = None def test_2(before): print 'test_2()' > assert 0 E assert 0 test_fixture_basic.py:12: AssertionError ===================== 1 failed, 1 passed in 0.23 seconds ======================
三. 調用fixture的三種方式
1. 在測試用例中直接調用它,例如第二部分的基礎實例。
2. 用fixture decorator調用fixture
可以用以下三種不同的方式來寫,我只變化了函數名字和類名字,內容沒有變。第一種是每個函數前聲明,第二種是封裝在類里,類里的每個成員函數聲明,第三種是封裝在類里在前聲明。在可以看到3中不同方式的運行結果都是一樣。 test_fixture_decorator.py
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_1()') @pytest.mark.usefixtures("before") def test_4(self): print('test_2()') @pytest.mark.usefixtures("before") class Test2: def test_5(self): print('test_1()') def test_6(self): print('test_2()')
3. 用autos調用fixture
fixture decorator一個optional的參數是autouse, 默認設置為False。 當默認為False,就可以選擇用上面兩種方式來試用fixture。 當設置為True時,在一個session內的所有的test都會自動調用這個fixture。 權限大,責任也大,所以用該功能時也要謹慎小心。
import time import pytest @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.function.__name__) print('time : %s' % time.asctime()) print('-----------------') def test_one(): print('in test_one()') def test_two(): print('in test_two()')
四. fixture scope
function:每個test都運行,默認是function的scope class:每個class的所有test只運行一次 module:每個module的所有test只運行一次 session:每個session只運行一次
比如你的所有test都需要連接同一個數據庫,那可以設置為module,只需要連接一次數據庫,對於module內的所有test,這樣可以極大的提高運行效率。
五. fixture 返回值
在上面的例子中,fixture返回值都是默認None,我們可以選擇讓fixture返回我們需要的東西。如果你的fixture需要配置一些數據,讀個文件,或者連接一個數據庫,那么你可以讓fixture返回這些數據或資源。
如何帶參數 fixture還可以帶參數,可以把參數賦值給params,默認是None。對於param里面的每個值,fixture都會去調用執行一次,就像執行for循環一樣把params里的值遍歷一次。 test_fixture_param.py
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