Pytest - setup、teardown、fixture的詳細使用


一、setup、teardown使用案例

1、代碼

'''
@Date:2022/2/13  13:02
@Author:一加一
'''
import pytest

def setup_module():
    print("=====整個.py模塊開始前只執行一次:打開瀏覽器=====")

def teardown_module():
    print("=====整個.py模塊結束后只執行一次:關閉瀏覽器=====")

def setup_function():
    print("===每個函數級別用例開始前都執行setup_function===")

def teardown_function():
    print("===每個函數級別用例結束后都執行teardown_function====")

def test_one():
        print("one")

def test_two():
        print("two")

class TestCase():
    def setup_class(self):
        print("====整個測試類開始前只執行一次setup_class====")

    def teardown_class(self):
        print("====整個測試類結束后只執行一次teardown_class====")

    def setup_method(self):
        print("==類里面每個用例執行前都會執行setup_method==")

    def teardown_method(self):
        print("==類里面每個用例結束后都會執行teardown_method==")

    def setup(self):
        print("=類里面每個用例執行前都會執行setup=")

    def teardown(self):
        print("=類里面每個用例結束后都會執行teardown=")

    def test_three(self):
        print("three")

    def test_four(self):
        print("four")

if __name__ == '__main__':
    pytest.main(["-q", "-s", "-ra", "setup_test.py"])

2、執行結果

 二、fixture的優勢

  • 命名方式靈活,不局限於 setup 和teardown 這幾個命名
  • conftest.py 配置里可以實現數據共享,不需要 import 就能自動找到fixture
  • scope="module" 可以實現多個.py 跨文件共享前置
  • scope="session" 以實現多個.py 跨文件使用一個 session 來完成多個用例

三、Fixture參數列表

@pytest.fixture(scope="function", params=None, autouse=False, ids=None, name=None)
def test():
    print("fixture初始化的參數列表")
  • scope:可以理解成fixture的作用域,默認:function,還有class、module、package、session四個【常用】
  • autouse:默認:False,需要用例手動調用該fixture;如果是True,所有作用域內的測試用例都會自動調用該fixture
  • name:默認:裝飾器的名稱,同一模塊的fixture相互調用建議寫個不同的name

注意 session的作用域:是整個測試會話,即開始執行pytest到結束測試

四、Fixture的三種調用方法

1、方式一:函數或類里面方法直接傳fixture的函數參數名稱

  定義fixture跟定義普通函數差不多,唯一區別就是在函數上加個裝飾器@pytest.fixture(),fixture命名不要以test開頭,跟用例區分開。

  fixture是有返回值的,沒有返回值默認為None。

  用例調用fixture的返回值,直接就是把fixture的函數名稱當做變量名稱。

import pytest

@pytest.fixture()
def test1():
    a = "南京"
    return a

def test2(test1):
    assert test1 == "南京"

if __name__ == '__main__':
    pytest.main("-s fixture_test.py")

2、方式二:使用裝飾器@pytest.mark.usefixtures()修飾需要運行的用例

import pytest

@pytest.fixture()
def test1():
    a = "南京"
    print("fixture")
    return a

def test2(test1):
    assert test1 == "南京"

@pytest.fixture()
def login():
    print("請先登錄")

@pytest.mark.usefixtures("login","test1")    
def test3():
    print("用例1:調用fixture") 

@pytest.mark.usefixtures("login")
@pytest.mark.usefixtures("test1")
def test4():
    '''
    疊加usefixtures:如果一個方法或者一個class用例想要同時調用多個fixture,
    可以使用@pytest.mark.usefixture()進行疊加。
    注意疊加順序,先執行的放底層,后執行的放上層。
    :return: 
    '''
    print("用例2:疊加userfixture")

if __name__ == '__main__':
    pytest.main("-s fixture_test.py")

注意:usefixtures與傳fixture區別

 如果fixture有返回值,那么usefixture就無法獲取到返回值,這個是裝飾器usefixture與用例直接傳fixture參數的區別。

當fixture需要用到return出來的參數時,只能講參數名稱直接當參數傳入,不需要用到return出來的參數時,兩種方式都可以。

3、方式三:fixture自動使用autouse=True

當用例很多的時候,每次都傳這個參數,會很麻煩。fixture里面有個參數autouse,默認是False沒開啟的,可以設置為True開啟自動使用fixture功能,這樣用例就不用每次都去傳參了,autouse設置為True,自動調用fixture功能

import pytest

@pytest.fixture(autouse=True)
def login3():
    print("====auto===,自動執行該fixture")

def test5():
    print("用例3:執行前自動執行fixture")

if __name__ == '__main__':
    pytest.main("-s fixture_test.py")

 4、知識點

  • 在類聲明上面加 @pytest.mark.usefixtures() ,代表這個類里面所有測試用例都會調用該fixture
  • 可以疊加多個 @pytest.mark.usefixtures() ,先執行的放底層,后執行的放上層
  • 可以傳多個fixture參數,先執行的放前面,后執行的放后面
  • 如果fixture有返回值,用 @pytest.mark.usefixtures() 是無法獲取到返回值的,必須用傳參的方式(方式一)
  • 添加了 @pytest.fixture ,如果fixture還想依賴其他fixture,需要用函數傳參的方式,不能用 @pytest.mark.usefixtures() 的方式,否則會不生效

五、Fixture之yield實現teardown

  前面講的,其實都是setup的操作,那么現在就來講下teardown是怎么實現的

import pytest

@pytest.fixture(scope="session")
def open():
    # 會話前置操作setup
    print("===打開瀏覽器===")
    test = "測試變量是否返回"
    yield test
    # 會話后置操作teardown
    print("==關閉瀏覽器==")


@pytest.fixture
def login(open):
    # 方法級別前置操作setup
    print(f"輸入賬號,密碼先登錄{open}")
    name = "==我是賬號=="
    pwd = "==我是密碼=="
    age = "==我是年齡=="
    # 返回變量
    yield name, pwd, age
    # 方法級別后置操作teardown
    print("登錄成功")


def test_s1(login):
    print("==用例1==")
    # 返回的是一個元組
    print(login)
    # 分別賦值給不同變量
    name, pwd, age = login
    print(name, pwd, age)
    assert "賬號" in name
    assert "密碼" in pwd
    assert "年齡" in age


def test_s2(login):
    print("==用例2==")
    print(login)

if __name__ == '__main__':
    pytest.main("-s fixture_test.py")

六、Conftest.py的使用

1、什么是conftest.py

可以理解成一個專門存放fixture的配置文件

2、實際開發場景

多個測試用例文件(test_*.py)的所有用例都需要用登錄功能來作為前置操作,那就不能把登錄功能寫到某個用例文件中去了

3、如何解決上述場景問題?

conftest.py的出現,就是為了解決上述問題,單獨管理一些全局的fixture

4、conftest.py配置fixture注意事項

  • pytest會默認讀取conftest.py里面的所有fixture
  • conftest.py 文件名稱是固定的,不能改動
  • conftest.py只對同一個package下的所有測試用例生效
  • 不同目錄可以有自己的conftest.py,一個項目中可以有多個conftest.py
  • 測試用例文件中不需要手動import conftest.py,pytest會自動查找

5、實例

       參考博客:https://www.cnblogs.com/poloyy/p/12663601.html

1)目錄結構

 2)HttprunnerProject目錄下

conftest.py代碼

最頂層的conftest,一般寫全局的fixture,在Web UI自動化中,可能會初始化driver

import pytest

'''最頂層的conftest,一般寫全局的fixture,在Web UI自動化中,可能會初始化driver'''

@pytest.fixture(scope="session")
def login():
    print("====登錄功能,返回賬號,token===")
    name="test"
    token="123bfdaj"
    yield name,token #如果有返回值,可以在yield后面直接寫返回值就好了,如果有多個直接用(返回值1,返回值2)
    print("====退出登錄!!!====")

@pytest.fixture(autouse=True)
def get_info(login):
    name,token=login
    print(f"== 每個用例都調用的外層fixture:打印用戶token: {token} ==")

test_conftest.py代碼

同級目錄下的測試用例

'''跟最頂層的conftest目錄下的測試用例'''
import pytest

def test_get_info(login):
    name,token = login
    print("***基礎用例:獲取用戶個人信息***")
    print(f"用戶名:{name}, token:{token}")

執行結果

 3)baidu目錄下

conftest.py代碼

配置一些針對baidu這個網站的測試用例獨有的fixture,譬如:打開baidu網站

'''baidu目錄下的conftest.py,配置一些針對baidu這個網站的測試用例獨有的fixture,譬如:打開baidu網站'''

import pytest
@pytest.fixture(scope="module")
def open_baidu(login):
    name,token=login
    print(f"###用戶 {name} 打開baidu網站###")

test_baidu_conftest.py

某個功能模塊下的測試用例

'''某個功能模塊下的測試用例'''

def test_case01(open_baidu):
    print("正確打開百度搜索")

執行結果

 

 

 


免責聲明!

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



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