我基本上是跟着官网去学习fixture,自己先看并学了一遍,为了方便后续查看和记忆,所以将学习笔记记录下来,如果有不对的地方,欢迎大家评论区指出。
下面我们会分别对两种结构的fixture函数进行说明,大家可以根据分析结果分别查看这两种结构,哪一种结构更好
1.使用结构紧凑的fixture函数
1.1介绍
pytest的夹具系统非常强大,但它仍然由计算机运行,因此它无法弄清楚如何安全地拆除我们仍给它的所有东西.如果我们不小心,fxiture函数中出错可能会使我们的测试留下一些东西,这可能导致进一步的问题.
1.2示例代码
文件名: test_demo.py
import pytest
@pytest.fixture
def setup():
# 打开浏览器
print("打开浏览器")
# 获取driver
print("获取driver")
# 登陆
print("登陆")
# 获取用户
print("获取用户")
yield "user"
# 退出用户
print("退出用户")
# 退出登录
print("退出登陆")
# 关闭driver
print("关闭driver")
# 关闭浏览器
print("关闭浏览器")
def test_demo(setup):
print("测试用例")
1.3运行结果
1.4结果分析
可以通过结果看到,咱们上述运行的结果没有问题,但是咱们的fixture函数是不是看起来很紧凑,且也更难阅读,没有一个非常具体描述性的夹具名称,并且没有一个夹具可以轻松重用.
而且还要注重顺序,如果注销的顺序乱了,例如:先关闭了浏览器,在退出登录,那是不是会引发异常呢?
还有一个更重要的问题,如果设置中的任何步骤引发异常,则任何拆解代码都不会执行,当然你可以使用addfinalizer方法而不用yield fixture,但这可能会边得非常复杂且难以维护(并且也不那么紧凑了)
2.使用结构安全的fixture函数
2.1介绍
官方认为最安全和最简单的fixtrue结构要求将fxture限制为每个fixture进进行一个状态更改操作,然后将他们与其拆卸代码捆绑在一起.
状态更改操作可能失败但仍然修改状态的可能性可以忽略不计,因此这些操作中的大多数往往是基于事务的(至少在状态可能被泡在后面的测试级别上).因此,如果我们通过将任何成功的状态更改操作移动到单独的fixtrue函数并将于其他可能失败的状态更改操作分开来确保任何成功的状态更改操作都会执行清理代码,那么我们的测试将可以很好的隔离
2.2示例代码
文件名: test_demo.py
import pytest
@pytest.fixture
def get_user(login):
print("获取用户")
yield "user"
print("退出用户")
@pytest.fixture
def login(get_driver):
print("登陆")
yield
print("退出登录")
@pytest.fixture
def get_chrome():
print("打开浏览器")
yield
print("关闭浏览器")
@pytest.fixture
def get_driver(get_chrome):
print('获取driver')
yield
print('关闭driver')
def test_demo(get_user):
print("测试用例")
2.3运行结果
2.4结果分析
可以看到咱们的运行结果是不受影响的,但是咱们的代码看上去不那么紧凑了,而是各司其职,一眼就能明确那个fixture对应的功能是什么.虽然依赖关系的布局方式会让我们不清楚是先影响给你登陆还是先打开谷歌.但这没关系,因为这些都是原子操作,测试的事件序列仍然是可线性化的.但重要的是,无论那个先运行,如果一个引发异常而另一个没有,则两者都不会留下任何的东西.如果打开获取用户失败了,那么前面执行的chrome,driver,登录都会执行清理代码,而本身用户获取失败就不用退出用户了.
3.总结
通过上面两种方式比对,我们在自动化项目中,尽量运用第二种结构清晰安全可重用的结构,第二种方式每个都拆分开,只修改一个状态,如我们获取chrome和driver,登陆,我们都可以在其他测试中运行,然而第一种方式却只适用于当前测试用例.所以推荐项目中尽量与运行第二种方式,一个fixture只维护一个状态.