python + pytest 之 fixture+yield 使用详解

一、前言

  用例执行完之后,如需要环境恢复和清除数据操作,可以使用yield来实现。fixture的teardown操作并不是独立的函数,

用yield关键字呼唤teardown操作。fixture通过scope参数控制setup级别,既然有setup作为测试用例之前的操作,那么测试

用例执行完后肯定也有teardown操作。

  yield是一个关键字,它不是单独存在的,要写在fixture标记的固件中。

       fixture固件函数 + yield关键字,可以实现setup环境预设和teardown环境恢复。

  如果测试用例中的代码出现异常或者断言失败,并不会影响他的固件fixture中yield后的代码执行;但是如果固件fixture中的yield

之前的代码(也是相当于setup部分的代码),出现错误或断言失败,那么yield后的代码将不会再执行,当然test测试用例方法也不会执行的。

 

二、scope="function"

  当pytest.fixture(scope="function")时,pytest的yield类似unittest的teardown。每个方法(函数)之前都会执行一次。

  1.文件:test_func1.py

import pytest

@pytest.fixture(scope="function")
def login():
    print("登录成功")
    yield  # 让步,先暂时停一下。下面的代码相当于teardown
    print("用例执行完成,关闭会话")
    print("--------------------------------------------")

def test1(login):
    print("操作1...")

def test2(login):
    print("操作2...")

def test3(login):
    print("操作3...")

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

============================= test session starts ============================
platform win32 -- Python 3.8.5, pytest-5.4.2, py-1.11.0, pluggy-0.13.1
rootdir: D:\PycharmProjects\requests_fuxi_230313\api
plugins: allure-pytest-2.8.6, assume-2.4.3
collected 3 items

test_func1.py 登录成功
操作1...
.用例执行完成,关闭会话
--------------------------------------------
登录成功
操作2...
.用例执行完成,关闭会话
--------------------------------------------
登录成功
操作3...
.用例执行完成,关闭会话
--------------------------------------------


============================== 3 passed in 0.05s =============================

2.文件:test_func2.py

import pytest

@pytest.fixture(scope="function")
def login():
    print("登录成功")
    yield  # 让步,先暂时停一下。下面的代码相当于teardown
    print("用例执行完成,关闭会话")
    print("--------------------------------------------")

def test1():
    print("操作1...")

def test2(login):
    print("操作2...")

def test3():
    print("操作3...")

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

========================== test session starts ============================
platform win32 -- Python 3.8.5, pytest-5.4.2, py-1.11.0, pluggy-0.13.1
rootdir: D:\PycharmProjects\requests_fuxi_230313\api
plugins: allure-pytest-2.8.6, assume-2.4.3
collected 3 items

test_func2.py 操作1...
.登录成功
操作2...
.用例执行完成,关闭会话
--------------------------------------------
操作3...
.

========================== 3 passed in 0.05s ===============================

三、scope=“module”

  fixture参数scope=“module”的作用范围是某个.py文件(该文件中只会执行一次)。

1.文件:test_func3.py

import pytest

@pytest.fixture(scope="module")
def login():
    print("登录成功")
    yield  # 让步,先暂时停一下。下面的代码相当于teardown_class
    print("用例执行完成,关闭会话")
    print("--------------------------------------------")

def test1(login): # 调用login成功
    print("操作1...")

def test2(login): # 调用login不执行
    print("操作2...")

def test3(login): # 调用login不执行
    print("操作3...")

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

============================ test session starts ==========================
platform win32 -- Python 3.8.5, pytest-5.4.2, py-1.11.0, pluggy-0.13.1
rootdir: D:\PycharmProjects\requests_fuxi_230313\api
plugins: allure-pytest-2.8.6, assume-2.4.3
collected 3 items

test_func3.py 登录成功
操作1...
.操作2...
.操作3...
.用例执行完成,关闭会话
--------------------------------------------


============================= 3 passed in 0.05s ============================

2.文件:test_func4.py

import pytest

@pytest.fixture(scope="module")
def login():
    print("登录成功")
    yield  # 让步,先暂时停一下。下面的代码相当于teardown_class
    print("用例执行完成,关闭会话")
    print("--------------------------------------------")

def test1():
    print("操作1...")

def test2(login): # 调用login方法
    print("操作2...")

def test3():
    print("操作3...")

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

============================ test session starts ==========================
platform win32 -- Python 3.8.5, pytest-5.4.2, py-1.11.0, pluggy-0.13.1
rootdir: D:\PycharmProjects\requests_fuxi_230313\api
plugins: allure-pytest-2.8.6, assume-2.4.3
collected 3 items

test_func4.py 操作1...
.登录成功
操作2...
.操作3...
.用例执行完成,关闭会话
--------------------------------------------


============================ 3 passed in 0.05s ===========================

 

四、scope=“class”

  fixture参数scope=“class”的作用范围是某个class测试类(该测试类中只会执行一次)。

文件:test_func5.py

import pytest

@pytest.fixture(scope="class")
def login():
    print("登录成功")
    yield  # 让步,先暂时停一下。下面的代码相当于teardown_class
    print("用例执行完成,关闭会话")
    print("--------------------------------------------")
class TestCase:
    def test1(self):
        print("操作1...")

    def test2(self, login): # 调用login成功
        print("操作2...")

    def test3(self, login): # 调用login不执行
        print("操作3...")

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

============================= test session starts ============================
platform win32 -- Python 3.8.5, pytest-5.4.2, py-1.11.0, pluggy-0.13.1
rootdir: D:\PycharmProjects\requests_fuxi_230313\api
plugins: allure-pytest-2.8.6, assume-2.4.3
collected 3 items

test_func5.py 操作1...
.登录成功
操作2...
.操作3...
.用例执行完成,关闭会话
--------------------------------------------


============================= 3 passed in 0.05s ===============================

五、yield遇到异常

  1.如果其中一个test用例抛出异常,是不会影响yield后面的teardown执行,且各测试用例运行结果互不影响。

文件:test_func6.py

import pytest

@pytest.fixture(scope="module")
def login():
    print("登录成功")
    yield  # 让步,先暂时停一下。下面的代码相当于teardown_class
    print("用例执行完成,关闭会话")
    print("--------------------------------------------")

def test1(login):
    print("操作1...")

def test2(login):
    print("操作2...")
    # 如果一个用例抛出异常了,是不影响其他用例的执行
    raise Exception()  # 手动抛出异常

def test3(login):
    print("操作3...")

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

============================== test session starts =============================
platform win32 -- Python 3.8.5, pytest-5.4.2, py-1.11.0, pluggy-0.13.1
rootdir: D:\PycharmProjects\requests_fuxi_230313\api
plugins: allure-pytest-2.8.6, assume-2.4.3
collected 3 items

test_func6.py 登录成功
操作1...
.操作2...
F操作3...
.用例执行完成,关闭会话
--------------------------------------------


=================================== FAILURES ====================================
__________________________________ test2 ________________________________________

login = None

   def test2(login):
        print("操作2...")
        # 如果一个用例抛出异常了,是不影响其他用例的执行
>       raise Exception() # 手动抛出异常
E       Exception

test_func6.py:17: Exception
============================ short test summary info ============================
FAILED test_func6.py::test2 - Exception
============================= 1 failed, 2 passed in 0.34s =======================

 

posted @ 2023-05-17 01:21  乌鸦哥  阅读(644)  评论(0编辑  收藏  举报