三、Pytest框架实现前后置(固件,夹具)的处理

一、setup_method/teardown_method,setup_class/teardown_class

为什么需要这些功能?
比如:web自动化执行用例之前,请问需要打开浏览器吗?用例执行后需要关闭浏览器?

[pytest]

addopts = -vs
testpaths = ./web_testcase/test_login.py
python_files = test*.py
python_classes = Test*
python_functions = test
markers =
    smoke:冒烟模块
    usermanage:用户管理模块
    productmanage:商品管理模块
import pytest


class TestLogin:

    # 在所有的用例之前只执行一次
    def setup_class(self):
        print("\n在每个类执行前的初始化的工作:比如:创建日志对象,创建数据库的连接,创建接口的请求对象。")

    # 在每个用例之前都会执行一次
    def setup_method(self):  # 以前的方法是 setup 就可以了,现在是 setup_method, 否则可以通过但会警告
        print("\n在执行测试用例之前初始化的代码:打开浏览器,加载网页, 类似 __init__方法")

    def test_login_01(self):
        print("\n测试WEB登录类01")

    def test_login_02(self):
        print("\n测试WEB登录类02")

    def teardown_method(self):  # 以前是teardown就可以了,现在是teardown_method,否则可以通过但会警告
        print("\n在执行测试用例之后的扫尾的代码:关闭浏览器, 类似 __str__方法")

    # 在所有的用例运行结束后执行一次
    def teardown_class(self):
        print("\n在每个类执行后的扫尾的工作:比如:销毁日志对象,销毁数据库的连接,销毁接口的请求对象。")

二、使用@pytest.fixture()装饰器来实现部分用例的前后置

@pytest.fixture(scope="", params="", autouse="", ids="", name="")
# 1. scope:表示的是被@pytest.fixture标记的方法的作用域。function(默认),class,module,package/session.
# 2. params:参数化(支持,列表[],元祖(),字典列表[{},{},{}],字典元祖({},{},{})
# 3. autouse=True:自动使用,默认False
# 4. ids:当使用params参数化时,给每一个值设置一个变量名。意义不大。
# 5. name:给表示的是被@pytest.fixture标记的方法取一个别名,意义不大。

2.1 scope的作用

2.1.1 scope="function" 作用在方法的前后置( setup_method/teardown_method)

import pytest


@pytest.fixture(scope="function")  # 默认就是function
def my_fixture():
    print("\n前后置的一些方法")


class TestLogin:

    def test_login_01(self):
        print("\n测试WEB登录类01")

    def test_login_02(self, my_fixture):
        print("\n测试WEB登录类02")
        
# 这种方法只能实现前置

 

import pytest


@pytest.fixture(scope="function")  # 默认就是function
def my_fixture():
    print("\n前置的一些方法")
    yield
    print("\n后置的一些方法")


class TestLogin:

    def test_login_01(self):
        print("\n测试WEB登录类01")

    def test_login_02(self, my_fixture):
        print("\n测试WEB登录类02")

 # 前置后置都是调用同一个函数,因此,在这个函数可以使用yeild来装饰成一个迭代器,等用例运行结束了,在迭代处理,就可以类似调用后置的处理了。然后再返回函数。

# 如果每个方法都需要调用前后置my_fixture函数,那么可以在每个方法后面加上 my_fixture。另外,就是在参数中加上 autouse = True 就可以了。

2.1.2 scope="class" 作用在类的前后置 (setup_class/teardown_class)

import pytest


@pytest.fixture(scope="class", autouse=True)
def my_fixture():
    print("\n前置的一些方法")
    yield
    print("\n后置的一些方法")


class TestLogin:

    def test_login_01(self):
        print("\n测试WEB登录类01")

    def test_login_02(self):
        print("\n测试WEB登录类02")

# 在所有用例执行之前,初始化前置方法,等所有用例执行结束之后,再后置方法 

 

import pytest


@pytest.fixture(scope="class", autouse=True)
def my_fixture():
    print("\n前置的一些方法")
    yield
    print("\n后置的一些方法")


class TestLogin01:

    def test_login_01(self):
        print("\n测试WEB01登录类01")

    def test_login_02(self):
        print("\n测试WEB01登录类02")


class TestLogin02:

    def test_login_01(self):
        print("\n测试WEB02登录类01")

    def test_login_02(self):
        print("\n测试WEB02登录类02")

# 当存在两个类的时候,每个类都会初始化前后置

2.1.3 scope="module" 作用在模块的前后置

import pytest


@pytest.fixture(scope="module", autouse=True)
def my_fixture():
    print("\n前置的一些方法")
    yield
    print("\n后置的一些方法")


class TestLogin01:

    def test_login_01(self):
        print("\n测试WEB01登录类01")

    def test_login_02(self):
        print("\n测试WEB01登录类02")


class TestLogin02:

    def test_login_01(self):
        print("\n测试WEB02登录类01")

    def test_login_02(self):
        print("\n测试WEB02登录类02")
# 使用module的时候,不管文件中有多少个类,都只会初始化一次前后置

2.2 params的作用

import pytest


@pytest.fixture(scope="function", params=["123", "234", "345"])
def my_fixture():
    print("\n前置的一些方法")
    yield
    print("\n后置的一些方法")


class TestLogin01:

    def test_login_01(self):
        print("\n测试WEB01登录类01")

    def test_login_02(self, my_fixture):
        print("\n测试WEB01登录类02")
        print("----------" + str(my_fixture))

# 存在三个参数,方法就会被执行三次,问题是参数并没有传递过去

 

import pytest


@pytest.fixture(scope="function", params=["123", "234", "345"])
def my_fixture():
    return "success"  # 被fixture标记的函数,可以这样直接传递结果,传递过后会被调用的位置的参数接收


class TestLogin01:

    def test_login_01(self):
        print("\n测试WEB01登录类01")

    def test_login_02(self, my_fixture):
        print("\n测试WEB01登录类02
        print("----------" + str(my_fixture))

 

# 当我们想要将参数传递过去的时候,使用request.param 固定用法。
import pytest


@pytest.fixture(scope="function", params=["123", "234", "345"])
def my_fixture(request):
    return request.param  # 固定用法


class TestLogin01:

    def test_login_01(self):
        print("\n测试WEB01登录类01")

    def test_login_02(self, my_fixture):
        print("\n测试WEB01登录类02")
        print("----------" + str(my_fixture))

 

# 当前后置与传递参数同时使用的情况,发现前后置成功了,但是参数并没有传递成功,因此可以通过yield传递参数
import pytest


@pytest.fixture(scope="function", params=["123", "234", "345"])
def my_fixture(request):
    print("\n前置的一些方法")
    yield
    print("\n后置的一些方法")
    return request.param


class TestLogin01:

    def test_login_01(self):
        print("\n测试WEB01登录类01")

    def test_login_02(self, my_fixture):
        print("\n测试WEB01登录类02")
        print("----------" + str(my_fixture))

 

# 使用yield传递参数,和前后置同时使用,就能完美实现功能
import pytest


@pytest.fixture(scope="function", params=["123", "234", "345"])
def my_fixture(request):
    print("\n前置的一些方法")
    yield request.param
    print("\n后置的一些方法")


class TestLogin01:

    def test_login_01(self):
        print("\n测试WEB01登录类01")

    def test_login_02(self, my_fixture):
        print("\n测试WEB01登录类02")
        print("----------" + str(my_fixture))

2.3 autouse的作用

import pytest


@pytest.fixture(scope="function", autouse=True)
def my_fixture():
    print("\n前置的一些方法")
    yield
    print("\n后置的一些方法")


class TestLogin:

    def test_login_01(self):
        print("\n测试WEB登录类01")

    def test_login_02(self):
        print("\n测试WEB登录类02")
        
# 如果每个方法都需要调用前后置my_fixture函数,那么可以在每个方法后面加上 my_fixture。另外,就是在参数中加上 autouse = True 就可以了。

2.4 ids的使用(不重要)

import pytest


@pytest.fixture(scope="function", params=["123", "234", "345"], ids=["01", "02", "03"])
def my_fixture(request):
    print("\n前置的一些方法")
    yield request.param
    print("\n后置的一些方法")


class TestLogin01:

    def test_login_01(self):
        print("\n测试WEB01登录类01")

    def test_login_02(self, my_fixture):
        print("\n测试WEB01登录类02")
        print("----------" + str(my_fixture))

2.5 name的使用

# 使用name之后,原本的变量名my_fixture传参就不能使用了
import pytest


@pytest.fixture(scope="function", params=["123", "234", "345"], ids=["01", "02", "03"], name="AAA")
def my_fixture(request):
    print("\n前置的一些方法")
    yield request.param
    print("\n后置的一些方法")


class TestLogin01:

    def test_login_01(self):
        print("\n测试WEB01登录类01")

    def test_login_02(self, AAA):
        print("\n测试WEB01登录类02")
        print("----------" + str(AAA))

三、通过conftest.py和@pytest.fixture()结合使用实现全局的前置应用(最常见)

# 在项目中 my_fixture 并不是和代码在一个文件中,因为 my_fixture的作用域只能在当前文件中,所以一般通过conftest.py和@pytest.fixture()结合使用实现全局的前置应用(比如:
# 项目的全局登录,模块的全局处理),可以理解为将 my_fixture的代码放在 conftest.py 中
1. conftest.py文件是单独存放的一个夹具配置文件,名称是不能更改。 2. 用处可以在不同的py文件中使用同一个fixture函数。 3. 原则上conftest.py需要和运行的用例放到统一层。并且不需要做任何的imprt导入的操作。

修改项目架构如下:

 

# testcase/interface_testcase/conftest.py
import pytest


@pytest.fixture(scope="function")
def interface_fixture():
    print("\n接口前置的一些方法")
    yield
    print("\n接口后置的一些方法")
# testcase\interface_testcase\test_interface.py
def test_interface(interface_fixture):
    print("测试接口函数")
    print("----------" + str(interface_fixture))

class TestInterfaceCase:
    def test_interface(self, interface_fixture):
        print("测试接口类方法")
        print("----------" + str(interface_fixture))
# testcase\web_testcase\conftest.py

import pytest

@pytest.fixture(scope="function")
def web_fixture():
    print("\nWEB前置的一些方法")
    yield
    print("\nWEB后置的一些方法")
# testcase\web_testcase\test_web.py
class TestWebCase:

    def test_web_01(self):
        print("\n测试WEB类方法01")

    def test_web_02(self, all_fixture, web_fixture):
        print("\n测试WEB类方法02")
        print("----------" + str(all_fixture))
        print("----------" + str(web_fixture))
# testcase\conftest.py
import pytest

@pytest.fixture(scope="function")
def all_fixture():
    print("\n全局前置的一些方法")
    yield
    print("\n全局后置的一些方法")
# all.py
import pytest

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

addopts = -vs
testpaths = ./
python_files = test*.py
python_classes = Test*
python_functions = test
markers =
    smoke:冒烟模块
    usermanage:用户管理模块
    productmanage:商品管理模块

 

posted on 2024-07-27 20:20  软饭攻城狮  阅读(4)  评论(0编辑  收藏  举报

导航