pytest--测试用例调用fixture、fixture传递测试数据(三)

1、简介

在pytest中,fixture是一种用于在测试前后进行预备和清理工作的代码处理机制。它有独立的命名,并通过声明激活。与unittest中的setup和teardown相比,fixture有显著改进,包括:

  • 命名方式灵活,不局限于 setup 和 teardown 这几个命名
  • conftest.py 配置里可以实现数据共享,不需要 import 就能自动找到 fixture
  • scope=“module” 可以实现多个 .py 跨文件共享前置
  • scope=“session” 可以实现多个 .py 跨文件使用一个 session 来完成多个用例

2、fixture参数解释

# -*- coding: utf-8 -*-
# @Time    : 2023/11/21 14:57
# @Author  : 梗小旭
# @File    : conftest.py

import pytest


@pytest.fixture(scope="function", params=None, autouse=False, ids=None, name=None)
def login_page():
    print("开始登录...")
  • scope:可以理解成 fixture 的作用范围,默认:function,还有 class、module、package、session
    • function 的作用域:每一个函数或方法都会调用
    • class 的作用域:每一个类调用一次,一个类中可以有多个方法
    • module 的作用域:每一个 .py 文件调用一次,该文件内又有多个 function 和 class
    • session 的作用域:是多个文件调用一次,可以跨 .py 文件调用,每个 .py 文件就是 module
  • params:一个可选的参数列表,它将导致多个参数调用 fixture 功能和所有测试使用它
  • autouse:默认:False,需要用例手动调用该 fixture;如果是 True,所有作用域内的测试用例都会自动调用该 fixture
  • ids:每个字符串 id 的列表,每个字符串对应于 params,这样他们就是测试ID的一部分。如果没有提供ID,它们将从 params 自动生成
  • name:默认:装饰器的名称,同一模块的 fixture 相互调用建议写不同的名称

3、快速上手

我们先创建一个test_query.py文件,内容如下:

# -*- coding: utf-8 -*-
# @Time    : 2023/11/21 14:55
# @Author  : 梗小旭
# @File    : test_query.py

import pytest

@pytest.fixture(scope="function")
def login():
    print("登录成功。。。")
    return {"token": "我是token"}

def test_query_success(login):
    token = login
    print(token)
    print("查询成功。。。")

def test_query_fail():
    print("查询失败。。。。")

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

正常在做接口自动化时,肯定都需要先登录才能进行增删改查,所以前置条件得先登录,上述例子中使用pytest.fixture()定义了一个登录前置条件并返回token信息。test_query_success用例使用了login前置,test_query_fail未调用。那我们看下执行结果是什么:
在这里插入图片描述
从执行结果可以看出,test_query_success用例执行前调用了login函数,接收了login返回的token并打印了出来,而test_query_fail未调用就没有执行。这样就弥补了之前用setup和teardown的不足,我想让哪个用例执行这个前置,就可以控制了,而不是所有的用例都执行这个前置,更加的灵活。

得出结论:
@pytest.fixture() 装饰器用于声明函数是一个 fixture,如果测试用例的参数中包含此 fixture 函数,则在测试用例运行前会先运行此 fixture 函数。如果 fixture 函数有返回值,则将返回值传递给测试用例函数。

4、多种情况下使用

4.1、测试用例调用fixture的3种方式

  • 将fixture装饰的函数名称作为测试用例的输入参数,例如上面例子中的login函数是test_query_success的输入参数
  • 测试用例加上装饰器:@pytest.mark.usefixtures(fixture_name)
  • fixture设置autouse=True

还是用上面test_query.py文件,代码如下:

# -*- coding: utf-8 -*-
# @Time    : 2023/11/21 14:55
# @Author  : 梗小旭
# @File    : test_query.py

import pytest


@pytest.fixture(scope="function")
def login():
    print("登录成功。。。")

# 调用方式一
def test_query_success_1(login):
    print("调用方式一:查询成功。。。")

# 调用方式二
@pytest.mark.usefixtures("login")
def test_query_success_2():
    print("调用方式二:查询成功。。。")

# 调用方式三
@pytest.fixture(autouse=True)
def login_autouse():
    print("执行login_autouse,每个用例之前都会调用。。。")

@pytest.mark.usefixtures("login_autouse")
def query_success_3():
    print("调用方式三:查询成功。。。")


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

从上述代码可以看出分别用三种方式调用fixture,方式一直接拿函数名传参,方式二使用@pytest.mark.usefixtures装饰器,方式三使用 fixture设置autouse=True,但是query_success_3用例的函数名前面没有加test_,下面我们看下执行结果:
在这里插入图片描述
从执行结果可以得出下面几点:

  • test_query_success_1引用了login,先执行login,再执行test_query_success_1
  • test_query_success_2使用了装饰器,先执行了login,再执行了test_query_success_2
  • fixture设置了autouse=True,每个用例都会执行,且用例不需要进行传参和使用装饰器都会执行,且优先级高于本身传入的前置条件
  • test_query_success_3即使使用了装饰器,但是用例没有加test_开头,所以不会执行

如果一个用例我想使用多个前置,一个类里面的测试用例都使用一个fixture等多种情况呢,想必大家在写接口自动化的时候会遇到很多复杂场景,下面列出几个例子:

# -*- coding: utf-8 -*-
# @Time    : 2023/11/21 14:55
# @Author  : 梗小旭
# @File    : test_query.py

"""
一个测试用例传入多个前置,删除商品需要先登录、找到商品ID,再通过商品ID删除商品。
需要注意的是,测试用例传入login, query的顺序不能错,执行规则是放在前面的先执行

"""
import pytest

@pytest.fixture(scope="function")
def login():
    print("登录成功。。。")

@pytest.fixture(scope="function")
def query():
    print("获取商品ID成功。。。")


def test_del_goods(login, query):
    print("删除商品成功。。。")


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

# -*- coding: utf-8 -*-
# @Time    : 2023/11/21 14:55
# @Author  : 梗小旭
# @File    : test_query.py
"""
和上面的例子一样,但是使用@pytest.mark.usefixtures,同样也是先执行前面的。
"""
import pytest

@pytest.fixture(scope="function")
def login():
    print("登录成功。。。")


@pytest.fixture(scope="function")
def query():
    print("获取商品ID成功。。。")


@pytest.mark.usefixtures("login", "query")
def test_del_goods():
    print("删除商品成功。。。")


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

# -*- coding: utf-8 -*-
# @Time    : 2023/11/21 14:55
# @Author  : 梗小旭
# @File    : test_query.py

"""
在类上面使用@pytest.mark.usefixtures,类下面所有的用例执行前都会调用login
"""
import pytest

@pytest.fixture(scope="function")
def login():
    print("登录成功。。。")


@pytest.mark.usefixtures("login")
class TestQuery:

    def test_query_1(self):
        print("test_query_1查询成功。。。")

    def test_query_2(self):
        print("test_query_2查询成功。。。")


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

关键点:

  • 在类声明上面加 @pytest.mark.usefixtures() ,代表这个类里面所有测试用例都会调用该 fixture
  • 可以叠加多个 @pytest.mark.usefixtures() ,先执行的放底层,后执行的放上层
  • 可以传多个 fixture 参数,先执行的放前面,后执行的放后面
  • 如果 fixture 有返回值,用 @pytest.mark.usefixtures() 是无法获取到返回值的,必须用传参的方式(方式一)

4.2、fixture传递测试数据

通过上面的例子,其实我们已经能看出fixture如何传参了,当我们把fixture装饰的函数名称传给测试用例后,执行用例时会先执行fixture装饰的函数并返回值,在测试用例中我们直接可以拿变量接收返回值,这里必须再提一下,使用@pytest.mark.usefixtures()是拿不到返回值的。

# -*- coding: utf-8 -*-
# @Time    : 2023/11/21 14:55
# @Author  : 梗小旭
# @File    : test_query.py

import pytest


@pytest.fixture(scope="function")
def login():
    print("登录成功。。。")

    return {"token": "我是token"}


def test_query(login):
    token = login
    print(token)
    print("查询成功。。。")


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

执行结果如下:
在这里插入图片描述
这章节目前只讲了测试用例调用fixture、fixture传递测试数据部分,fixture的其他部分在后面章节继续讲解,如果觉得博主的文章对你有所帮助,点个关注支持一下哦,ღ( ´・ᴗ・` )比心

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值