在pytest中的fixture是在测试函数运行前后,由pytest执行的外壳函数,fixture中的代码可以定制,满足多变的测试需求:包括定义传入测试中的数据集、配置测试前系统的初始化状态、为批量测试提供数据源。

import pytest

@pytest.fixture()
def return_data():
return 1000 def test_someting(return_data):
assert return_data == 1000

执行结果如下:

(venv) E:\Programs\Python\Python_Pytest\TestScripts>pytest -v test_fixture.py
============= test session starts ====================================
platform win32 -- Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.11.0 -- c:\python37\python.exe
cachedir: .pytest_cache
rootdir: E:\Programs\Python\Python_Pytest\TestScripts
plugins: xdist-1.29.0, timeout-1.3.3, repeat-0.8.0, instafail-0.4.1, forked-1.0.2, emoji-0.2.0, allure-pytest-2.6.3
collected 1 item test_fixture.py::test_someting PASSED [100%]
===================== 1 passed in 0.10 seconds ======================

通过conftest.py共享fixture
fixture可以放在单独的测试文件里,也可以通过在某个公共目录下新建一个conftest.py文件,将fixture放在其中实现多个测试文件共享fixture。
conftest.py是Python模块,但他不能被测试文件导入,pytest视其为本地插件库。

使用fixture执行配置及销毁逻辑
借助fixture的yield实现setup和teardown

# encoding = utf-8
import pytest
from selenium import webdriver
from time import sleep driver = webdriver.Chrome()
url = "https://www.baidu.com" @pytest.fixture(scope='module')
def automation_testing():
# 执行测试前
driver.get(url)
yield # 测试结束后
driver.quit() def test_fixture(automation_testing):
driver.find_element_by_id("kw").send_keys("davieyang")
driver.find_element_by_id("su").click()
sleep(10)

执行结果如下:

DY@MacBook-Pro TestScripts$pytest -v test_seven.py
================ test session starts ======================
platform darwin -- Python 3.6.5, pytest-5.1.2, py-1.8.0, pluggy-0.13.0 -- /Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6
cachedir: .pytest_cache
rootdir: /Volumes/Extended/PythonPrograms/Pytest/TestScripts
collected 1 item test_seven.py::test_fixture PASSED [100%] =================== 1 passed in 20.45s =============================

使用–setup-show回溯fixture的执行过程

同样的代码,在执行命令中加上参数–setup-show,便可以看到fixture中实际的执行过程,执行结果如下:

DY@MacBook-Pro TestScripts$pytest --setup-show test_seven.py
================= test session starts ==================================
platform darwin -- Python 3.6.5, pytest-5.1.2, py-1.8.0, pluggy-0.13.0
rootdir: /Volumes/Extended/PythonPrograms/Pytest/TestScripts
collected 1 item test_seven.py
SETUP F automation_testing
test_seven.py::test_fixture (fixtures used: automation_testing).
TEARDOWN F automation_testing
================= 1 passed in 14.69s =============================

使用fixture传递测试数据

fixture非常适合存放测试数据,并且它可以返回任何数据

# encoding = utf-8
import pytest @pytest.fixture()
def return_tuple():
return ('davieyang', '', {'mail': 'davieyang@qq.com'}) def test_return_tuple(return_tuple):
assert return_tuple[2]['mail'] == 'davieyang1@qq.com'

执行结果如下:

DY@MacBook-Pro TestScripts$pytest --setup-show -v test_seven.py
============================================================================ test session starts =============================================================================
platform darwin -- Python 3.6.5, pytest-5.1.2, py-1.8.0, pluggy-0.13.0 -- /Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6
cachedir: .pytest_cache
rootdir: /Volumes/Extended/PythonPrograms/Pytest/TestScripts
collected 1 item test_seven.py::test_return_tuple
SETUP F return_tuple
test_seven.py::test_return_tuple (fixtures used: return_tuple)FAILED
TEARDOWN F return_tuple ============================= FAILURES ============================
________________________ test_return_tuple _______________________________ return_tuple = ('davieyang', '', {'mail': 'davieyang@qq.com'}) def test_return_tuple(return_tuple):
> assert return_tuple[2]['mail'] == 'davieyang1@qq.com'
E AssertionError: assert 'davieyang@qq.com' == 'davieyang1@qq.com'
E - davieyang@qq.com
E + davieyang1@qq.com
E ? + test_seven.py:11: AssertionError
============================= 1 failed in 0.08s ======================

假设在fixture函数中出现了异常,那么执行结果中报的会是Error而不是Fail

DY@MacBook-Pro TestScripts$pytest --setup-show -v test_seven.py
=================== test session starts ============================
platform darwin -- Python 3.6.5, pytest-5.1.2, py-1.8.0, pluggy-0.13.0 -- /Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6
cachedir: .pytest_cache
rootdir: /Volumes/Extended/PythonPrograms/Pytest/TestScripts
collected 0 items / 1 errors ============================= ERRORS ==============================
_______________________ ERROR collecting test_seven.py ____________________

如果是测试函数异常,那么会报Fail而不是Error

指定fixture作用范围
Fixture中包含一个叫scope的可选参数,用于控制fixture执行配置和销毁逻辑的频率,该参数有4个值分别是:function、class、module和session,其中function为默认值。

import pytest

@pytest.fixture(scope='function')
def func_scope():
"""The function scope fixture""" @pytest.fixture(scope='module')
def mod_scope():
"""The module scope fixture""" @pytest.fixture(scope='class')
def class_scope():
"""The class scope fixture""" @pytest.fixture(scope='session')
def sess_scope():
"""The session scope fixture""" def test_one(sess_scope, mod_scope, func_scope):
"""
Test using session, module, and function scope fixtures
:param sess_scope:
:param mod_scope:
:param func_scope:
:return:
""" def test_two(sess_scope, mod_scope, func_scope):
"""
Again!
:param sess_scope:
:param mod_scope:
:param func_scope:
:return:
""" @pytest.mark.usefixtures('class_scope')
class TestSomething:
def test_three(self):
"""
Test using class scope fixture
:return:
""" def test_four(self):
"""
Again
:return:
"""

执行结果如下:

DY@MacBook-Pro TestScripts$pytest --setup-show test_eight.py
====================== test session starts =======================
platform darwin -- Python 3.6.5, pytest-5.1.2, py-1.8.0, pluggy-0.13.0
rootdir: /Volumes/Extended/PythonPrograms/Pytest/TestScripts
collected 4 items test_eight.py
SETUP S sess_scope
SETUP M mod_scope
SETUP F func_scope
test_eight.py::test_one (fixtures used: func_scope, mod_scope, sess_scope).
TEARDOWN F func_scope
SETUP F func_scope
test_eight.py::test_two (fixtures used: func_scope, mod_scope, sess_scope).
TEARDOWN F func_scope
SETUP C class_scope
test_eight.py::TestSomething::test_three (fixtures used: class_scope).
test_eight.py::TestSomething::test_four (fixtures used: class_scope).
TEARDOWN C class_scope
TEARDOWN M mod_scope
TEARDOWN S sess_scope
====================== 4 passed in 0.07s ============================

从执行结果中,可以看到不但出现了代表函数级别和会话级别的F和S,还出现了代表类级别和模块级别的C和M

scope参数是在定义fixture时定义的,而不是在调用fixture时定义,使用fixture的测试函数是无法改变fixture作用范围的

fixture只能使用同级别的fixture或者高级别的fixture,比如函数级别的fixture可以使用同级别的fixture,也可以使用类级别、模块级别和会话级别的fixture,反过来则不可以

使用usefixtures指定fixture
在之前的代码示例中都是在测试函数的参数列表中指定fixture,除了这种方法可以让测试函数使用fixture外,还可以使用@pytest.mark.usefixtures(‘fixture1’, ‘fixture2’)标记测试函数或测试类,虽然这种方式这对测试函数来说意义不大,因为分别放在测试函数的参数中跟为每个函数做这样的标记比起来或许更简单,但是对于测试类来说,使用这种标记的方式就简便了很多。

@pytest.mark.usefixtures('class_scope')
class TestSomething:
def test_three(self):
"""
Test using class scope fixture
:return:
""" def test_four(self):
"""
Again
:return:
"""

使用usefixtures和在测试方法中指定fixture参数大体上差不多,但只有后者才能够使用fixture的返回值

为常用fixture添加autouse选项
通过指定autouse=True使作用域内的测试函数都运行该fixture,在需要多次运行但不依赖任何的系统状态或者外部数据的代码配合起来更加便利。

import pytest
import time @pytest.fixture(autouse=True, scope='session')
def footer_session_scope():
"""Report the time at the end of a session"""
yield
now = time.time()
print('- -')
print('finish:{}'.format(time.strftime('%d %b %X', time.localtime(now))))
print('---------------') @pytest.fixture(autouse=True)
def footer_function_scope():
"""Report test durations after each function"""
start = time.time()
yield
stop = time.time()
delta = stop - start
print('\ntest duration:{:0.3} seconds'.format(delta)) def test_one():
"""Simulate long-ish running test."""
time.sleep(1) def test_two():
"""Simulate slightly longer test"""
time.sleep(1.23)

执行结果如下:

DY@MacBook-Pro TestScripts$pytest -v -s test_nine.py
====================== test session starts ===================
platform darwin -- Python 3.6.5, pytest-5.1.2, py-1.8.0, pluggy-0.13.0 -- /Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6
cachedir: .pytest_cache
rootdir: /Volumes/Extended/PythonPrograms/Pytest/TestScripts
collected 2 items test_nine.py::test_one PASSED
test duration:1.01 seconds test_nine.py::test_two PASSED
test duration:1.24 seconds
- -
finish:15 Sep 17:12:25
--------------- ======================== 2 passed in 2.26s =========================

为fixture重命名

import pytest

@pytest.fixture(name='davieyang')
def rename_fixture_as_davieyang():
""""""
return 36 def test_rename_fixture(davieyang):
assert davieyang == 36

执行结果如下:

DY@MacBook-Pro TestScripts$pytest --setup-show test_ten.py -v
======================= test session starts ==========================
platform darwin -- Python 3.6.5, pytest-5.1.2, py-1.8.0, pluggy-0.13.0 -- /Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6
cachedir: .pytest_cache
rootdir: /Volumes/Extended/PythonPrograms/Pytest/TestScripts
collected 1 item test_ten.py::test_rename_fixture
SETUP F davieyang
test_ten.py::test_rename_fixture (fixtures used: davieyang)PASSED
TEARDOWN F davieyang ========================== 1 passed in 0.01s ==========================

如果想找到‘davieyang’在哪里定义的,则可以使用pytest的参数 --fixtures

DY@MacBook-Pro TestScripts$pytest --fixtures test_ten.py
===================== test session starts ===========================
platform darwin -- Python 3.6.5, pytest-5.1.2, py-1.8.0, pluggy-0.13.0
rootdir: /Volumes/Extended/PythonPrograms/Pytest/TestScripts
collected 1 item
------------------- fixtures defined from TestScripts.test_ten ----------------------------------
davieyang
Return where we renamed fixture
==================== no tests ran in 0.04s ============================

Fixture的参数化

对测试函数进行参数化,可以多次运行的只是该测试函数;对fixture进行参数化,每个使用该fixture的测试函数都可以执行多次

task_tuple = (Task('sleep',None, False),
Task('wake', 'brain',False),
Task('breathe', 'BRAIN', True),
Task('exercise', 'BrIaN', False)) task_ids = ['Task({},{},{})'.format(t.summary, t.owner, t.done)for t in task_tuple] def equivalent(t1, t2):
"""Check two tasks for equivalence"""
return ((t1.summary == t2.summart)and
(t1.owner == t2.owner)and
(t1.done == t2.done)) @pytest.fixture(params=task_tuple)
def a_task(request):
return request.param def test_dosomething(tasks_db, a_task):
task_id = tasks.add(a_task)
t_from_db = tasks.get(task_id)
assert equivalent(t_from_db, a_task)
task_tuple = (Task('sleep',None, False),
Task('wake', 'brain',False),
Task('breathe', 'BRAIN', True),
Task('exercise', 'BrIaN', False)) task_ids = ['Task({},{},{})'.format(t.summary, t.owner, t.done)for t in task_tuple] def equivalent(t1, t2):
"""Check two tasks for equivalence"""
return ((t1.summary == t2.summart)and
(t1.owner == t2.owner)and
(t1.done == t2.done)) @pytest.fixture(params=task_tuple, ids=task_ids)
def b_task(request):
return request.param def test_dosomething(tasks_db, b_task)):
task_id = tasks.add(b_task)
t_from_db = tasks.get(task_id)
assert equivalent(t_from_db, b_task)
task_tuple = (Task('sleep',None, False),
Task('wake', 'brain',False),
Task('breathe', 'BRAIN', True),
Task('exercise', 'BrIaN', False)) def id_function(fixture_value):
t = fixture_value
return 'Task({},{},{})'.format(t.summary, t.owner, t.done) def equivalent(t1, t2):
"""Check two tasks for equivalence"""
return ((t1.summary == t2.summart)and
(t1.owner == t2.owner)and
(t1.done == t2.done)) @pytest.fixture(params=task_tuple, ids=id_function)
def c_task(request):
return request.param def test_dosomething(tasks_db, c_task):
task_id = tasks.add(c_task)
t_from_db = tasks.get(task_id)
assert equivalent(t_from_db, c_task)







												

Pytest【定制fixture】的更多相关文章

  1. pytest.4.Fixture

    From: http://www.testclass.net/pytest/fixture/ 我们可以简单的把Fixture理解为准备测试数据和初始化测试对象的阶段. 一般我们对测试数据和测试对象的管 ...

  2. pytest(6)-Fixture(固件)

    什么是固件 Fixture 翻译成中文即是固件的意思.它其实就是一些函数,会在执行测试方法/测试函数之前(或之后)加载运行它们,常见的如接口用例在请求接口前数据库的初始连接,和请求之后关闭数据库的操作 ...

  3. 『德不孤』Pytest框架 — 12、Pytest中Fixture装饰器(二)

    目录 5.addfinalizer关键字 6.带返回值的Fixture 7.Fixture实现参数化 (1)params参数的使用 (2)进阶使用 8.@pytest.mark.usefixtures ...

  4. pytest 15 fixture之autouse=True

    前言 平常写自动化用例会写一些前置的fixture操作,用例需要用到就直接传该函数的参数名称就行了.当用例很多的时候,每次都传这个参数,会比较麻烦.fixture里面有个参数autouse,默认是Fa ...

  5. pytest 5. fixture之yield实现teardown

    前言: 1.前面讲的是在用例前加前置条件,相当于setup,既然有setup那就有teardown,fixture里面的teardown用yield来唤醒teardown的执行 看以下的代码: #!/ ...

  6. pytest 3.fixture介绍一 conftest.py

    前言: 前面一篇pytest2 讲到用例加setup和teardown可以实现在测试用例之前或之后加入一些操作,但这种是整个脚本全局生效的,如果我想实现以下场景: 用例1需要先登录,用例2不需要登录, ...

  7. pytest的fixture和conftest

    解决问题:用例1需要先登录,用例2不需要登录,用例3需要先登录.很显然这就无法用setup和teardown来实现了,这个时候就可以自定义测试用例的预置条件,比setup灵活很多. 1.fixture ...

  8. 【Pytest04】全网最全最新的Pytest框架fixture应用篇(2)

    一.Fixture参数之params参数可实现参数化:(可以为list和tuple,或者字典列表,字典元祖等) 实例如下: import pytest def read_yaml(): '] @pyt ...

  9. 【Pytest03】全网最全最新的Pytest框架fixture应用篇(1)

    fixtrue修饰器标记的方法通常用于在其他函数.模块.类或者整个工程调用时会优先执行,通常会被用于完成预置处理和重复操作.例如:登录,执行SQL等操作. 完整方法如下:fixture(scope=' ...

随机推荐

  1. Navicat安装及使用

    一.安装Navicat 1.下载安装文件:navicat11.0.17_premium_cs_x86.exe(32位) 2.Oracle 的 Instance Client:instantclient ...

  2. selenium3 web自动化测试框架 三:项目实战中PO模型的设计与封装

    po模型设计思想 Page Object 模式主要是将每个页面设计为一个class,其中包含页面中的需要测试的元素(按钮,输入框,标题等),这样在Selenium测试页面中可以通过调取页面类来获取页面 ...

  3. 创建KVM虚拟机

    #此操作是在VMware workstations上面做的,要在开机前 编辑虚拟机设置——>处理器--->虚拟化Intel/VT-x/ept 选项勾选上,如果是在服务器上请在bios界面设 ...

  4. UIPath工具来取得邮件里面的添付文件及邮件内容

    下图是得到Outlook邮件附件的示意图 下面的图是对UIPath的属性的设定.最重要的是两个文件夹要保持一致.

  5. layui监听radio点击事件

    layui.form.on('radio(layui_dataType)', function(data){ console.log(data.elem); //得到radio原始DOM对象 cons ...

  6. 设计模式的好书 -- ongoing

    1 设计模式--可复用面向对象软件的基础  Erich Gamma. Richard Helm  -- 已经下载了/baiduNetDisk   Design Patterns --- Element ...

  7. 原生JS+ CSS3创建loading加载动画;

    效果图: js创建loading show = function(){ //loading dom元素 var Div = document.createElement("div" ...

  8. 【转】利用匿名namespace解决C++中重复定义的问题

    目录 利用匿名namespace解决C++中重复定义的问题 原文:https://blog.csdn.net/pi9nc/article/details/11267031 利用匿名namespace解 ...

  9. [eclipse]UML之AmaterasUML 插件

    软件体系结构分析软件设计模式要求给出相应设计模式源码对应的UML类图,在此之前我安装过一种UML插件,可以自动生成一个源码包对应的UML类图,但是重装过系统,所以软件包括eclipse都重新下载了新的 ...

  10. redis键的迁移操作

    1.redis单个实例内多库间的数据迁移操作 命令名称:move 语法:move key db 功能:将当前数据库的key移动到给定的数据库db当中.如果当前数据库(源数据库)和给定数据库(目标数据库 ...