Pytest - 自定义fixture
目录
基础使用
任意py文件的方法中用@pytest.fixture 进行标记后使用
import pytest
# scope=functiOn 函数级别 - 手动调用
@pytest.fixture(scope='funciton')
def exec_sql():
print("sql run.!!!!!!!")
class TestDemo1:
def test2(self, exec_sql): # 将fixture 函数名称传入用例形参即为手动调用
print("test1 run....")
if __name__ == '__main__':
pytest.main(['-s'])
# out:
'''
============================= test session starts =============================
collecting ... collected 1 item
TestDemo.py::TestDemo1::test2 sql run.!!!!!!!
PASSED [100%]test1 run....
============================== 1 passed in 0.01s ==============================
'''
# scope=function 函数级别 - 自动调用(参数 autouse默认是False )
import pytest
@pytest.fixture(scope='class', autouse=True)
def exec_sql():
print("sql run.!!!!!!!")
class TestDemo1:
def test2(self):
print("test1 run....")
if __name__ == '__main__':
pytest.main(['-s'])
# out:
'''
============================= test session starts =============================
collecting ... collected 1 item
TestDemo.py::TestDemo1::test2 sql run.!!!!!!!
PASSED [100%]test1 run....
============================== 1 passed in 0.01s ==============================
'''
# 类级别 - 借助 yield 实现前后置
import pytest
@pytest.fixture(scope='class', autouse=True)
def exec_sql():
print("sql run.!!!!!!!")
yield
print('close sql collection.!!!!!!!')
class TestDemo1:
def test1(self):
print("test1 run....")
def test2(self):
print("test2 run....")
if __name__ == '__main__':
pytest.main()
#out:
'''
============================= test session starts =============================
collecting ... collected 2 items
TestDemo.py::TestDemo1::test1 sql run.!!!!!!!
PASSED [ 50%]test1 run....
TestDemo.py::TestDemo1::test2 PASSED [100%]test2 run....
close sql collection.!!!!!!!
============================== 2 passed in 0.01s ==============================
'''
测试用例中使用自定义fixture的返回值
import pytest
@pytest.fixture(scope='function')
def exec_sql():
return "fixture 返回的值"
class TestDemo1:
def test1(self,exec_sql):
print("test1 run....")
print(exec_sql) # 打印调用fixture函数的返回值
def test2(self,exec_sql):
print("test2 run....")
print(exec_sql) # 打印调用fixture函数的返回值
if __name__ == '__main__':
pytest.main()
# out:
'''
============================= test session starts =============================
collecting ... collected 2 items
test_demo2.py::TestDemo1::test1 PASSED [ 50%]test1 run....
fixture 返回的值
test_demo2.py::TestDemo1::test2 PASSED [100%]test2 run....
fixture 返回的值
============================== 2 passed in 0.01s ==============================
'''
类级别fixture 手动调用
使用 该方式在测试类上调用 @pytest.mark.usefixtures("")
import pytest
@pytest.fixture(scope='class',autouse=False)
def exec_sql():
print("sql run.!!!!!!!")
yield
print('close sql collection.!!!!!!!')
@pytest.mark.usefixtures("exec_sql")
class TestDemo1:
def test1(self):
print("test1 run....")
def test2(self):
print("test2 run....")
class TestDemo3:
def test1(self):
print("TestDemo3 test1 run..")
if __name__ == '__main__':
pytest.main()
# out:
'''
============================= test session starts =============================
collecting ... collected 3 items
test_demo3.py::TestDemo1::test1 sql run.!!!!!!!
PASSED [ 33%]test1 run....
test_demo3.py::TestDemo1::test2 PASSED [ 66%]test2 run....
close sql collection.!!!!!!!
test_demo3.py::TestDemo3::test1 PASSED [100%]TestDemo3 test1 run..
============================== 3 passed in 0.01s ==============================
Process finished with exit code 0
'''
fixure 中获取params 传入的数据 实现数据驱动
import pytest
def read_data():
'''数据源'''
return ['xiaoming', 'zhangsan', 'wangwu']
@pytest.fixture(scope='function', autouse=False, params=read_data())
def exec_sql(request):
'''
1.params
2.requst: 参数固定写法,不能更改
3.requst.param: 获得传入的参数
'''
print(request.param)
print("sql run.!!!!!!!")
yield
print('close sql collection.!!!!!!!')
class TestDemo1:
def test1(self):
print("test1 run....")
def test2(self, exec_sql):
print("test2 run....")
class TestDemo3:
def test1(self):
print("TestDemo3 test1 run..")
if __name__ == '__main__':
pytest.main()
# out(test2 执行了三次,因为exec_sql 产生了三个值):
============================= test session starts =============================
collecting ... collected 5 items
test_demo4.py::TestDemo1::test1 PASSED [ 20%]test1 run....
test_demo4.py::TestDemo1::test2[xiaoming] xiaoming
sql run.!!!!!!!
PASSED [ 40%]test2 run....
close sql collection.!!!!!!!
test_demo4.py::TestDemo1::test2[zhangsan] zhangsan
sql run.!!!!!!!
PASSED [ 60%]test2 run....
close sql collection.!!!!!!!
test_demo4.py::TestDemo1::test2[wangwu] wangwu
sql run.!!!!!!!
PASSED [ 80%]test2 run....
close sql collection.!!!!!!!
test_demo4.py::TestDemo3::test1 PASSED [100%]TestDemo3 test1 run..
============================== 5 passed in 0.01s ==============================
测试用例中使用 fixture 返回的数据
import pytest
def read_data():
return ['xiaoming', 'zhangsan', 'wangwu']
@pytest.fixture(scope='function', autouse=False, params=read_data())
def exec_sql(request): # requst 参数固定写法,不能更改
print("sql run.!!!!!!!")
yield request.param
print('close sql collection.!!!!!!!')
class TestDemo1:
def test1(self):
print("test1 run....")
def test2(self, exec_sql):
''' 使用fixture 返回的数据'''
print("test2 run...." + exec_sql)
class TestDemo3:
def test1(self):
print("TestDemo3 test1 run..")
if __name__ == '__main__':
pytest.main()
# out:
'''
============================= test session starts =============================
collecting ... collected 5 items
test_demo5.py::TestDemo1::test1 PASSED [ 20%]test1 run....
test_demo5.py::TestDemo1::test2[xiaoming] sql run.!!!!!!!
PASSED [ 40%]test2 run....xiaoming
close sql collection.!!!!!!!
test_demo5.py::TestDemo1::test2[zhangsan] sql run.!!!!!!!
PASSED [ 60%]test2 run....zhangsan
close sql collection.!!!!!!!
test_demo5.py::TestDemo1::test2[wangwu] sql run.!!!!!!!
PASSED [ 80%]test2 run....wangwu
close sql collection.!!!!!!!
test_demo5.py::TestDemo3::test1 PASSED [100%]TestDemo3 test1 run..
============================== 5 passed in 0.02s ==============================
Process finished with exit code 0
'''
ids 与params参数结合使用,给参数起别名
import pytest
def read_data():
return ['xiaoming', 'zhangsan', 'wangwu']
@pytest.fixture(scope='function', autouse=False, params=read_data(), ids=['a', 'b', 'c'])
def exec_sql(request): # requst 参数固定写法,不能更改
print("sql run.!!!!!!!")
yield request.param
print('close sql collection.!!!!!!!')
class TestDemo1:
def test1(self):
print("test1 run....")
def test2(self, exec_sql):
print("test2 run...." + exec_sql)
class TestDemo3:
def test1(self):
print("TestDemo3 test1 run..")
if __name__ == '__main__':
pytest.main()
name 参数 给fixture 起别名
需要注意的是一旦给fixture 起了别名后,原来被@pytest.fixture 标记过的方法名称就失效了
fixture 结合 conftest.py 文件使用
- conftest.py 它是专门用于存放fixture的配置文件。名称是固定的,不能变
- 在conftest.py 文件里面所有的方法在调用时都不需要导包
- conftest.py 文件可以有多个,并且多个conftest.py 文件里面的多个fixture 可以被一个用例调用
- 当用例调用多个fixture时,按方法传入的参数顺序调用
调用的优先级
- fixture 全部是自动调用: fixture的优先级高于setup/teardown/setup_class/teardown_class
- fixture 是手动调用: setup/teardown/setup_class/teardown_class 的优先级高于fixture
fixture 全部是自动调用
# conftest.py
import pytest
@pytest.fixture(scope="session", autouse=True)
def first():
print("全局会话级别的fixture_前置")
yield
print("全局会话级别的fixture_后置")
@pytest.fixture(scope="class", autouse=True)
def second():
print("fixture_class_前置")
yield
print("fixture_class_后置")
@pytest.fixture(scope="function", autouse=True)
def third():
print("fixture_function_前置")
yield
print("fixture_function_后置")
# test_demo7.py
import pytest
class TestDemo1:
def test1(self):
print("test1 run....")
def test2(self):
print("test2 run....")
def setup_class(self):
print("setup_class")
def teardown_class(self):
print("teardown_class")
def setup(self):
print("setup")
def teardown(self):
print("teardown")
if __name__ == '__main__':
pytest.main()
# 执行输出结果:
'''
test_demo7.py::TestDemo1::test1 全局会话级别的fixture_前置
fixture_class_前置
setup_class
fixture_function_前置
setup
PASSED [ 50%]test1 run....
teardown
fixture_function_后置
test_demo7.py::TestDemo1::test2 fixture_function_前置
setup
PASSED [100%]test2 run....
teardown
fixture_function_后置
teardown_class
fixture_class_后置
全局会话级别的fixture_后置
'''
类级别/方法级别 全部是手动调用
# conftest.py
import pytest
@pytest.fixture(scope="session", autouse=True)
def first():
print("全局会话级别的fixture_前置")
yield
print("全局会话级别的fixture_后置")
@pytest.fixture(scope="class", autouse=False)
def second():
print("fixture_class_前置")
yield
print("fixture_class_后置")
@pytest.fixture(scope="function", autouse=False)
def third():
print("fixture_function_前置")
yield
print("fixture_function_后置")
# test_demo7.py
import pytest
@pytest.mark.usefixtures("second")
class TestDemo1:
def test1(self, third):
print("test1 run....")
def test2(self, third):
print("test2 run....")
def setup_class(self):
print("setup_class")
def teardown_class(self):
print("teardown_class")
def setup(self):
print("setup")
def teardown(self):
print("teardown")
if __name__ == '__main__':
pytest.main()
# 输出:
test_demo7.py::TestDemo1::test1 全局会话级别的fixture_前置
setup_class
fixture_class_前置
setup
fixture_function_前置
PASSED [ 50%]test1 run....
fixture_function_后置
teardown
test_demo7.py::TestDemo1::test2 setup
fixture_function_前置
PASSED [100%]test2 run....
fixture_function_后置
teardown
fixture_class_后置
teardown_class
全局会话级别的fixture_后置
总结:pytest执行过程
- 1.查询根目录下的conftest.py文件
- 2.查询根目录下的pytest.ini文件,找到测试用例的位置
- 3.查询测试用例目录下的conftest.py文件
- 4.查询测试用例的py文件中是否有setup,teardown,setup_class,teardown_class
- 5.再根据pytest.ini文件的测试用例规则去查找用例并执行
https://www.cnblogs.com/joker108/p/16795760.html
https://blog.csdn.net/weixin_43563447/article/details/115843308?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-1-115843308-blog-119120349.pc_relevant_3mothn_strategy_and_data_recovery&spm=1001.2101.3001.4242.2&utm_relevant_index=4
本文来自博客园,作者:chuangzhou,转载请注明原文链接:https://www.cnblogs.com/czzz/p/16796426.html