前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python pytest框架之@pytest.fixture()和conftest详解

Python pytest框架之@pytest.fixture()和conftest详解

作者头像
王大力测试进阶之路
发布2019-10-25 17:33:50
5.4K0
发布2019-10-25 17:33:50
举报
文章被收录于专栏:橙子探索测试橙子探索测试

一、fixture简介 学pytest就不得不说fixture,fixture是pytest的精髓所在,类似unittest中setup/teardown这种前后置东西。但是比它们要强大、灵活很多,它的优势是可以跨文件共享 fixture的目的是提供一个固定基线,在该基线上测试可以可靠地和重复地执行。fixture提供了区别于传统单元测试(setup/teardown)有显著改进 1、有独立的命名,并通过声明它们从测试函数、模块、类或整个项目中的使用来激活。 2、按模块化的方式实现,每个fixture都可以互相调用。 3、fixture的范围从简单的单元扩展到复杂的功能测试,允许根据配置和组件选项对fixture和测试用例进行参数化,或者跨函数function、类class、模块module或整个测试会话sessio范围。

二、用途: 1.做测试前后的初始化设置,如测试数据准备,链接数据库,打开浏览器等这些操作都可以使用fixture来实现 2.测试用例的前置条件可以使用fixture实现 3.支持经典的xunit fixture ,像unittest使用的setup和teardown 4.fixture可以实现unittest不能实现的功能,比如unittest中的测试用例和测试用例之间是无法传递参数和数据的,但是fixture却可以解决这个问题

三、fixture作为参数传入: 1、定义fixture跟定义普通函数差不多,唯一区别就是在函数上加个装饰器@pytest.fixture(),fixture命名不要用test_开头,跟用例区分开。用例才是test_开头的命名。 2、fixture是可以有返回值的,如果没return默认返回None。用例调用fixture的返回值,直接就是把fixture的函数名称当成变量传入 3、fixture装饰器里的scope有四个级别的参数。“function(不写默认这个)”,“class”,“module”or“session” 4、除scope之外。还有params、autouse、ids、name等。 5、fixture可以有返回值,如果没有return,默认会是None;用例调用fixture的返回值,就是直接把fixture的函数名称作为参数传入

6、fixture可以返回一个元组、列表或字典

7、test_用例可传单个、多个fixture参数

8、fixture与fixture间可相互调用

代码语言:javascript
复制
fixture可以返回一个元组、列表或字典

@pytest.fixture()
def user():
    print("=====打印装饰器函数=====")
    username='wangli'
    psw=123456
    assert username=="wangli"
    assert psw == 123456
    return username,psw
def test_login(user):
    print(user)
    assert user[0]=="wangli"
    assert user[1] == 123456

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


"C:\Program Files\Python35\python.exe" C:/Users/wangli/PycharmProjects/test/test/test03.py
============================= test session starts =============================
platform win32 -- Python 3.5.2, pytest-5.1.2, py-1.8.0, pluggy-0.12.0
rootdir: C:\Users\wangli\PycharmProjects\test\test
collected 1 item

test03.py =====打印装饰器函数=====
('wangli', 123456)
.

============================== 1 passed in 0.16s ==============================

Process finished with exit code 0
代码语言:javascript
复制
test_用例可传单个、多个fixture参数

@pytest.fixture()
def username():
    print("=====打印username装饰器函数=====")
    username='wangli'
    assert username=="wangli"
    return username
@pytest.fixture()
def psw():
    print("=====打印psw装饰器函数=====")
    psw=123456
    assert psw==123456
    return psw
def test_login(username,psw):
    print(username,psw)
    assert username=="wangli"
    assert psw == 123456

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


"C:\Program Files\Python35\python.exe" C:/Users/wangli/PycharmProjects/test/test/test03.py
============================= test session starts =============================
platform win32 -- Python 3.5.2, pytest-5.1.2, py-1.8.0, pluggy-0.12.0
rootdir: C:\Users\wangli\PycharmProjects\test\test
collected 1 item

test03.py =====打印username装饰器函数=====
=====打印psw装饰器函数=====
wangli 123456
.

============================== 1 passed in 0.13s ==============================

Process finished with exit code 0
代码语言:javascript
复制
fixture与fixture间可相互调用

@pytest.fixture()
def first():
    print("=====first=====")
    username='wangli'
    assert username=="wangli"
    return username
@pytest.fixture()
def sencond(first):
    print("=====sencond=====")
    psw=123456
    assert psw==123456
    return first,psw
def test_login(sencond):
    print(sencond)
    assert sencond[0]=="wangli"
    assert sencond[1] == 123456

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


"C:\Program Files\Python35\python.exe" C:/Users/wangli/PycharmProjects/test/test/test03.py
============================= test session starts =============================
platform win32 -- Python 3.5.2, pytest-5.1.2, py-1.8.0, pluggy-0.12.0
rootdir: C:\Users\wangli\PycharmProjects\test\test
collected 1 item

test03.py =====first=====
=====sencond=====
('wangli', 123456)
.

============================== 1 passed in 0.02s ==============================

Process finished with exit code 0

四、fixture源码详解: fixture(scope='function',params=None,autouse=False,ids=None,name=None): fixture里面有个scope参数可以控制fixture的作用范围,scope:有四个级别参数"function"(默认),"class","module","session

params:一个可选的参数列表,它将导致多个参数调用fixture功能和所有测试使用它。 autouse:如果True,则为所有测试激活fixture func可以看到它。如果为False则显示需要参考来激活fixture ids:每个字符串id的列表,每个字符串对应于params这样他们就是测试ID的一部分。如果没有提供ID它们将从params自动生成 name:fixture的名称。这默认为装饰函数的名称。如果fixture在定义它的统一模块中使用,夹具的功能名称将被请求夹具的功能arg遮蔽,解决这个问题的一种方法时将装饰函数命令"fixture_<fixturename>"然后使用"@pytest.fixture(name='<fixturename>')"。

五、fixture的作用范围

fixture里面有个scope参数可以控制fixture的作用范围:session>module>class>function

-function:每一个函数或方法都会调用

-class:每一个类调用一次,一个类中可以有多个方法

-module:每一个.py文件调用一次,该文件内又有多个function和class

-session:是多个文件调用一次,可以跨.py文件调用,每个.py文件就是module

function默认模式@pytest.fixture(scope='function')或 @pytest.fixture()

函数级别的,每一个函数或方法都会调用,每个测试用例执行前都会执行一次function级别的fixture @pytest.fixture()如果不写参数,参数就是scope="function",它的作用范围是每个测试用例来之前运行一次,销毁代码在测试用例之后运行。

class类级别@pytest.fixture(scope='class')

如果一个class里面有多个用例,都调用了1次fixture,那么此fixture只在此class里所有用例开始前执行一次

代码语言:javascript
复制
@pytest.fixture(scope='class')
def test1():
    b = '男'
    print('传出了%s, 且只在class里所有用例开始前执行一次!!!' % b)
    return b

class TestCase:
    def test3(self, test1):
        name = '男'
        print('找到name')
        assert test1 == name

    def test4(self, test1):
        sex = '男'
        print('找到sex')
        assert test1 == sex
if __name__=="__main__":
    pytest.main(["-s","test03.py"])

"C:\Program Files\Python35\python.exe" C:/Users/wangli/PycharmProjects/test/test/test03.py
============================= test session starts =============================
platform win32 -- Python 3.5.2, pytest-5.1.2, py-1.8.0, pluggy-0.12.0
rootdir: C:\Users\wangli\PycharmProjects\test\test
collected 2 items

test03.py 传出了男, 且只在class里所有用例开始前执行一次!!!
找到name
.找到sex
.

============================== 2 passed in 0.09s ==============================

Process finished with exit code 0

module模块级别@pytest.fixture(scope='module')

每一个.py文件调用一次,fixture为module时,在当前.py脚本里面所有用例开始前只执行一次,模块里所有的用例执行前执行一次module级别的fixture

代码语言:javascript
复制
@pytest.fixture(scope='module')
def test1():
    b = '男'
    print('传出了%s, 且在当前py文件下执行一次!!!' % b)
    return b

def test3(test1):
    name = '男'
    print('找到name')
    assert test1 == name

class TestCase:
    def test4(self, test1):
        sex = '男'
        print('找到sex')
        assert test1 == sex
if __name__=="__main__":
    pytest.main(["-s","test03.py"])

"C:\Program Files\Python35\python.exe" C:/Users/wangli/PycharmProjects/test/test/test03.py
============================= test session starts =============================
platform win32 -- Python 3.5.2, pytest-5.1.2, py-1.8.0, pluggy-0.12.0
rootdir: C:\Users\wangli\PycharmProjects\test\test
collected 2 items

test03.py 传出了男, 且在当前py文件下执行一次!!!
找到name
.找到sex
.

============================== 2 passed in 0.09s ==============================

Process finished with exit code 0

session 会话级别@pytest.fixture(scope='session')

1、可以跨.py文件调用,有多个.py文件调用时,实际只调用了一次fixture

2、conftest.py与运行的用例要在同一个pakage下,并且有__init__.py文件

3、不需要import导入 conftest.py,pytest会自动识别该文件,放到项目的根目录下就可以全局调用了,如果放到某个package下,那就在改package内有效

4、conftest.py配置脚本名称是固定的,不能改名称

代码语言:javascript
复制
多个.py文件只调用1次fixture

import pytest
# conftest.py
@pytest.fixture(scope='session')
def get_token():
    token = 'qeehfjejwjwjej11sss@22'
    print('获取到token:%s' % token)
    return token



import pytest
# test02.py
class Test(object):
    def test2(self,get_token):
        token = 'qeehfjejwjwjej11sss@22'
        print("【执行test02.py-Test类-test2用例,获取get_token:%s】" %get_token)
        assert get_token == token

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


import pytest
#test03.py
class Test(object):
    def test3(self,get_token):
        token = 'qeehfjejwjwjej11sss@22'
        print("【执行test03.py-Test类-test3用例,获取get_token:%s】" %get_token)
        assert get_token == token
    def test4(self,get_token):
        token = 'qeehfjejwjwjej11sss@22'
        print("【执行test03.py-Test类-test4用例,获取get_token:%s】" %get_token)
        assert get_token == token

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



"C:\Program Files\Python35\python.exe" C:/Users/wangli/PycharmProjects/Test/test/test02.py
============================= test session starts =============================
platform win32 -- Python 3.5.2, pytest-5.1.2, py-1.8.0, pluggy-0.12.0
rootdir: C:\Users\wangli\PycharmProjects\Test\test
collected 3 items

test02.py 获取到token:qeehfjejwjwjej11sss@22
【执行test02.py-Test类-test2用例,获取get_token:qeehfjejwjwjej11sss@22】
.
test03.py 【执行test03.py-Test类-test3用例,获取get_token:qeehfjejwjwjej11sss@22】
.【执行test03.py-Test类-test4用例,获取get_token:qeehfjejwjwjej11sss@22】
.

============================== 3 passed in 0.30s ==============================

Process finished with exit code 0









多个.py文件只调用多次fixture

import pytest
# conftest.py
@pytest.fixture()
def get_token():
    token = 'qeehfjejwjwjej11sss@22'
    print('获取到token:%s' % token)
    return token



import pytest
# test02.py
class Test(object):
    def test2(self,get_token):
        token = 'qeehfjejwjwjej11sss@22'
        print("【执行test02.py-Test类-test2用例,获取get_token:%s】" %get_token)
        assert get_token == token

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


import pytest
#test03.py
class Test(object):
    def test3(self,get_token):
        token = 'qeehfjejwjwjej11sss@22'
        print("【执行test03.py-Test类-test3用例,获取get_token:%s】" %get_token)
        assert get_token == token
    def test4(self,get_token):
        token = 'qeehfjejwjwjej11sss@22'
        print("【执行test03.py-Test类-test4用例,获取get_token:%s】" %get_token)
        assert get_token == token

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



"C:\Program Files\Python35\python.exe" C:/Users/wangli/PycharmProjects/Test/test/test03.py
============================= test session starts =============================
platform win32 -- Python 3.5.2, pytest-5.1.2, py-1.8.0, pluggy-0.12.0
rootdir: C:\Users\wangli\PycharmProjects\Test\test
collected 3 items

test02.py 获取到token:qeehfjejwjwjej11sss@22
【执行test02.py-Test类-test2用例,获取get_token:qeehfjejwjwjej11sss@22】
.
test03.py 获取到token:qeehfjejwjwjej11sss@22
【执行test03.py-Test类-test3用例,获取get_token:qeehfjejwjwjej11sss@22】
.获取到token:qeehfjejwjwjej11sss@22
【执行test03.py-Test类-test4用例,获取get_token:qeehfjejwjwjej11sss@22】
.

============================== 3 passed in 0.04s ==============================

Process finished with exit code 0
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 橙子探索测试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • function默认模式@pytest.fixture(scope='function')或 @pytest.fixture()
  • class类级别@pytest.fixture(scope='class')
  • module模块级别@pytest.fixture(scope='module')
  • session 会话级别@pytest.fixture(scope='session')
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档