pytest fixture + conftest.py

一、基础信息说明

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

魔法函数 -python内置函数
https://ceshiren.com/t/topic/28401