Pytest【定制fixture】
在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】的更多相关文章
- pytest.4.Fixture
From: http://www.testclass.net/pytest/fixture/ 我们可以简单的把Fixture理解为准备测试数据和初始化测试对象的阶段. 一般我们对测试数据和测试对象的管 ...
- pytest(6)-Fixture(固件)
什么是固件 Fixture 翻译成中文即是固件的意思.它其实就是一些函数,会在执行测试方法/测试函数之前(或之后)加载运行它们,常见的如接口用例在请求接口前数据库的初始连接,和请求之后关闭数据库的操作 ...
- 『德不孤』Pytest框架 — 12、Pytest中Fixture装饰器(二)
目录 5.addfinalizer关键字 6.带返回值的Fixture 7.Fixture实现参数化 (1)params参数的使用 (2)进阶使用 8.@pytest.mark.usefixtures ...
- pytest 15 fixture之autouse=True
前言 平常写自动化用例会写一些前置的fixture操作,用例需要用到就直接传该函数的参数名称就行了.当用例很多的时候,每次都传这个参数,会比较麻烦.fixture里面有个参数autouse,默认是Fa ...
- pytest 5. fixture之yield实现teardown
前言: 1.前面讲的是在用例前加前置条件,相当于setup,既然有setup那就有teardown,fixture里面的teardown用yield来唤醒teardown的执行 看以下的代码: #!/ ...
- pytest 3.fixture介绍一 conftest.py
前言: 前面一篇pytest2 讲到用例加setup和teardown可以实现在测试用例之前或之后加入一些操作,但这种是整个脚本全局生效的,如果我想实现以下场景: 用例1需要先登录,用例2不需要登录, ...
- pytest的fixture和conftest
解决问题:用例1需要先登录,用例2不需要登录,用例3需要先登录.很显然这就无法用setup和teardown来实现了,这个时候就可以自定义测试用例的预置条件,比setup灵活很多. 1.fixture ...
- 【Pytest04】全网最全最新的Pytest框架fixture应用篇(2)
一.Fixture参数之params参数可实现参数化:(可以为list和tuple,或者字典列表,字典元祖等) 实例如下: import pytest def read_yaml(): '] @pyt ...
- 【Pytest03】全网最全最新的Pytest框架fixture应用篇(1)
fixtrue修饰器标记的方法通常用于在其他函数.模块.类或者整个工程调用时会优先执行,通常会被用于完成预置处理和重复操作.例如:登录,执行SQL等操作. 完整方法如下:fixture(scope=' ...
随机推荐
- fastadmin 后台管理 时间戳字段使用
数据库样式 int 11 后台add.html: <div class="form-group"> <label class="control-labe ...
- mq 探究
一 mq简介(message queue) 消息队列技术是分布式应用间交互信息的一种技术. 消息队列可驻留在内存或磁盘上,队列存储消息直到它们被应用程序读走 通过消息队列,应用程序可独立地执行-它们不 ...
- LC 417. Linked List Cycle II
题目描述 Given a linked list, return the node where the cycle begins. If there is no cycle, return null. ...
- Python反射和内置方法(双下方法)
Python反射和内置方法(双下方法) 一.反射 什么是反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发 ...
- maven 依赖 无法下载到jar包,典型的json-lib包
<dependency> <groupId>net.sf.json-lib</groupId> <artifact ...
- Python3 和 Python2的区别
目录 print Python2.7的print不是一个function Python3里的print是一个function. Unicode Python 2 有 ASCII str() 类型,un ...
- CSS定位以及z-index属性(层叠性)的详解(转)
https://blog.csdn.net/weixin_41342585/article/details/79484879
- web pack备忘
全局安装:npm install webpack -g npm i module_name -S = > npm install module_name --save 写入到 dependenc ...
- 如何在SAP Kyma的控制台里扩展新的UI
方法是创建一个新的resource,类型为ClusterMicroFrontend. 使用命令行kubectl get ClusterMicroFrontend查看这些UI扩展: 最后自定义的UI出现 ...
- 7.生产者消费者 案例 (使用Lock 同步锁 方式,使用Condition完成线程之间的通信)
/* * 生产者消费者 案例 (使用Lock 同步锁 方式,使用Condition完成线程之间的通信) * */ public class TestProductorAndConsumerForLoc ...