前言

  • 前面一篇讲了setup、teardown可以实现在执行用例前或结束后加入一些操作,但这种都是针对整个脚本全局生效的,无法进行精细化,精准化操作
  • 如果有以下场景:用例 1 需要先登录,用例 2 不需要登录,用例 3 需要先登录。很显然无法用 setup 和 teardown 来实现了,pytest给出了一种非常灵活的处理办法就是fixture

1. Pytest fixture 的作用

  1. pytestfixture用于将测试前后进行预备,清理工作的代码分离出核心测试逻辑的一种机制,由pytest执行的外壳函数;代码可以定制,满足多变的测试需求;这个功能相当于Setup Teardown , 但远比Setup Teardown 更加的灵活,好用。
  2. pytestfixture还可以向测试用例传入数据集, 同时批量测试提供数据源,fixture非常适合存放测试数据,可以返回任何数据<br />

2. Pytest fixture 的优势

  在pytest中加入fixture的目的是提供一个固定的基准,使测试能够可靠、重复地执行,pytest的fixture比传统xUnit风格的setup/teardown函数相比,有了巨大的改进:
  1. fixture具有明确的名称,并通过在测试函数、模块、类或整个项目中声明它们的使用来激活。
  2. fixture是以模块化的方式实现的,因为每个fixture名称都会触发fixture函数,其本身也可以使用其他fixture。
  3. fixture管理从简单的单元扩展到复杂的函数测试,允许根据配置和组件选项参数化fixture和测试,或者在函数、类、模块或整个测试会话范围内重复使用fixture。

3. Fixture参数列表

@pytest.fixture 默认值
(scope=”function”, params=None, autouse=False, ids=None, name=None)

各个参数解析

  • scope:可以理解成fixture的作用域,默认:function,还有class、module、package、session四个【常用】
  • autouse:默认:False,需要用例手动调用该fixture;如果是True,所有作用域内的测试用例都会自动调用该fixture
  • ids:字符串id的列表,每个id对应于参数,是测试id的一部分,如果没有提供id,它们将从参数自动生成标识。
  • params:一个可选的参数列表,它将导致对fixture函数和使用它的所有测试的多次调用。当前参数在”request.param”中可用
  • name:可以理解成为这前置函数取个别名

注意

session的作用域:是整个测试会话,即开始执行pytest到结束测试

4 . fixture快速入门

     **    先看一个 例子 11-1:    **

代码:

# -*- coding:utf-8 -*-
# Author:tang_ren_li
# 2021-1-29 22:45

import pytest


@pytest.fixture()
def fixture_1():
    str="test_data"
    print("fixture1_测试开始之前执行")
    return str


@pytest.fixture(scope="class")#如果自动调用不开启,scope参数不会起作用,
def fixture_2():
    str="test_data2"
    print("fixture2_测试开始之前执行")
    yield str
    print("fixture1_测试开始之后执行")


@pytest.fixture(name='driver')#name参数用来对fixture进行重命名
def fixture_3():
    str="test_data3"
    print("fixture3_测试开始之前执行")
    yield str
    print("fixture3_测试开始之后执行")


@pytest.fixture()
def fixture_4():
    str = "test_data4"
    yield str
    print("fixture4_测试开始之后执行")



def test_case_1(fixture_1):
    print('test_case_1 is run ! ')
    print(fixture_1)
    assert 1


def test_case_2(fixture_2):
    print('test_case_2 is run ! ')
    print(fixture_2)
    assert 1


def test_case_3(driver):
    print('test_case_3 is run ! ')
    print(driver)
    assert 1


def test_case_4(fixture_4):
    print(fixture_4)
    assert 1

运行结果:

========================= test session starts ===================
collecting … collected 4 items

TestFixture_1.py::test_case_1
fixture1
测试开始之前执行
PASSED [ 25%]
testcase_1 is run !
test_data
fixture1
测试开始之后执行

TestFixture_1.py::test_case_2
fixture2
测试开始之前执行
PASSED [ 50%]
testcase_2 is run !
test_data2
fixture1
测试开始之后执行

TestFixture_1.py::test_case_3
fixture3
测试开始之前执行
PASSED [ 75%]
testcase_3 is run !
test_data3
fixture3
测试开始之后执行

TestFixture_1.py::test_case_4 PASSED [100%]
test_data4
fixture4
测试开始之后执行

=================== 4 passed in 0.02s ======================

说明:

  1. 普通函数被装饰器pytest.fixture()装饰后,就可以被声明成一个fixture
    2. 使用fixture的一种方法,测试用例可以通过fixture名字调用fixture,因此每个测试用例可以灵活精准的选择自己的fixture
    3. 测试 setup功能在 yield 或者 return 前执行, yield 或者 return 可以用例传递数据,数据类型任意,传递的数据通过函数名称返回
    4. 测试teardown 功能通过在yield 后面的代码块进行定义 ,一个fixture函数可以只定义setup或只定义teardown ,只需要在对应代码块进行控制即可
    5. fixture的name就是对fixture函数起别名, 在fixtu互相调用的时候可以进行区分,通过别名也可以描述特殊含义的fixture
    6. autouse:默认:False,需要用例手动调用该fixture;如果是手动调用的情况下scope参数将不起作用




]