fixture

fixture用途

  1.用例编写前的初始化设置,连接数据库等
  2.测试用例的前置条件可以使用fixture实现
  3.实现unittest不能实现的功能,注入测试用例之间的参数传递

fixture与unittest区别:

  1.独立命名,并通过声明它们从测试函数、模块、类或整个项目中的使用来激活
  2.按模块化的方式实现,每个fixture可以相互调用
  3.fixture的范围从简单的单元测试到复杂的功能测试,可以对fixture配置参数,或者跨函数function、类class、模块modules或整个测试session的范围

fixture参数传入

  1.单个fixture
# test_fixture.py
import pytest

@pytest.fixture()
def fixtureFunc():
    a = 1
    b = 2
    return (a, b)

def test_fixture(fixtureFunc):
    a = fixtureFunc[0]
    b = fixtureFunc[1]
    assert a == 1
    assert b == 2
    print("调用了{}".format(fixtureFunc))

class TestFixture(object):
    def test_fixture_class(self, fixtureFunc):
        a = fixtureFunc[0]
        assert a == 1
        print('在类中使用fixture "{}"'.format(fixtureFunc))

if __name__=='__main__':
    pytest.main(['-s', 'test_fixture.py'])
0
  2.使用多个fixture
# test_fixture.py

import pytest

@pytest.fixture()
def test1():
    a = 1
    return a

@pytest.fixture()
def test2():
    b = 2
    return b

def test_fixture(test1, test2):
    a = test1
    b = test2
    assert a+b == 3
    print("调用了{}".format(test1, test2))

class TestFixture(object):
    def test_fixture_class(self, test1, test2):
        a = test1
        assert a == 1
        print('在类中使用fixture "{}"'.format(test1))

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

  3.互相调用
# 相互调用
import pytest

@pytest.fixture()
def test1():
    a = 1
    a2 = a * a
    print('a的平方为{}'.format(a2))
    return a2

def test2(test1):
    assert test1 == 1
    print('test1使用成功')

if __name__ == '__main__':
    pytest.main('-s test_fixture.py')

fixture scope

  function:每个test都运行,默认值是function,作用范围内的每个测试用例运行之前运行一次
import pytest

@pytest.fixture()
def test1():
    a = 2
    b = 'aaa'
    print('传入a,b')
    return a, b

def test2(test1):
    c = 'aaa'
    d = test1[1]
    print('test1使用成功')
    assert c == d


def test2(test1):
    c = 2
    assert c == test1[0]
    print('test1使用成功')

if __name__ == '__main__':
    pytest.main('-v test_fixture.py')

  class:如果一个class中有多个用例度调用了fixture,那在此class运行之前运行一次
# scope='class'
import pytest

@pytest.fixture(scope='class')
def test1():
    a = 2
    b = 'aaa'
    print('传入a,b')
    return a, b

class Testcase:
    def test2(self, test1):
        c = 'aaa'
        d = test1[1]
        print('test1使用成功')
        assert c == d

    def test3(self, test1):
        c = 2
        assert c == test1[0]
        print('test3使用成功')

if __name__ == '__main__':
    pytest.main('-v test_fixture.py')

  module:在当前.py文件所有用例开始前执行一次
# scope = 'module'
import pytest

@pytest.fixture(scope='module')
def test1():
    a = 2
    b = 'aaa'
    c = '呀谁啦累'
    print('传入a,b')
    return a, b, c

class Testcase:
    def test2(self, test1):
        c = 'aaa'
        d = test1[1]
        print('test1使用成功')
        assert c == d

    def test3(self, test1):
        c = 2
        assert c == test1[0]
        print('test3使用成功')

def test4():
    d = '呀'
    e = test1[2]
    f = d in e
    assert f

if __name__ == '__main__':
    pytest.main('-v test_fixture.py')

  session:跨.py文件调用,当多个.py文件只需要调用一次fixture时,设置scope='session'并写入到conftest中
    conftest.py文件名称是固定的pytest会自动识别该文家 ,放在项目的根目录下用以全局调用,对当前所在文件夹下的文件有效
# conftest.py
import pytest

@pytest.fixture(scope='module')
def test1():
    a = 2
    b = 'aaa'
    c = '呀谁啦累'
    print('传入a,b')
    return a, b, c
# test_1.py
import pytest

class Testcase:
    def test2(self, test1):
        c = 'aaa'
        d = test1[1]
        print('test2执行成功')
        assert c == d

    def test3(self, test1):
        c = 2
        assert c == test1[0]
        print('test3执行成功')

if __name__ == '__main__':
    pytest.main(['-s', 'test_1.py'])
# test_2.py
import pytest

def test4(test1):
    d = '呀谁啦累'
    e = test1[2]
    print("test4执行成功")
    assert d == e

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

fixture调用方法

  1.fixture的名字直接作为测试用例的参数
  编写时,被调用方法前要使用@pytest.fixture装饰器,
import pytest

@pytest.fixture()
def fixtureFunc():
    return 'fixtureFunc'

def test_fixture(fixtureFunc):
    print('我调用了{}'.format(fixtureFunc))

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

 

  2.使用@pytest.mark.userfixtures('fixture')装饰器
  每个使用fixture函数的函数或类前都使用@pytest.mark.userfixtures('fixture')装饰器装饰
  usefixture可以叠加,注意先执行的放底层,后执行的放顶层
# test_fixture.py
import pytest

@pytest.fixture()
def fixtureFunc():
    # print('\n fixture->fixtureFunc')
    return 'fixture'

@pytest.mark.usefixtures('fixtureFunc')
def test_fixture():
    print('in test_fixture')

@pytest.mark.usefixtures('fixtureFunc')
class TestFixture(object):
    def test_fixture_class(self):
        print('in class with text_fixture_class')

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

 

  叠加使用@pytest.mark.userfixtures()
# 叠加usefixture
import pytest

@pytest.fixture()
def test1():
    print('a=1')

@pytest.fixture()
def test2():
    print('b=2')

@pytest.mark.usefixtures('test2')
@pytest.mark.usefixtures('test1')
def test_fixture():
    print("调用了")

@pytest.mark.usefixtures('test1')
@pytest.mark.usefixtures('test2')
class TestFixture(object):
    def test_fixture_class(self):
        print('在类中使用fixture')

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

  3.使用autouse参数(自动调用fixture)
  在@pytest.fixture()中加入autouse参数,设置值为True
# test_fixture.py
import pytest

@pytest.fixture(autouse=True)
def fixtureFunc():
    # print('\n fixture->fixtureFunc')
    return 'fixture'

def test_fixture():
    print('in test_fixture')

class TestFixture(object):
    def test_fixture_class(self):
        print('in class with text_fixture_class')

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

conftest.py

  作用范围:对当前文件夹下的文件生效,若该文件在根目录中,则起全局作用
  注意:
  conftest在不同位置,作用域也不一样
  conftest不能跨模块调用

fixture实现teardown

  1.在fixture中添加yield,用以唤醒teardown执行内容
  注:如果其中一个用例执行异常,不会影响yield后的teardown执行,运行结果互不影响;
    但如果在setup(即open函数中yield之前的部分)就出现异常,不会去执行teardown;
    yield可以配合with语句使用。
import pytest

@pytest.fixture(scope='module')
def open():
    print("第一步")

    yield
    print("执行teardown")

def test1(open):
    print("用例一")
    assert 1==2
    raise AssertionError

def test2(open):
    print("用例二")

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

  结合with使用
import smtplib
import pytest

@pytest.fixture(scope="module")
def smtp():
    with smtplib.SMTP("smtp.qq.com") as smtp:
        yield smtp
  addfinalizer终结函数
# yield配合with语句使用
import smtplib
import pytest

@pytest.fixture(scope="module")
def smtp_connection(request):
    smtp_connection = smtplib.SMTP("smtp.gmail.com", 587, timeout=5)
    def fin():
        print("teardown smtp_connection")
        smtp_connection.close()
    request.addfinalizer(fin)
    return smtp_connection
posted @ 2023-01-31 17:24  乌醍  阅读(113)  评论(0编辑  收藏  举报