日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

pytest 的前置與后置處理

Pytest貼心的提供了類似setup、teardown的方法,并且還超過四個(gè),一共有十種

  • 模塊級別:setup_module、teardown_module

  • 函數(shù)級別:setup_function、teardown_function,不在類中的方法

  • 類級別:setup_class、teardown_class

  • 方法級別:setup_method、teardown_method

  • 方法細(xì)化級別:setup、teardown

setup和teardown的詳細(xì)使用

代碼

#!/usr/bin/env Python/ target=_blank class=infotextkey>Python# -*- coding: utf-8 -*-import pytest

def setup_module():    print("=====整個(gè).py模塊開始前只執(zhí)行一次:登錄=====")
def teardown_module():    print("=====整個(gè).py模塊結(jié)束后只執(zhí)行一次:數(shù)據(jù)清理=====")
def setup_function():    print("===每個(gè)函數(shù)級別用例開始前都執(zhí)行setup_function===")
def teardown_function():    print("===每個(gè)函數(shù)級別用例結(jié)束后都執(zhí)行teardown_function====")
def test_one():    print("1")
def test_two():    print("2")
class TestCase():    def setup_class(self):        print("====整個(gè)測試類開始前只執(zhí)行一次setup_class====")
    def teardown_class(self):        print("====整個(gè)測試類結(jié)束后只執(zhí)行一次teardown_class====")
    def setup_method(self):        print("==測試類里面每個(gè)用例執(zhí)行前都會執(zhí)行setup_method==")
    def teardown_method(self):        print("==測試類里面每個(gè)用例結(jié)束后都會執(zhí)行teardown_method==")
    def setup(self):        print("=測試類里面每個(gè)用例執(zhí)行前都會執(zhí)行setup=")
    def teardown(self):        print("=測試類里面每個(gè)用例結(jié)束后都會執(zhí)行teardown=")
    def test_three(self):        print("3")
    def test_four(self):        print("4")

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

運(yùn)行結(jié)果

C:Userschenyongzhi11.virtualenvsapi-test-project-FfYYNBU1Scriptspython.exe D:/apk_api/api-test-project/debug/debug_pytest.py =====整個(gè).py模塊開始前只執(zhí)行一次:登錄========每個(gè)函數(shù)級別用例開始前都執(zhí)行setup_function===1.===每個(gè)函數(shù)級別用例結(jié)束后都執(zhí)行teardown_function=======每個(gè)函數(shù)級別用例開始前都執(zhí)行setup_function===2.===每個(gè)函數(shù)級別用例結(jié)束后都執(zhí)行teardown_function========整個(gè)測試類開始前只執(zhí)行一次setup_class======測試類里面每個(gè)用例執(zhí)行前都會執(zhí)行setup_method==3.==測試類里面每個(gè)用例結(jié)束后都會執(zhí)行teardown_method====測試類里面每個(gè)用例執(zhí)行前都會執(zhí)行setup_method==4.==測試類里面每個(gè)用例結(jié)束后都會執(zhí)行teardown_method======整個(gè)測試類結(jié)束后只執(zhí)行一次teardown_class=========整個(gè).py模塊結(jié)束后只執(zhí)行一次:數(shù)據(jù)清理=====
4 passed in 0.33s
進(jìn)程已結(jié)束,退出代碼0

 

  • 模塊級別:模塊級別的初始化、清除分別再整個(gè)模塊的測試用例執(zhí)行錢后執(zhí)行,并且只執(zhí)行一次

  • 類級別:類級別的初始化、清除分別再整個(gè)類的測試用例執(zhí)行前后執(zhí)行,并且只執(zhí)行一次

  • 方法級別:方法級別的初始化、清除分別在類的每個(gè)測試方法執(zhí)行前后執(zhí)行,并且每個(gè)用例執(zhí)行一次

    注:上述都是針對整個(gè)腳本全局生效

 

fixture的詳細(xì)使用

fixture的優(yōu)勢

  • 名命靈活,不局限與setupteardown 的名命

  • coNFTest.py 配置可以實(shí)現(xiàn)數(shù)據(jù)共享,不需要import 就能自動找到fixture

  • scope="module" 實(shí)現(xiàn)多py文件共享前置

  • scope="session" 實(shí)現(xiàn)多個(gè)py文件使用一個(gè)session完成多用例

     

fixture參數(shù)列表

@pytest.fixture(scope="function", params=None, autouse=False, ids=None, name=None)def test():    print("fixture初始化的參數(shù)列表")

參數(shù)列表

  • scope:可以理解成fixture的作用域,默認(rèn):function,還有class、module、package、session四個(gè)【常用】

  • autouse:默認(rèn):False,需要用例手動調(diào)用該fixture;如果是True,所有作用域內(nèi)的測試用例都會自動調(diào)用該fixture

  • name:默認(rèn):裝飾器的名稱,同一模塊的fixture相互調(diào)用建議寫個(gè)不同的name

注意

session的作用域:是整個(gè)測試會話,即開始執(zhí)行pytest到結(jié)束測試

測試用例調(diào)用fixture的方式

  1. 將fixture名稱作為測試用例函數(shù)的輸入?yún)?shù)

  2. 測試用例加上裝飾器:@pytest.mark.usefixtures(fixture_name)

  3. fixture設(shè)置autouse=True

    1. 將fixture名稱作為測試用例函數(shù)的輸入?yún)?shù)

import pytest

# 調(diào)用方式一@pytest.fixturedef login():    print("輸入賬號,密碼先登錄")

def test_s1(login):    print("用例 1:登錄之后其它動作 111")

def test_s2():  # 不傳 login    print("用例 2:不需要登錄,操作 222")

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

結(jié)果

============================= test session starts =============================platform win32 -- Python 3.9.5, pytest-7.3.1, pluggy-1.0.0rootdir: D:apk_apiapi-test-projectdebugplugins: Faker-18.4.0collected 2 items
debug_pytest.py 輸入賬號,密碼先登錄用例 1:登錄之后其它動作 111.用例 2:不需要登錄,操作 222.
============================== 2 passed in 0.14s ==============================
進(jìn)程已結(jié)束,退出代碼0

方式2:測試用例加上裝飾器:@pytest.mark.usefixtures(fixture_name)

import pytest

# 調(diào)用方式一@pytest.fixturedef login():    print("輸入賬號,密碼先登錄")

# 調(diào)用方式二@pytest.fixturedef login2():    print("please輸入賬號,密碼先登錄")

@pytest.mark.usefixtures("login2", "login")def test_s11():    print("用例 11:登錄之后其它動作 111")

輸出:

============================= test session starts =============================collecting ... collected 1 item
teat_learn03.py::test_s11 please輸入賬號,密碼先登錄輸入賬號,密碼先登錄PASSED                                         [100%]用例 11:登錄之后其它動作 111
============================== 1 passed in 0.01s ==============================
Process finished with exit code 0

注意:

  • 在類聲明上面加 @pytest.mark.usefixtures() ,代表這個(gè)類里面所有測試用例都會調(diào)用該fixture

  • 可以疊加多個(gè) @pytest.mark.usefixtures() ,先執(zhí)行的放底層,后執(zhí)行的放上層

  • 可以傳多個(gè)fixture參數(shù),先執(zhí)行的放前面,后執(zhí)行的放后面

  • 如果fixture有返回值,用 @pytest.mark.usefixtures() 是無法獲取到返回值的,必須用傳參的方式(方式一)

  • 方式3:fixture設(shè)置autouse=True

  • import pytest
    
    # 調(diào)用方式三
    @pytest.fixture(autouse=True)def login3():    print("====所有作用域內(nèi)的測試用例都會自動調(diào)用該fixture===")
    
    def test_s1(login3):    print("用例 1:登錄之后其它動作 111")
    
    def test_s2():  # 不傳 login    print("用例 2:不需要登錄,操作 222")
    
    # 不是test開頭,加了裝飾器也不會執(zhí)行fixture@pytest.mark.usefixtures("login3")def loginss():    print(123)
    
    
  • ====所有作用域內(nèi)的測試用例都會自動調(diào)用該fixture===PASSED                                          [ 50%]用例 1:登錄之后其它動作 111
    teat_learn03.py::test_s2 ====所有作用域內(nèi)的測試用例都會自動調(diào)用該fixture===PASSED                                          [100%]用例 2:不需要登錄,操作 222
    
    ============================== 2 passed in 0.02s ==============================
    
    
fixture的實(shí)例化順序
  • 較高 scope 范圍的fixture(session)在較低 scope 范圍的fixture( function 、 class )之前實(shí)例化【session > package > module > class > function】

  • 具有相同作用域的fixture遵循測試函數(shù)中聲明的順序,并遵循fixture之間的依賴關(guān)系【在fixture_A里面依賴的fixture_B優(yōu)先實(shí)例化,然后到fixture_A實(shí)例化】

  • 自動使用(autouse=True)的fixture將在顯式使用(傳參或裝飾器)的fixture之前實(shí)例化

import pytest
order = []

@pytest.fixture(scope="session")def s1():    order.Append("s1")

@pytest.fixture(scope="module")def m1():    order.append("m1")

@pytest.fixturedef f1(f3, a1):    # 先實(shí)例化f3, 再實(shí)例化a1, 最后實(shí)例化f1    order.append("f1")    assert f3 == 123

@pytest.fixturedef f3():    order.append("f3")    a = 123    yield a

@pytest.fixturedef a1():    order.append("a1")

@pytest.fixturedef f2():    order.append("f2")

def test_order(f1, m1, f2, s1):    # m1、s1在f1后,但因?yàn)閟cope范圍大,所以會優(yōu)先實(shí)例化    assert order == ["s1", "m1", "f3", "a1", "f1", "f2"]

執(zhí)行結(jié)果:斷言成功

關(guān)于fixture的注意點(diǎn)

添加了 @pytest.fixture ,如果fixture還想依賴其他fixture,需要用函數(shù)傳參的方式,不能用 @pytest.mark.usefixtures() 的方式,否則會不生效

@pytest.fixture(scope="session")def open():    print("===打開瀏覽器===")
@pytest.fixture# @pytest.mark.usefixtures("open") 不可?。。?!不生效!!!def login(open):    # 方法級別前置操作setup    print(f"輸入賬號,密碼先登錄{open}")

fixture的后置teardown

用fixture實(shí)現(xiàn)teardown并不是一個(gè)獨(dú)立的函數(shù),而是用 yield 關(guān)鍵字來開啟teardown操作(yield 之前是前置,之后是后置)

import pytest


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


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


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

 

輸出:

============================= test session starts =============================
collecting ... collected 1 item

test_05.py::test_s2 ===打開瀏覽器===
輸入賬號,密碼先登錄---測試變量是否返回
PASSED                                               [100%]==用例2==
('==我是賬號==', '==我是密碼==', '==我是年齡==')
登錄成功
==關(guān)閉瀏覽器==

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

 

yield注意事項(xiàng)

  • 如果yield前面的代碼,即setup部分已經(jīng)拋出異常了,則不會執(zhí)行yield后面的teardown內(nèi)容

  • 如果測試用例拋出異常,yield后面的teardown內(nèi)容還是會正常執(zhí)行

addfinalizer

在用法上,addfinalizer跟yield是不同的,需要你去注冊作為終結(jié)器使用的函數(shù)。

import pytest


@pytest.fixture()
def demo_fixture(request):
    print("n這個(gè)fixture在每個(gè)case前執(zhí)行一次")

    def demo_finalizer():
        print("n在每個(gè)case完成后執(zhí)行的teardown")

    # 注冊demo_finalizer為終結(jié)函數(shù)
    request.addfinalizer(demo_finalizer)


def test_01(demo_fixture):
    print("n===執(zhí)行了case: test_01===")


def test_02(demo_fixture):
    print("n===執(zhí)行了case: test_02===")


def test_03(demo_fixture):
    print("n===執(zhí)行了case: test_03===")

 

輸出:

============================= test session starts =============================
collecting ... collected 3 items

test_06.py::test_01 
這個(gè)fixture在每個(gè)case前執(zhí)行一次
PASSED                                               [ 33%]
===執(zhí)行了case: test_01===

在每個(gè)case完成后執(zhí)行的teardown

test_06.py::test_02 
這個(gè)fixture在每個(gè)case前執(zhí)行一次
PASSED                                               [ 66%]
===執(zhí)行了case: test_02===

在每個(gè)case完成后執(zhí)行的teardown

test_06.py::test_03 
這個(gè)fixture在每個(gè)case前執(zhí)行一次
PASSED                                               [100%]
===執(zhí)行了case: test_03===

在每個(gè)case完成后執(zhí)行的teardown


============================== 3 passed in 0.04s ==============================

Process finished with exit code 0

 

yield與addfinalizer的區(qū)別

1. addfinalizer可以注冊多個(gè)終結(jié)函數(shù)。
import pytest

import pytest


@pytest.fixture()
def demo_fixture(request):
    print("n這個(gè)fixture在每個(gè)case前執(zhí)行一次")

    def demo_finalizer():
        print("n在每個(gè)case完成后執(zhí)行的teardown")

    def demo_finalizer2():
        print("n在每個(gè)case完成后執(zhí)行的teardown2")

    def demo_finalizer3():
        print("n在每個(gè)case完成后執(zhí)行的teardown3")

    # 注冊demo_finalizer為終結(jié)函數(shù)
    request.addfinalizer(demo_finalizer)
    request.addfinalizer(demo_finalizer2)
    request.addfinalizer(demo_finalizer3)


def test_01(demo_fixture):
    print("n===執(zhí)行了case: test_01===")


def test_02(demo_fixture):
    print("n===執(zhí)行了case: test_02===")


def test_03(demo_fixture):
    print("n===執(zhí)行了case: test_03===")

 

輸出:

============================= test session starts =============================
collecting ... collected 3 items

test_06.py::test_01 
這個(gè)fixture在每個(gè)case前執(zhí)行一次
PASSED                                               [ 33%]
===執(zhí)行了case: test_01===

在每個(gè)case完成后執(zhí)行的teardown3

在每個(gè)case完成后執(zhí)行的teardown2

在每個(gè)case完成后執(zhí)行的teardown

test_06.py::test_02 
這個(gè)fixture在每個(gè)case前執(zhí)行一次
PASSED                                               [ 66%]
===執(zhí)行了case: test_02===

在每個(gè)case完成后執(zhí)行的teardown3

在每個(gè)case完成后執(zhí)行的teardown2

在每個(gè)case完成后執(zhí)行的teardown

test_06.py::test_03 
這個(gè)fixture在每個(gè)case前執(zhí)行一次
PASSED                                               [100%]
===執(zhí)行了case: test_03===

在每個(gè)case完成后執(zhí)行的teardown3

在每個(gè)case完成后執(zhí)行的teardown2

在每個(gè)case完成后執(zhí)行的teardown


============================== 3 passed in 0.04s ==============================

Process finished with exit code 0

 

可以看到,注冊的3個(gè)函數(shù)都被執(zhí)行了,但是要注意的是執(zhí)行順序,與注冊的順序相反

2. 當(dāng)setUp的代碼執(zhí)行錯(cuò)誤,addfinalizer依舊會執(zhí)行

conftest.py的詳細(xì)講解

可以理解成一個(gè)專門存放fixture的配置文件,如果多個(gè)測試用例文件(test_*.py)的所有用例都需要用登錄功能來作為前置操作,那就不能把登錄功能寫到某個(gè)用例文件中去了,conftest.py的出現(xiàn),就是為了解決上述問題,單獨(dú)管理一些全局的fixture。

conftest.py配置fixture注意事項(xiàng)

  • pytest會默認(rèn)讀取conftest.py里面的所有fixture

  • conftest.py 文件名稱是固定的,不能改動

  • conftest.py只對同一個(gè)package下的所有測試用例生效

  • 不同目錄可以有自己的conftest.py,一個(gè)項(xiàng)目中可以有多個(gè)conftest.py

  • 測試用例文件中不需要手動import conftest.py,pytest會自動查找

conftest.py使用舉例

conftest.py文件(scope=“session”)

import pytest


@pytest.fixture(scope="session")
def login():
    print("輸入賬號密碼")
    yield
    print("清理數(shù)據(jù)完成")

 

case文件:

import pytest


class TestLogin1():
    def test_1(self, login):
        print("用例1")

    def test_2(self):
        print("用例2")

    def test_3(self, login):
        print("用例3")


if __name__ == '__main__':
    pytest.main()

輸出:

輸入賬號密碼
PASSED                                  [ 33%]用例1
PASSED                                  [ 66%]用例2
PASSED                                  [100%]用例3
清理數(shù)據(jù)完成

 

可以看出,conftest.py內(nèi)的fixture方法的作用范圍是session,調(diào)用時(shí),整個(gè).py文件只會調(diào)用一次

conftest.py注意事項(xiàng)

  • conftest.py的作用域與Python變量作用域相同

  • 內(nèi)層包內(nèi)conftest.py不允許被其它包的測試類或方法使用,相當(dāng)于本地變量

  • 外層conftest.py可被內(nèi)層測試類和方法使用,相當(dāng)于全局變量

分享到:
標(biāo)簽:pytest
用戶無頭像

網(wǎng)友整理

注冊時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定