confest.py
confest.py可以理解成一个专门存放fixture的配置文件。
使用场景:当多个测试用例文件test_*.py
的所有用例都需要使用同一个功能作为前置操作时,可以将其写入confest.py文件实现功能的共享。
注意事项:
- pytest会默认读取conftest.py里面的所有fixture,不需要手动import
- conftest.py 文件名称是固定的,不能改动
- conftest.py只对同一个package下的所有测试用例生效
- 不同目录可以有自己的conftest.py,一个项目中可以有多个conftest.py
一、fixutre优势
- 命名方式灵活,不局限于 setup 和teardown 这几个命名
- conftest.py 配置里可以实现数据共享,不需要 import 就能自动找到fixture
- scope="module" 可以实现多个.py 跨文件共享前置
- scope="session" 可以实现多个.py 跨文件使用一个fixture来完成多个用例
二、fixture函数
@pytest.fixture(scope="function", params=None, autouse=False, ids=None, name=None)
def test():
print("fixture初始化的参数列表")
scope:参数有四种,分别是'session'、'module'、'class'、'function',默认为function。
一个.py文件为一个module,module参数是每个module的所有test只运行一次; class是每个class的所有test只运行一次;function是每个test都运行;
若是多个.py文件共用一个功能时,可以使用session参数。session是每个session只运行一次
autouse:默认:False,需要用例手动调用该fixture;如果是True,所有作用域内的测试用例都会自动调用该fixture
三、Fixture的调用方法
1.函数或类里面方法直接传fixture的函数参数名称
定义fixture跟定义普通函数差不多,唯一区别就是在函数上加个装饰器@pytest.fixture(),fixture命名不要以test开头,跟用例区分开。
fixture是有返回值的,没有返回值默认为None。
用例调用fixture的返回值,直接就是把fixture的函数名称当做变量名称。
2.使用装饰器@pytest.mark.usefixtures()修饰需要运行的用例
import pytest
@pytest.fixture()
def fix_1():
print("fixture--fix1")
@pytest.fixture()
def fix_2():
print("fixture--fix2")
def test1(fix_1):
assert 3 == 3
@pytest.mark.usefixtures("fix_1", "fix_2")
def test2():
print("用例1:调用fixture")
@pytest.mark.usefixtures("fix_1")
@pytest.mark.usefixtures("fix_2")
def test3():
"""
叠加usefixtures:如果一个方法或者一个class用例想要同时调用多个fixture,
可以使用@pytest.mark.usefixture()进行叠加。
注意叠加顺序,先执行的放底层,后执行的放上层。
:return:
"""
print("用例2:叠加userfixture")
if __name__ == '__main__':
pytest.main("-s xxxx.py")
结果如下:
============================= test session starts =============================
collecting ... collected 3 items
xxxx.py::test1 fixture--fix1
PASSED [ 33%]
xxxx.py::test2 fixture--fix1
fixture--fix2
PASSED [ 66%]用例1:调用fixture
xxxx.py::test3 fixture--fix2
fixture--fix1
PASSED [100%]用例2:叠加userfixture
============================== 3 passed in 0.03s ==============================
注意:usefixtures与传fixture区别
如果需要用到return出来的参数,只能使用fixture传参数。
如果不需要用到return出来的参数,两种方式都可以。
3.fixture自动使用autouse=True
当用例很多的时候,每次都传这个参数,会很麻烦。fixture里面有个参数autouse,默认是False没开启的,可以设置为True开启自动使用fixture功能,这样用例就不用每次都去传参了。
import pytest
@pytest.fixture(autouse=True)
def fix_3():
print("====auto===,自动执行该fix_3")
def test4():
print("用例4:执行前自动执行fixture")
if __name__ == '__main__':
pytest.main("-s xxxx.py")
结果如下:
============================= test session starts =============================
collecting ... collected 1 item
xxxx.py::test4 ====auto===,自动执行该fix_3
PASSED [100%]用例4:执行前自动执行fixture
============================== 1 passed in 0.02s ==============================
四、fixture之yield
前面的都是setup的操作,那么现在就来讲下teardown是怎么实现的。
import pytest
@pytest.fixture(scope="session")
def open():
# 会话前置操作setup
print("*****打开浏览器*****")
test = "*****测试变量是否返回*****"
yield test
# 会话后置操作teardown
print("*****关闭浏览器*****")
@pytest.fixture
def login(open):
# 方法级别前置操作setup
print(f"==输入账号,密码先登录{open}==")
name = "==我是账号=="
pwd = "==我是密码=="
age = "==我是年龄=="
# 返回变量
yield name, pwd, age
# 方法级别后置操作teardown
print("==登录成功==")
def test_s1(login):
print("用例1")
# 返回的是一个元组
print(login)
# 分别赋值给不同变量
name, pwd, age = login
print(name, pwd, age)
assert "账号" in name
assert "密码" in pwd
assert "年龄" in age
def test_s2(login):
print("用例2")
print(login)
if __name__ == '__main__':
pytest.main("-s xxxx.py")
结果如下:
============================= test session starts =============================
collecting ... collected 2 items
xxxx.py::test_s1 *****打开浏览器*****
==输入账号,密码先登录*****测试变量是否返回*****==
PASSED [ 50%]用例1
('==我是账号==', '==我是密码==', '==我是年龄==')
==我是账号== ==我是密码== ==我是年龄==
==登录成功==
xxxx.py::test_s2 ==输入账号,密码先登录*****测试变量是否返回*****==
PASSED [100%]用例2
('==我是账号==', '==我是密码==', '==我是年龄==')
==登录成功==
*****关闭浏览器*****
============================== 2 passed in 0.03s ==============================