自動化測試之Pytest入門


pytest是一個功能非常全面的Python自動化測試框架

特點:

1、簡單靈活,支持參數化,可以細粒度的控制測試用例;

2、不僅支持簡單的單元測試,還支持復雜的功能測試,不僅可以用來做selenium/appium的UI自動化測試,還可以用作做基於Python+requests的接口自動化測試;

3、第三方插件非常豐富,如pytest-selenium(集成了selenium)、pytest-html(完美的html測試報告)、pytest-reunfailures(失敗case重復測試)等;

4、測試用例跳躍式(skip)執行以及標記后選擇性處理(mark);

5、很好的與CI工具(jenkins)結合;

 

編寫規則:

1、測試文件以test_開頭,以_test結尾也可以;

2、測試類以Test開頭,並且不能帶有__init__方法;

3、測試函數(方法)以test_開頭;

4、斷言使用assert;

 

一、安裝pytest

$ pip install pytest

二、執行一個測試

測試通過

# test_demo8.py

def test_pass():
    assert 1 == 1

通過pytest來運行上面測試函數

在pycharm的Terminal中直接輸入命令pytest test_demo8.py執行

MacBook-Pro:test_demo fyuanyuan$ pytest test_demo8.py

========================================================================================= test session starts ==========================================================================================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir: /Users/fujinjie/PycharmProjects/test_demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collected 1 item

test_demo8.py . [100%]

========================================================================================== 1 passed in 0.01s ===========================================================================================

執行結果為test_demo8.py測試通過(pytest使用 . 標識測試通過PASSED)

下面使用-v選項來展示測試的詳細信息

MacBook-Pro:test_demo fujinjie$ pytest -v test_demo8.py
========================================================================================= test session starts ==========================================================================================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7
cachedir: .pytest_cache
metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}}
rootdir: /Users/fujinjie/PycharmProjects/test_demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collected 1 item                                                                                                                                                                                       

test_demo8.py::test_passing PASSED                                                                                                                                                               [100%]

========================================================================================== 1 passed in 0.01s ===========================================================================================

測試失敗

# test_demo8.py

def test_fail():
    assert 1 ==2 

同樣在命令行執行pytest test_demo8.py命令

MacBook-Pro:test_demo fujinjie$ pytest test_demo8.py
========================================================================================= test session starts ==========================================================================================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir: /Users/fujinjie/PycharmProjects/test_demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collected 1 item                                                                                                                                                                                       

test_demo8.py F                                                                                                                                                                                  [100%]

=============================================================================================== FAILURES ===============================================================================================
_____________________________________________________________________________________________ test_failing _____________________________________________________________________________________________

    def test_fail():
>       assert 1 == 2
E       assert 1 == 2

test_demo8.py:8: AssertionError
========================================================================================== 1 failed in 0.05s ===========================================================================================

測試結果為失敗,pytest使用 F 來標識測試失敗FAILED

pytest中使用assert來進行斷言。

 

三、標記函數

pytest默認查找當前目錄下所有以test開始或者結尾的Python文件,並執行其中所有以test開始或結束的函數(方法)

 

run.py

#--coding:utf-8 --
#run.py
import pytest if __name__ == '__main__': pytest.main(['-v'])

test_demo9.py

#--coding:utf-8 --
#test_demo9.py

def test_demo9_func1():
    assert 1 == 1

def test_demo9_func2():
    assert 2 == 2

test_demo10.py

#--coding:utf-8 --
#test_demo10.py

def test_demo10_func3():
    assert 3 == 3

def test_demo10_func4():
    assert 4 == 4

因為run.py/test_demo9.py/test_demo10.py在同一個demo目錄下,所以執行run.py時pytest會查找該目錄下所有以test開頭或結尾的Python文件,並執行文件中所有以test開頭或結尾的函數和方法

============================= test session starts ==============================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7
cachedir: .pytest_cache
metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}}
rootdir: /Users/fujinjie/PycharmProjects/test_demo/templates/demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collecting ... collected 4 items

test_demo10.py::test_demo10_func3 PASSED                                 [ 25%]
test_demo10.py::test_demo10_func4 PASSED                                 [ 50%]
test_demo9.py::test_demo9_func1 PASSED                                   [ 75%]
test_demo9.py::test_demo9_func2 PASSED                                   [100%]

============================== 4 passed in 0.02s ===============================

由於某些原因,我只想執行test_demo9_func2()測試用例看是否通過,通過pytest有以下幾種方法:

方法一,執行時指定函數名,通過 :: 標記

#--coding:utf-8 --
#run.py
import pytest


if __name__ == '__main__':
    pytest.main(['test_demo9.py::test_demo9_func2','-v'])

或者在命令行中輸入

$pytest -v demo/test_demo9.py::test_demo9_func2

運行結果

MacBook-Pro:test_demo fujinjie$ pytest -v demo/test_demo9.py::test_demo9_func2
========================================================================================= test session starts ==========================================================================================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7
cachedir: .pytest_cache
metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}}
rootdir: /Users/fujinjie/PycharmProjects/test_demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collected 1 item                                                                                                                                                                                       

demo/test_demo9.py::test_demo9_func2 PASSED                                                                                                                                                      [100%]

========================================================================================== 1 passed in 0.01s ===================================================

 

方法二,使用 -k 選項標識來模糊匹配

匹配執行demo目錄下名稱中含有func2的測試用例

$ pytest -v -k func2 demo/

執行結果

MacBook-Pro:test_demo fujinjie$ pytest -v -k func2 demo/
========================================================================================= test session starts ==========================================================================================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7
cachedir: .pytest_cache
metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}}
rootdir: /Users/fujinjie/PycharmProjects/test_demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collected 4 items / 3 deselected / 1 selected                                                                                                                                                          

demo/test_demo9.py::test_demo9_func2 PASSED                                                                                                                                                      [100%]

=================================================================================== 1 passed, 3 deselected in 0.01s =========================================

以上兩種方法,第一種只能指定一個測試用例,無法批量執行;第二種需要所有測試名稱包含相同的部分名稱是才能批量執行。

方法三,直接使用 pytest.mark 在函數(測試用例)上進行標記

#--coding:utf-8 --
#test_demo9.py
import pytest

@pytest.mark.run
def test_demo9_func1():
    assert 1 == 1

@pytest.mark.unrun
def test_demo9_func2():
    assert 2 == 2
#--coding:utf-8 --
#test_demo10.py
import pytest

@pytest.mark.unrun
def test_demo10_func3():
    assert 3 == 3

@pytest.mark.unrun
def test_demo10_func4():
    assert 4 == 4

在命令行輸入 pytest -v -m run demo/ 命令執行

MacBook-Pro:test_demo fujinjie$ pytest -v -m run demo/
========================================================================================= test session starts ==========================================================================================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7
cachedir: .pytest_cache
metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}}
rootdir: /Users/fujinjie/PycharmProjects/test_demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collected 4 items / 3 deselected / 1 selected                                                                                                                                                          

demo/test_demo9.py::test_demo9_func1 PASSED                                                                                                                                                      [100%]

=========================================================================================== warnings summary ==========================

上述4個測試函數,只有被標記為run的 test_demo9_func1( ) 被執行

注:一個函數可以被添加多個標記,多個函數可以添加相同的標記來實現批量執行

運行時 -m 后面可加邏輯

#--coding:utf-8 --
#test_demo9.py
import pytest

@pytest.mark.run
def test_demo9_func1():
    assert 1 == 1

@pytest.mark.commit
@pytest.mark.unrun
def test_demo9_func2():
    assert 2 == 2

執行 pytest -v -m "unrun and commit" demo/

MacBook-Pro:test_demo fujinjie$ pytest -v -m "unrun and commit" demo/
========================================================================================= test session starts ==========================================================================================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7
cachedir: .pytest_cache
metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}}
rootdir: /Users/fujinjie/PycharmProjects/test_demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collected 4 items / 3 deselected / 1 selected                                                                                                                                                          

demo/test_demo9.py::test_demo9_func2 PASSED                                                                                                                                                      [100%]

被標記為 unrun 和 commit 的測試函數才執行

 

四、跳過測試

在測試工作中面對大批量的測試用例,想對其中某一條跳過不執行,Pytest中使用 pytest.mark.skip 可直接跳過該測試用例

#--coding:utf-8 --
#test_demo10.py
import pytest

@pytest.mark.skip
def test_demo10_func3():
    assert 3 == 3


def test_demo10_func4():
    assert 4 == 4

在命令行執行 pytest -v demo/test_demo10.py

MacBook-Pro:test_demo fujinjie$ pytest -v demo/test_demo10.py
========================================================================================= test session starts ==========================================================================================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7
cachedir: .pytest_cache
metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}}
rootdir: /Users/fujinjie/PycharmProjects/test_demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collected 2 items                                                                                                                                                                                      

demo/test_demo10.py::test_demo10_func3 SKIPPED                                                                                                                                                   [ 50%]
demo/test_demo10.py::test_demo10_func4 PASSED                                                                                                                                                    [100%]

===================================================================================== 1 passed, 1 skipped in 0.01s =============================================

執行結果中只有 test_demo10_func4 被執行,test_demo10_func3 直接跳過沒執行

五、參數化

當對一個函數進行測試時,通常會給這個函數傳遞多組參數,模擬各種不同情況,在pytest中就是參數化測試,即每組參數都獨立執行一次測試,使用 pytest.mark.parametrize(argnames, argvalues)

#--coding:utf-8 --
#test_demo11.py

import pytest

@pytest.mark.parametrize('password',['12345','123456a','abcdefgh'])
def test_demo_func5(password):
    assert len(password) >= 6

在命令行執行 pytest -v demo/test_demo11.py

MacBook-Pro:test_demo fujinjie$ pytest -v demo/test_demo11.py
========================================================================================= test session starts ==========================================================================================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7
cachedir: .pytest_cache
metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}}
rootdir: /Users/fujinjie/PycharmProjects/test_demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collected 3 items                                                                                                                                                                                      

demo/test_demo11.py::test_demo_func5[12345] FAILED                                                                                                                                               [ 33%]
demo/test_demo11.py::test_demo_func5[123456a] PASSED                                                                                                                                             [ 66%]
demo/test_demo11.py::test_demo_func5[abcdefgh] PASSED                                                                                                                                            [100%]

=============================================================================================== FAILURES ===============================================================================================
________________________________________________________________________________________ test_demo_func5[12345] ________________________________________________________________________________________

password = '12345'

    @pytest.mark.parametrize('password',['12345','123456a','abcdefgh'])
    def test_demo_func5(password):
>       assert len(password) >= 6
E       AssertionError: assert 5 >= 6
E        +  where 5 = len('12345')

demo/test_demo11.py:8: AssertionError

通過上述結果可以看出該測試函數被執行了3次,每次都以不同的password參數傳入,FAILLED一次,PASSED兩次。

傳入多個參數

#--coding:utf-8 --
#test_demo11.py

import pytest

@pytest.mark.parametrize('user,password',[('Jack','123456'),('Pluo','123456a'),('Flak','abcdefg')])
def test_demo11_func6(user,password):
    db = {'Jack':'123456',
          'Pluo':'123456a',
          'Flak':'abcdefg'}
    assert db[user] == password

在命令行執行 pytest -v demo/test_demo11.py::test_demo11_func6

MacBook-Pro:test_demo fujinjie$ pytest -v demo/test_demo11.py::test_demo11_func6
========================================================================================= test session starts ==========================================================================================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7
cachedir: .pytest_cache
metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}}
rootdir: /Users/fujinjie/PycharmProjects/test_demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collected 3 items                                                                                                                                                                                      

demo/test_demo11.py::test_demo11_func6[Jack-123456] PASSED                                                                                                                                       [ 33%]
demo/test_demo11.py::test_demo11_func6[Pluo-123456a] PASSED                                                                                                                                      [ 66%]
demo/test_demo11.py::test_demo11_func6[Flak-abcdefg] PASSED                                                                                                                                      [100%]

========================================================================================== 3 passed in 0.02s ===========================================================================================

 

六、固件Fixture

Fixture是一些函數,pytest會在執行測試函數(用例)之前或之后加載執行它們,比如執行測試函數前數據庫的連接和執行完畢后數據庫的關閉操作。

Pytest通過 @pytest.fixture() 來定義固件,在pytest中使用conftest.py集中管理固件,更大程度上復用(conftest.py的作用域為其所在的目錄和子目錄)

 

 

 

conftest.py在demo目錄下,因此它的作用域為demo目錄下的所有文件以及子文件

conftest.py

#--coding:utf-8 --
#conftest.py

import pytest

@pytest.fixture()
def fixture_func1():
    return '3721'

test_demo11.py

#--coding:utf-8 --
#test_demo11.py

import pytest

def test_demo11_func7(fixture_func1):
    num = '3721'
    assert num == fixture_func1

在 test_demo11.py 中測試函數 test_demo11_func7 直接調用 conftest.py 中的 fixture_func1 固件完成測試

注意:不要顯示調用 conftest.py (pytest會根據conftest.py的作用域自動調用),可以把 conftest.py 當作插件來理解。

在命令行執行 pytest -v -k func7 demo/test_demo11.py

MacBook-Pro:test_demo fujinjie$ pytest -v -k func7 demo/test_demo11.py
========================================================================================= test session starts ==========================================================================================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /usr/local/bin/python3.7
cachedir: .pytest_cache
metadata: {'Python': '3.7.2', 'Platform': 'Darwin-19.6.0-x86_64-i386-64bit', 'Packages': {'pytest': '5.3.5', 'py': '1.8.1', 'pluggy': '0.13.1'}, 'Plugins': {'html': '2.0.1', 'allure-pytest': '2.8.10', 'metadata': '1.8.0'}}
rootdir: /Users/fujinjie/PycharmProjects/test_demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collected 7 items / 6 deselected / 1 selected                                                                                                                                                          

demo/test_demo11.py::test_demo11_func7 PASSED                                                                                                                                                    [100%]

=================================================================================== 1 passed, 6 deselected in 0.02s ====================================================================================

 七、預處理和后處理

在測試過程中,我們需要在測試開始之前做准備工作,以及在測試結束后做收尾工作,在pytest中通過固件來自動化所有預處理和后處理,使用 yield 關鍵字將固件分為兩部分,yield 之前的代碼屬於預處理,在測試之前執行,yield 之后的代碼屬於后處理,將在測試完成后執行。

在 conftest.py 中加入 fixture_func2 固件

#--coding:utf-8 --
#conftest.py

import pytest

@pytest.fixture()
def fixture_func1():
    return '3721'

@pytest.fixture()
def fixture_func2():
    print('測試開始之前')
    yield
    print('測試結束之后')

在 test_demo11.py 的測試函數 test_demo11_func7 中調用固件 fixture_func1 和 fixture_func2

def test_demo11_func7(fixture_func1,fixture_func2):
    num = '3721'
    assert num == fixture_func1

在命令行中執行 pytest --setup-show -s -k func7 demo/

MacBook-Pro:test_demo fujinjie$ pytest --setup-show -s -k func7 demo/
========================================================================================= test session starts ==========================================================================================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir: /Users/fujinjie/PycharmProjects/test_demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collected 11 items / 10 deselected / 1 selected                                                                                                                                                        

demo/test_demo11.py 
        SETUP    F fixture_func1測試開始之前

        SETUP    F fixture_func2
        demo/test_demo11.py::test_demo11_func7 (fixtures used: fixture_func1, fixture_func2).測試結束之后

        TEARDOWN F fixture_func2
        TEARDOWN F fixture_func1

=================================================================================== 1 passed, 10 deselected in 0.02s ===================================================================================

 

八、作用域

pytest使用作用域來進行指定固件的使用范圍

定義固件時通過 scope 參數聲明作用域,可選項有:

1、function: 函數級,每個測試函數都會執行一次固件;

2、class:類級別,每個測試類執行一次,所有方法都可以使用;

3、module:模塊級,每個模塊執行一次,模塊內函數和方法都可以使用;

4、session:會話級,一次測試只執行一次,所有被找到的函數和方法都可用。

注:固件默認的作用域為 function

conftest.py

@pytest.fixture(scope='function')
def fixture_function():
    pass

@pytest.fixture(scope='module')
def fixture_module():
    pass

@pytest.fixture(scope='session')
def fixture_session():
    pass

@pytest.fixture(scope='class')
def fixture_class():
    pass

test_demo11.py

 def test_demo11_func8(fixture_function,fixture_session,fixture_module):
    pass

在命令行執行 pytest --setup-show -k func8 demo/ 可以看到各固件的作用域與執行順序

MacBook-Pro:test_demo fujinjie$ pytest --setup-show -k func8 demo/
========================================================================================= test session starts ==========================================================================================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir: /Users/fujinjie/PycharmProjects/test_demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collected 12 items / 11 deselected / 1 selected                                                                                                                                                        

demo/test_demo11.py 
SETUP    S fixture_session
    SETUP    M fixture_module
        SETUP    F fixture_function
        demo/test_demo11.py::test_demo11_func8 (fixtures used: fixture_function, fixture_module, fixture_session).
        TEARDOWN F fixture_function
    TEARDOWN M fixture_module
TEARDOWN S fixture_session

=================================================================================== 1 passed, 11 deselected in 0.02s ============================================================

 

 對於類使用作用域,需要使用 @pytest.mark.usefixtures

test_demo11.py

@pytest.mark.usefixtures('fixture_class')
class TestDemo11Class1:
    def test_demo11_func9(self):
        pass

    def test_demo11_func10(self):
        pass

在命令行執行 pytest --setup-show -k TestDemo11Class1 demo/ 結果如下

MacBook-Pro:test_demo fujinjie$ pytest --setup-show -k TestDemo11Class1 demo/
========================================================================================= test session starts ==========================================================================================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir: /Users/fujinjie/PycharmProjects/test_demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collected 14 items / 12 deselected / 2 selected                                                                                                                                                        

demo/test_demo11.py 
      SETUP    C fixture_class
        demo/test_demo11.py::TestDemo11Class1::test_demo11_func9 (fixtures used: fixture_class).
        demo/test_demo11.py::TestDemo11Class1::test_demo11_func10 (fixtures used: fixture_class).
      TEARDOWN C fixture_class

=================================================================================== 2 passed, 12 deselected in 0.04s ===================================================================================

上述結果可見,該類下的所有測試函數都在這個類級別固件作用范圍內

九、自動執行

上述固件,都是通過我們手動指定后才執行的,在pytest中可以在定義固件時指定 autouse 參數讓固件自動執行

conftest.py

@pytest.fixture(scope='function',autouse=True)
def fixture_function():
    pass

@pytest.fixture(scope='module',autouse=True)
def fixture_module():
    pass

@pytest.fixture(scope='session',autouse=True)
def fixture_session():
    pass

test_demo11.py

def test_demo11_func11():
    pass

命令行執行 pytest --setup-show -k func11 demo/

MacBook-Pro:test_demo fujinjie$ pytest --setup-show -k func11 demo/
========================================================================================= test session starts ==========================================================================================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir: /Users/fujinjie/PycharmProjects/test_demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collected 15 items / 14 deselected / 1 selected                                                                                                                                                        

demo/test_demo11.py 
SETUP    S fixture_session
    SETUP    M fixture_module
        SETUP    F fixture_function
        demo/test_demo11.py::test_demo11_func11 (fixtures used: fixture_function, fixture_module, fixture_session).
        TEARDOWN F fixture_function
    TEARDOWN M fixture_module
TEARDOWN S fixture_session

=================================================================================== 1 passed, 14 deselected in 0.02s ===================================================================================

結果可見,所有參數 autouse = True 的 fixture 都自動執行了

十、對固件重命名

fixture默認的名稱為定義是的函數名稱,可以通過 name 選項指定名稱

 conftest.py

@pytest.fixture(name='year')
def fixture_year():
    return 2020

test_demo11.py

def test_demo11_func12(year):
    now_year = 2020
    assert now_year == year

執行結果可見,固件名稱被命名為 year,可供測試函數直接調用

MacBook-Pro:test_demo fujinjie$ pytest --setup-show -k func12 demo/
========================================================================================= test session starts ==========================================================================================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir: /Users/fujinjie/PycharmProjects/test_demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collected 16 items / 15 deselected / 1 selected                                                                                                                                                        

demo/test_demo11.py 
        SETUP    F year
        demo/test_demo11.py::test_demo11_func12 (fixtures used: year).
        TEARDOWN F year

=================================================================================== 1 passed, 15 deselected in 0.02s ===================================================================================

十一、固件參數化

通過固件調用不同的參數,使測試函數應用與不同的測試場景,提高測試函數的復用性

固件參數化需要使用 pytest 內置的固件 request,並通過 request.param 獲取參數

# conftest.py

@pytest.fixture(params=[('參數k1','參數v1'),('參數k2','參數v2'),('參數k3','參數v3')])
def param(request):
    return request.param

@pytest.fixture(autouse=True)
def fixture_param(param):
    print('正在傳入參數%s:%s'% param)
    yield
    print('參數%s:%s處理完畢'% param)

在test_demo11.py中加入test_demo11_func13 測試函數

def test_demo11_func13():
    pass

執行結果

MacBook-Pro:test_demo fujinjie$ pytest --setup-show -s -k func13 demo/
========================================================================================= test session starts ==========================================================================================
platform darwin -- Python 3.7.2, pytest-5.3.5, py-1.8.1, pluggy-0.13.1
rootdir: /Users/fujinjie/PycharmProjects/test_demo
plugins: html-2.0.1, allure-pytest-2.8.10, metadata-1.8.0
collected 51 items / 48 deselected / 3 selected                                                                                                                                                        

demo/test_demo11.py 
        SETUP    F param[('參數k1', '參數v1')]正在傳入參數參數k1:參數v1

        SETUP    F fixture_param (fixtures used: param)
        demo/test_demo11.py::test_demo11_func13[param0] (fixtures used: fixture_param, param, request).參數參數k1:參數v1處理完畢

        TEARDOWN F fixture_param
        TEARDOWN F param[('參數k1', '參數v1')]
        SETUP    F param[('參數k2', '參數v2')]正在傳入參數參數k2:參數v2

        SETUP    F fixture_param (fixtures used: param)
        demo/test_demo11.py::test_demo11_func13[param1] (fixtures used: fixture_param, param, request).參數參數k2:參數v2處理完畢

        TEARDOWN F fixture_param
        TEARDOWN F param[('參數k2', '參數v2')]
        SETUP    F param[('參數k3', '參數v3')]正在傳入參數參數k3:參數v3

        SETUP    F fixture_param (fixtures used: param)
        demo/test_demo11.py::test_demo11_func13[param2] (fixtures used: fixture_param, param, request).參數參數k3:參數v3處理完畢

        TEARDOWN F fixture_param
        TEARDOWN F param[('參數k3', '參數v3')]

=================================================================================== 3 passed, 48 deselected in 0.04s ============================================

注意:與函數參數化 @pyest.mark.parametrize 不同,固件是在定義時使用 params 進行參數化,固件參數化依賴內置的 request 以及屬性 param

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM