Pytest框架 — 08、Pytest的Fixture(部分前后置)(三)

目录
  • 8、Fixture带返回值
  • 9、Fixture实现参数化
  • 10、可靠的Fixture写法
    • (一)一个不可靠Fixture的例子
    • (二)修改成可靠Fixture的例子

8、Fixture带返回值

fixture
中我们可以使用
yield
或者
return
来返回我们需要的东西,如测试数据,数据库连接对象,文件对象等。

  1. 没有后置处理
    直接采用
    return
    的方式返回数据(
    yield
    也可以)
 import pytest

@pytest.fixture()
def data_fixture():
return ["a", "b", "c"]


def test_case(data_fixture):
print(f"测试数据为:{data_fixture}")

"""
执行结果
fixture/yield_data.py::test_case 测试数据为:['a', 'b', 'c']
PASSED
"""
  1. 有后置处理
  • 使用
    yield
    返回数据,在
    yield
    下面添加后置处理
 import pytest

@pytest.fixture()
def data_fixture():
print("【前置】")
yield ["a", "b", "c"]
print("【后置】")

def test_case(data_fixture):
print(f"测试数据为:{data_fixture}")

"""
执行结果
fixture/yield_data.py::test_case 【前置】
测试数据为:['a', 'b', 'c']
PASSED【后置】
"""
  • 使用
    return
    返回数据,通过
    addfinalizer
    注册后置处理
 import pytest

@pytest.fixture()
def data_fixture(request):
print("【前置】")

def addfinalizer_demo():
print("【后置】")
request.addfinalizer(addfinalizer_demo)
return ["a", "b", "c"]


def test_case(data_fixture):
print(f"测试数据为:{data_fixture}")

"""
执行结果
fixture/return_data.py::test_case 【前置】
测试数据为:['a', 'b', 'c']
PASSED【后置】
"""

9、Fixture实现参数化

可以通过

fixture
params
参数来实现参数化。(有更好的参数化方式,故此方法不常用)
示例1:

 import pytest
data = [("张三","男"), ("李四","女")]


@pytest.fixture(params=data)
def fixture_data(request):
print("【前置】")
def addfinalizer_demo():
print("【后置】")
request.addfinalizer(addfinalizer_demo)
return request.param


def test_case(fixture_data):
print(fixture_data[0], fixture_data[1])


"""
执行结果
fixture/fixture_params.py::test_case[fixture_data0] 【前置】
张三 男
PASSED【后置】

fixture/fixture_params.py::test_case[fixture_data1] 【前置】
李四 女
PASSED【后置】
"""

示例2:通过

ids
参数为每个用例取别名

 import pytest
data = [("张三","男"), ("李四","女")]


@pytest.fixture(params=data,ids=["Developer", "Tester"])
def fixture_data(request):
print("【前置】")
def addfinalizer_demo():
print("【后置】")
request.addfinalizer(addfinalizer_demo)
return request.param


def test_case(fixture_data):
print(fixture_data[0], fixture_data[1])

"""
执行结果
fixture/fixture_params_ids.py::test_case[Developer] 【前置】
张三 男
PASSED【后置】

fixture/fixture_params_ids.py::test_case[Tester] 【前置】
李四 女
PASSED【后置】
"""

总结:

  • 通过
    params
    参数实现参数化需要用到
    request
    关键字,通过
    return request.param
    将测试数据返回。
  • params
    中有多少数据,
    ids
    就必须对应多少参数,脱离使用
    params
    实现参数化,
    ids
    将毫无意义。
  • params
    支持的参数格式:
    • 列表
      []
    • 元祖
      ()
    • 元祖列表
      [(),(),()]
    • 字典列表
      [{},{},{}]
    • 字典元祖
      ({},{},{})

10、可靠的Fixture写法

假如,我们有一个登录页面,需要进行登录测试。为了方便测试,我们还有一个管理员的api,可以直接调用来生成测试用户。那么,这个测试场景通常会这样去构建:

  • 通过管理API创建一个用户
  • 使用Selenium启动浏览器
  • 进入我们网站的登录页面
  • 使用创建好的用户进行登录
  • 断言登录后的用户名出现在登录页的页眉中

(一)一个不可靠Fixture的例子

说明:该例子不可执行,仅做示例

 import pytest
from selenium import webdriver
import AdminApiClent
import LoginPage
import IndexPage
from urllib.parse import urljoin
base_url = "https:xxx.com"
username = "xxx"

@pytest.fixture()
def setup_fixture():
# 【前置处理】
# 1、通过AdminApiClent创建一个用户
client = AdminApiClent()
client.create_user(username)
# 2、获取驱动对象
driver = webdriver.Chrome()
# 3、打开登录页
driver.(urljoin(base_url,"/login"))
# 4、执行登录操作
login_page = LoginPage(driver)
login_page.login(username)
yield username
# 【后置处理】
# 1、关闭浏览器
driver.quit()
# 2、删除用户
client.del_user(username)
# 3、退出AdminApiClent
client.quit()


def test_login_success(setup_fixture):
# 断言登录后用户名是否出现在首页
assert setup_fixture == IndexPage.username

上面例子存在的问题:

  • setup_fixture
    这一个
    fixture
    函数中做的事情太多,很多步骤不容易重用。
  • 假设
    setup_fixture
    yield
    之前出现异常,后置处理不会执行。(虽然可以使用
    addfinalizer
    ,但是不易维护和重用)

(二)修改成可靠Fixture的例子

说明:该例子不可执行,仅做展示

 import pytest
from selenium import webdriver
import AdminApiClent
import LoginPage
import IndexPage
from urllib.parse import urljoin
base_url = "https:xxx.com"
username = "xxx"

# 处理AdminApiClient
@pytest.fixture(name="client")
def AdminApiClient_fixture():
client = AdminApiClent()
yield client
client.quit()

# 处理用户
@pytest.fixture()
def user_fixture(client):
client.create_user(username)
yield username
client.del_user(username)

# 处理驱动
@pytest.fixture()
def driver_fixture():
driver = selenium.Chrome()
yield driver
driver.quit()

# 处理登录
@pytest.fixture()
def login_fixture(driver_fixture, user_fixture):
driver_fixture.get(urljoin(base_url, "/login"))
login_page = LoginPage(driver_fixture)
login_page.login(user_fixture)

# 处理首页
@pytest.fixture()
def index_fixture(driver_fixture):
return IndexPage(driver_fixture)

# 断言
def test_login_success(login_fixture,index_fixture,user_fixture):
assert user_fixture == index_fixture.username

这么改造的优点:

  • 每一步都单独进行了封装,提高了复用性
  • 假设运行中
    user_fixture
    报错了,那么不影响
    driver_fixture
    关闭浏览器
  • 假设运行中
    driver_fixture
    报错了,那么根本就不会执行
    user_fixture

参考
https://www.cnblogs.com/liuyuelinfighting/p/15999810.html
https://zhuanlan.zhihu.com/p/359125816

标签: python

添加新评论