一、基础信息说明
1.1优势/特点
1.命令灵活:对于setup/teardown可以不起这2个名字
2.数据共享:在conftest.py配置里写方法可以实现数据共享,不需要import导入,可以跨文件共享
3.scope的层次及神奇的yield组合相当于各种setup和teardown
1.2fixture参数
1.autouse
fixture函数自否自动运行 默认False
2.scope
fixture生效范围,有function(默认)、 class、 module、 package(暂不支持)、 session
3.params
fixture函数参数传递,通过方法的参数request来在函数内获取到request.param
@pytest.fixture(params=[["张三","123456"],["李四","666666"]])
def login(request):
print(f"登录信息:{request.param}")
return request.param
4.ids
用例命名,和params数量对应
有具体说明-参考
1.3fixture function参数
只有request(参考1.2fixture参数的第3点params)
request.param 获取fixture通过params传递的参数
request.config 用于读取测试的配置数据
https://developer.aliyun.com/article/1287985
1.4yield
实现setup和teardown操作
yield相当于return,后边的变量/常量即为setup操作的返回值
@pytest.fixture
def fixtute_name():
setup操作
yield 返回值1,返回值2
teardown操作
1.5fixture函数在用例中如何调用
1.直接把fixture函数名作为参数传递给用例方法
@pytest.mark.parametrize(‘fixture函数名’,[value],indirect=True)
def test_function(fixture函数名):
pass
indrect:
一般与pytest的request、fixture组合使用
indrect=True,@pytest.mark.parametrize( argnames,argvalues,indirect=True)里argnames的fixture函数名就不是普通变量,而是作为函数(函数调用)
indrect 参考来源
https://www.cnblogs.com/trystudy/p/17162957.html
https://blog.csdn.net/qq_16782499/article/details/115677233
1.6pytest内置fixture
https://ceshiren.com/t/topic/28344 *
https://ceshiren.com/t/topic/22327
https://www.cnblogs.com/sheehan-dali/p/16294755.html
1.7相互调用
直接把被调用的fixture函数名放入要调用的fixture函数的入参中(两个fixture函数需要保持scope一致)
如下例子里fixture函数cmdopt作为参数传入fixture函数login内,即可使用cmdopt的信息。
pytest.fixture(scope='session')
def cmdopt(request):
return request.config.getoption("--cmdopt")
@pytest.fixture(autouse=True,scope='session')
def login(cmdopt):
print(cmdopt)
1.8 pytest hook函数 钩子函数
https://blog.csdn.net/MA976647776/article/details/130280873
二、应用
更多应用参考: https://ceshiren.com/t/topic/14015
1.共享登录
问题: setup_module不能写在类中(不好实现共享登录),直接写在.py文件里,并且没有session级别的
class TestInnerCustomer:
def setup_module(self):
self.home_page = LoginPage().login('machao341', '2gynz30J')
def test_search_innerCust(self,login):
login.switch_to_InnerCallCust().search_ByContactTel('13707205952')
如上代码setup_module写在类里报错:AttributeError: ‘TestInnerCustomer’ object has no attribute ‘home_page’
解决办法
方式1:登录操作在session级别或者module级别运行
可以使用conftest.py结合fixture函数
conftest.py
import pytest
from page.login_page import LoginPage
@pytest.fixture(autouse=True,scope='session')
def login():
return LoginPage().login('machao341', '2gynz30J')
用例中把fixture函数login作为参数传递到用例函数中
class TestInnerCustomer:
def test_search_innerCust(self,login):
login.switch_to_InnerCallCust().search_ByContactTel('13707205952')
说明:
- 即便多个用例中引用了fixture函数login作为参数,login也只执行了一次(登录一次)——是期待的效果
- fixture函数里return可以使用yeild代替(这样可以写类似teardown的效果方法)
参考
问题
- 同时多个用例(多个.py文件)运行,记得每个用例把整个frame退出掉,因为上一个用例的frame没有退出,那么下一个用例再去找元素会找不到。
方式2:实现多个用户登录
说明:
- 利用@pytest.fixture的参数params(注意这个带s,且值是字典列表)
- fixture函数的参数request,函数内使用 request.param[‘key’]获取到参数params的多组值(注意request的param不带s)
test_user_data = [{'user': 'machao341', 'pwd': '2gynz30J'}, {'user': 'chenyao007', 'pwd': '2gynz30J'}]
@pytest.fixture(autouse=True,scope='session',params=test_user_data)
def login(request):
user = request.param['user']
pwd = request.param['pwd']
yield LoginPage().login(user, pwd)
2.登录不同账号 ——fixture相互调用
如果不同的登录用户需要执行不同用例,那么可以利用mark去标记用例哪个用户可以执行(可在类级别上),再结合fixure函数在命令上传入要登录的用户账号(在结合上述fixture去登录)
conftest.py
# 注册自定义参数 cmdopt 添加到配置对象
def pytest_addoption(parser):
parser.addoption('--cmdopt',action="store",
default='chenyao007',help='my option:The username of the person who will login in ')
# 从配置对象中读取自定义参数值
@pytest.fixture(scope='session')
def cmdopt(request):
return request.config.getoption('--cmdopt')
test_data = { 'machao341': '2gynz30J',
'chenyao007': '2gynz30J'}
@pytest.fixture(autouse=True, scope='session')
def login_tmr(cmdopt):
username = cmdopt
password = test_data[cmdopt]
yield LoginPage().login(username, password) # yield相当于return
说明:因为cmdopt被login调用,所以两个函数需要保持scope一致,否则报错。
用例 test_demo1.py
@pytest.mark.fc
class TestDemo:
# @pytest.mark.fc
def test_fc_show1(self):
print("case show")
# @pytest.mark.cz
def test_fc_show2(self):
print("case show")
用例 test_demo2.py
@pytest.mark.cz
class TestDemo:
# @pytest.mark.fc
def test_cz_show1(self):
print("case show")
# @pytest.mark.cz
def test_cz_show2(self):
print("case show")
此时运行命令,可以实现不同账号登录执行不同的用例
pytest -vs -m=fc test_demo1.py test_demo2.py --cmdopt=machao341
说明:-m的参数与–cmdopt对应,即为这个用户登录,执行这些用例
如果用例中需要使用到登录对象
那么就在用例参数里传入fixture函数login_tmr
class TestFcDifficultTask:
def test_new_fcDiffcultTask(self,login_tmr):
login_tmr.quickly_search(cust_id='1000452249129').entryCustinfo_byID()
alter_text = login_tmr.fc_difficultTask().new_FCdifficultTask()
assert '成功' in alter_text