遇一山,过一山,处处有风景;只要勇敢向前,一路尽是繁花盛开。 | (点击查看→)【测试干货】python/java自动化、持续集成、性能、测开、简历、笔试面试等

pytest简易教程(04):fixture简介及调用

 

pytest简易教程汇总,详见https://www.cnblogs.com/uncleyong/p/17982846 

前言

上一篇我们介绍了固件,通过示例可以看到,一个模块中,固件会对其作用范围内的所有用例起作用;

其实这样很不灵活,比如我们只希望部分测试用例执行某个固件,通过setup和teardown是实现不了的;

但是,通过fixture就可以根据需要自定义测试用例的前置、后置操作;

fixture是通过yield来区分前后置的,前后置均可以单独存在,fixture如果有后置,前置不报错就都会执行,前置报错后置就不会执行。

 

fixture的优势

1、与setup、teardown类似,fixture提供了测试执行前和测试执行后的处理,但是又比setup、teardown更灵活好用,比如:fixture命名更加灵活,不局限于setup和teardown

2、conftest.py配置里可以实现数据共享,可以方便管理、修改和查看fixture函数,并且不需要import就能自动找到fixture

3、fixture可用于封装数据,也可用于封逻辑动作,使用范围非常广

 

fixture介绍

fixture装饰器来标记固定的工厂函数,在其他函数、类、模块或整个工程调用它时会被激活并优先执行,通常会被用于完成预置处理和重复操作。

源码:

def fixture(  # noqa: F811
    fixture_function: Optional[FixtureFunction] = None,
    *,
    scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = "function",
    params: Optional[Iterable[object]] = None,
    autouse: bool = False,
    ids: Optional[
        Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]]
    ] = None,
    name: Optional[str] = None,
) -> Union[FixtureFunctionMarker, FixtureFunction]:

 

方法:fixture(scope="function", params=None, autouse=False, ids=None, name=None)

常用参数:

  • scope:被@pytest.fixture标记的方法的作用域,默认是function,还可以是class、module、package、session。(注:下一篇详解)
  • params:用于给fixture传参,可实现数据基于fixture的数据驱动,接收一个可以迭代的对象,比如列表[]、元组()、字典列表{[],[],[]}、字典元组{(),(),()},提供参数数据供调用fixture的用例使用;传进去的参数,可以用request.param调用
  • autouse:是否自动运行,是一个布尔值,默认为False不会自动执行,需要手动调用;当它为True时,作用域内的测试用例都会自动调用该fixture
  • ids:用例标识id,每个ids和params一一对应,如果没有id,将从params自动产生
  • name:给被@pytest.fixture标记的方法取一个别名,如果使用了name,那只能将name传入,函数名不再生效

 

fixture的调用

测试用例如何调用fixture呢?

 

函数引用/参数引用

将fixture名称作为测试用例函数/方法的参数;另外,如果fixture有返回值,必须用这种方式,否则获取不到返回值(比如:@pytest.mark.usefixtures()这种方式就获取不到返回值,详见:https://www.cnblogs.com/uncleyong/p/17957896

函数引用:测试类中测试方法形参是测试类外被@pytest.fixture()标记的测试函数,也就是说,fixture标记的函数可以应用于测试类内部

参数引用:测试类中测试方法形参是当前测试类中被@pytest.fixture()标记的方法

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧
# @wx :ren168632201
# @Blog :https://www.cnblogs.com/uncleyong/
import pytest

@pytest.fixture()
def fun():
    print("---fixture")

@pytest.fixture()
def fun2():
    print("---fixture2")

def test_a(fun):
    print("--------------test_a")

class Test01:
    def test_b(self, fun2):
        print("--------------test_b")

    def test_c(self, fun3):
        print("--------------test_c")

    @pytest.fixture()
    def fun3(self):
        print("---fixture3")

  

结果:

 

加装饰器:@pytest.mark.usefixtures(fixture_name, ...)

测试用例上加装饰器

可以多个fixture参数,放前面的先执行,放后面的后执行,也就是说,执行顺序和usefixtures后面引用顺序对应

示例一:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧
# @wx :ren168632201
# @Blog :https://www.cnblogs.com/uncleyong/
import pytest

@pytest.fixture()
def fun():
    print("---fixture")

@pytest.fixture()
def fun2():
    print("---fixture2")

def test_a(fun):
    print("--------------test_a")

class Test01:
    def test_b(self, fun2):
        print("--------------test_b")
    @pytest.mark.usefixtures('fun2','fun')
    def test_c(self):
        print("--------------test_c")

  

结果:先调用fun2,然后调用fun

 

示例二:

可以多个装饰器,先执行的放底层,后执行的放上层

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧
# @wx :ren168632201
# @Blog :https://www.cnblogs.com/uncleyong/
import pytest

@pytest.fixture()
def fun():
    print("---fixture")

@pytest.fixture()
def fun2():
    print("---fixture2")

def test_a(fun):
    print("--------------test_a")

@pytest.mark.usefixtures('fun')
@pytest.mark.usefixtures('fun2')
class Test01:
    def test_b(self):
        print("--------------test_b")

    def test_c(self):
        print("--------------test_c")

  

结果

 

示例三:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧
# @wx :ren168632201
# @Blog :https://www.cnblogs.com/uncleyong/
import pytest

@pytest.fixture()
def fun():
    print("---fixture")

@pytest.fixture()
def fun2():
    print("---fixture2")

def test_a(fun):
    print("--------------test_a")

class Test01:
    def test_b(self):
        print("--------------test_b")

    @pytest.mark.usefixtures('fun')
    def test_c(self, fun2):
        print("--------------test_c")

  

结果:同时有装饰器和引用,装饰器先执行

 

测试类上加装饰器

类中所有测试用例都会调用该fixture

示例一:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧
# @wx :ren168632201
# @Blog :https://www.cnblogs.com/uncleyong/
import pytest

@pytest.fixture()
def fun():
    print("---fixture")

@pytest.fixture()
def fun2():
    print("---fixture2")

def test_a(fun):
    print("--------------test_a")

@pytest.mark.usefixtures('fun2')
class Test01:
    def test_b(self):
        print("--------------test_b")
    def test_c(self, fun):
        print("--------------test_c")

  

结果:同时有装饰器和引用,装饰器先执行

 

示例二:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧
# @wx :ren168632201
# @Blog :https://www.cnblogs.com/uncleyong/
import pytest

@pytest.fixture()
def fun():
    print("---fixture")

@pytest.fixture()
def fun2():
    print("---fixture2")

def test_a(fun):
    print("--------------test_a")

@pytest.mark.usefixtures('fun2')
class Test01:
    def test_b(self):
        print("--------------test_b")

    @pytest.mark.usefixtures('fun')
    def test_c(self):
        print("--------------test_c")

  

结果:方法和类上都有装饰器,方法上装饰器优先执行

 

总结:

@pytest.mark.usefixtures('fun2')
@pytest.mark.usefixtures('fun')
等价于:
@pytest.mark.usefixtures('fun','fun2')

 

自动适配:fixture设置autouse=True

影响作用域内所有用例

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧
# @wx :ren168632201
# @Blog :https://www.cnblogs.com/uncleyong/
import pytest

@pytest.fixture()
def fun():
    print("---fixture")

@pytest.fixture(autouse=True)
def fun2():
    print("---fixture2")

def test_a():
    print("--------------test_a")

class Test01:
    def test_b(self):
        print("--------------test_b")
    def test_c(self):
        print("--------------test_c")

  

结果:每个测试用例都执行了fun2

 

fixture嵌套

不能用@pytest.mark.usefixtures

示例:两个fixture,fun依赖login

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : 韧
# @wx :ren168632201
# @Blog :https://www.cnblogs.com/uncleyong/
import pytest

@pytest.fixture()
def login():
    print("---登录")

@pytest.fixture()
def fun(login):
    print("---fun")

# 下面写法报错
# @pytest.fixture()
# @pytest.mark.usefixtures(login)
# def fun():
#     print("---fun")

# @pytest.mark.usefixtures(fun)  # 报错
def test_a(fun):
    print("--------------test_a")

 

结果:

 

posted @ 2024-02-23 20:44  全栈测试笔记  阅读(746)  评论(1编辑  收藏  举报
浏览器标题切换
浏览器标题切换end