Python自动化测试pytest中fixtureAPI简单说明

什么是fixture

根据pytest官方文档的说明,fixture可以简单的归纳为具有以下功能的函数:

  • 配置测试前系统的初始状态;
  • 定义传入测试中的数据集;
  • 为批量测试提供数据源等

与xUnit风格的setup和teardown的对比

fixture的功能与setup和teardown类似,可以实现setup和teardown的功能,但是对这些功能进行了明显的改进,主要有以下方面:

  • 调用灵活。可以在测试函数、模块、类或整个项目中声明fixture的名称来进行调用;
  • 使用灵活。fixture即适用于简单的单元测试又适用于复杂的功能测试。根据测试的需求可对fixture进行参数化使用,并且可对fixture进行重复使用。
  • fixture是以模块化方式实现的,因此允许fixture调用其他fixture函数;
  • teardown的实现逻辑更加清晰明了,并且方便进行管理。

 fixture运行报错后,pytest的处理方式

通过上面的说明,我们可以知道fixture函数本身是允许调用其他fixture函数的。在这种情况下,测试运行的时候,其中一个fixture函数报错了,pytest的会如何处理呢?
通过pytest官方文档的说明,我们可以知道:

  • pytest以线性的方式顺序执行测试用例所调用的fixture函数;
  • 当顺序较前的fixture函数执行报错后,pytest会停止执行该测试所调用的其他fixture,并且将测试标记出错;
  • 测试标记错误,并不意味着测试未通过,只能说明测试无法尝试执行下去,因此我们需要尽可能的去为测试函数减少必要的依赖关系。

示例1:

1.在以下demo代码中,order()返回类型存在问题,正确的应该返回一个list,我们给其返回一个None:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

import pytest

@pytest.fixture

def order():

    return None  #正确应该返回[],我们给返回一个None

@pytest.fixture

def append_first(order):

    order.append(1)

@pytest.fixture

def append_second(order, append_first):

    order.extend([2])

@pytest.fixture(autouse=True)

def append_third(order, append_second):

    order += [3]

def test_order(order):

    assert order == [1, 2,3]

运行后结果如下:

test_order被标记Error,并且信息提示:test setup failed,说明是调用的fixture函数存在问题,且说明了错误原因。

在这里插入图片描述

2.如果是test_order运行未通,运行信息会怎么样提醒呢?我们按照以下demo修改测试代码,修改test_order的断言语句:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

import pytest

@pytest.fixture

def order():

    return []   #返回一个list

@pytest.fixture

def append_first(order):

    order.append(1)

@pytest.fixture

def append_second(order, append_first):

    order.extend([2])

@pytest.fixture(autouse=True)

def append_third(order, append_second):

    order += [3]

def test_order(order):

    assert order == [1, 2#断言失败,正确应该是 order==[1,2,3]

运行结果如下:

test_order被标记failed,且提醒是AssertionError,断言出错。这说明是test_order 本身运行未通过。

2.fixture API @pytest.fixture()说明

pytest使用@pytest.fixture()来声明fixture方法。具体如何使用,我会在文章后面进行详细说明。在此,主要来简单说明一下fixture()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

def fixture(

    fixture_function: Optional[_FixtureFunction] = None,

    *,

    scope: "Union[_Scope, Callable[[str, Config], _Scope]]" = "function",

    params: Optional[Iterable[object]] = None,

    autouse: bool = False,

    ids: Optional[

        Union[

            Iterable[Union[None, str, float, int, bool]],

            Callable[[Any], Optional[object]],

        ]

    ] = None,

    name: Optional[str] = None,

) -> Union[FixtureFunctionMarker, _FixtureFunction]:

参数说明:

2.1 scope

fixture函数的作用域。作用域从小到大依次为:function(默认)classmodulepackagesession

还可传入一个可调用对象,以实现动态修改fixture的作用域。

后面会单独写一篇文章,为大家详细介绍fixture的scope。

2.2 params

传入测试数据集,动态生成测试用例,每一条数据都单独生成一条测试用例。通过request.param,可以获取传入的这些数据。

后面会单独写一篇文章,为大家详细介绍fixture的参数化。

2.3 autouse

fixture自动应用标识。

如果是True,则在同作用域下的测试函数,会自动调用该fixture;如果是False,则测试函数需要主动去调用该fixture。

后面会在介绍fixture调用方法的文章给大家详细说明。

2.4 ids

测试用例ID标识,与parmas传入的参数一一对应。当未定义时,会自动生成id。

示例2:

1.传入ids参数,运行以下demo:

1

2

3

4

5

6

7

8

import pytest

@pytest.fixture(params=[1,2,3],ids=['A','B','C'])

def ids(request):

    data=request.param

    print(f'获取测试数据{data}')

    return data

def test_ids(ids):

    print(ids)

运行结果:

在执行信息中,我们可以发现ids的三个参数和params的三个参数一一对应显示,并且ids的参数作为测试用例id的一部分呈现出来。

2. 修改上面demo中的代码,不传入ids参数,运行一下:

1

2

3

4

5

6

7

8

import pytest

@pytest.fixture(params=[1,2,3]) #未传入ids

def ids(request):

    data=request.param

    print(f'获取测试数据{data}')

    return data

def test_ids(ids):

    print(ids)

运行结果:

查看运行结果我们可以发现,虽然没有传入ids,但是却自动生成了ids

测试结束后,我们常常以测试报告的形式来汇报测试结果,如结合allure呈现测试结果。通过ids传入的参数可以对测试用例进行说明,这样更方便我们查看测试结果。

2.5 name

fixture的别名。fixture的name默认是@pytest.fixture所装饰的函数的函数名。使用fixture的别名可以提高代码的阅读性。

示例3:
以下面的demo为例:

1

2

3

4

5

6

7

8

9

10

11

12

import pytest

@pytest.fixture()

def login():

    print('login')

class SubClass:

    def sub_login(self):

        print('subcalss_login')

class TestCase:

    def test_case1(self,login):  #调用fixture——login

        login=SubClass()  #定义一个login并实例化SubClass

        login.sub_login() #调用SubClass中的sub_login()

        print('这是testcase1')

我们定义了一个fixture函数——login(),同时在test_case1中实例化了一个Subclass类,并起名为login,然后调用了SubClass类中的sub_login()。如果代码复杂的情况,很容易将fixture函数的login与SubClass实例的login弄混淆,增加代码的阅读的复杂度。

当我们使用fixture别名的话,在阅读代码的时候就很容易进行区分。

1

2

3

@pytest.fixture(name='module_login')

def login():

    print('login')

1

2

3

4

5

class TestCase:

    def test_case1(self,module_login):  #使用fixture别名:module_login

        login=SubClass()  #定义一个login并实例化SubClass

        login.sub_login() #调用SubClass中的sub_login()

        print('这是testcase1')

注意:

当使用name参数后,则无法再通过@pytest.fixture所装饰的函数的函数名来进行调用,必须使用name所指定fixture别名来调用。

​现在我也找了很多测试的朋友,做了一个分享技术的交流群,共享了很多我们收集的技术文档和视频教程。
如果你不想再体验自学时找不到资源,没人解答问题,坚持几天便放弃的感受
qq群号:485187702【暗号:csdn11】
可以加入我们一起交流。而且还有很多在自动化,性能,安全,测试开发等等方面有一定建树的技术大牛
分享他们的经验,还会分享很多直播讲座和技术沙龙
可以免费学习!划重点!开源的!!!
视频+文档+PDF+面试题可以关注公众号:【软件测试小dao】

最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走! 希望能帮助到你!【100%无套路免费领取】

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值