草庐IT

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

qishuaiRisen 2023-04-20 原文

目录

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实现参数化

可以通过fixtureparams参数来实现参数化。(有更好的参数化方式,故此方法不常用)
示例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_fixtureyield之前出现异常,后置处理不会执行。(虽然可以使用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

有关Pytest框架 — 08、Pytest的Fixture(部分前后置)(三)的更多相关文章

  1. TimeSformer:抛弃CNN的Transformer视频理解框架 - 2

    Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图

  2. ruby - sinatra 框架的 MVC 模式 - 2

    我想开始使用“Sinatra”框架进行编码,但我找不到该框架的“MVC”模式。是“MVC-Sinatra”模式或框架吗? 最佳答案 您可能想查看Padrino这是一个围绕Sinatra构建的框架,可为您的项目提供更“类似Rails”的感觉,但没有那么多隐藏的魔法。这是使用Sinatra可以做什么的一个很好的例子。虽然如果您需要开始使用这很好,但我个人建议您将它用作学习工具,以对您来说最有意义的方式使用Sinatra构建您自己的应用程序。写一些测试/期望,写一些代码,通过测试-重复:)至于ORM,你还应该结帐Sequel其中(imho

  3. ruby-on-rails - Ruby:如何在 fixture 中配置枚举? - 2

    给定这个类:classUser我想创建一个如下所示的fixture:testuser1:id:1username:sampermission::permission_staff我尝试了多种语法变体,但没有找到有效的方法。结果user.permission为nil或0。我知道enum是最近添加的。这可以做到吗? 最佳答案 根据enumdocs你可以像这样通过类引用可枚举的:User.permissions[:permission_staff]工厂只是ruby​​代码——所以他们应该能够以相同的方式访问值testuser1:id:1us

  4. ruby - 在 ruby​​ 中的字符串前后添加空格? - 2

    我想在随机字符串前后添加一个空格。我试过使用"Random_string".center(1,"")但它不起作用。谢谢 最佳答案 我发现这是最优雅的解决方案:padded_string="#{random_string}"走简单的路没有错。 关于ruby-在ruby​​中的字符串前后添加空格?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/3357897/

  5. ruby - 如何使用部分字符串搜索数组并返回索引? - 2

    我想使用部分字符串搜索数组,然后获取找到该字符串的索引。例如:a=["Thisisline1","Wehaveline2here","andfinallyline3","potato"]a.index("potato")#thisreturns3a.index("Wehave")#thisreturnsnil使用a.grep将返回完整的字符串,使用a.any?将返回正确的true/false语句,但都不会返回匹配的索引找到了,或者至少我不知道该怎么做。我正在编写一段代码,该代码读取文件、查找特定header,然后返回该header的索引,以便它可以将其用作future搜索的偏移量。如果

  6. ruby-on-rails - 如何将数据传递给部分? - 2

    K伙计们,所以我创建了这个赞成/反对的投票脚本(基本上就像stackoverflow上的那个),我试图向其中添加一些Ajax,这样页面就不会在您每次投票时都重新加载。我有两个Controller,一个叫grinder,一个叫votes。(磨床基本都是帖子)所以这是所有研磨机的索引(看起来像这样)这是该页面的代码。Listinggrinders"grinders/grinders")%>这就是我在views/grinders/_grinders.erb中的内容true)do|u|%>grinder.id%>"up"%>'create')%>true)do|d|%>grinder.id%>

  7. ruby-on-rails - 正确了解 Rails 框架的最佳方式是什么? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。我一直在Rails上做两个项目,它们运行良好,但在这个过程中重新发明了轮子,自来水(和热水)和止痛药,正如我随后了解到的那样,这些已经存在于框架中。那么基本上,正确了解框架中所有智能部分的最佳方法是什么,这将节省时间而不是自己构建已经实现的功能?从第1页开始阅读文档?是否有公开所有内容的特定示例应用程序?一个特定的开源项目?所有的rails交通?还是完全

  8. ruby - 自动将院子文档框架添加到现有的 Rails 遗留代码中 - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。关闭4年前。Improvethisquestion我希望能够将模板化的YARD文档样式注释插入到我现有的Rails遗留应用程序中。目前它的评论很少。我想要具有指定参数的类header和方法header(通过从我假定的方法签名中提取)和返回值的占位符。在PHP代码中,我有一些工具可以检查代码并在适当的位置创建插入到代码中的文档header注释。在带有Ducktyping等的Ruby中,我确信诸如@params等类型之类

  9. ruby-on-rails - 将 restclient 与多部分帖子一起使用 - 2

    我将restclient用于多部分表单,以将数据发送到restfulweb服务(它是Panda视频编码服务)。不过,诀窍在于我传递给restclient(Technoweenie分支)的文件来自用户提交的我自己的表单。那么,让我们来看看这个。用户将文件发布到我的Rails应用程序。在我的Controller中,它从params[:file]接收文件。然后我想使用RestClient将params[:file]传递给Panda。我在Panda服务器上遇到的错误如下。我注意到堆栈跟踪中的文件参数也在一个字符串中(我假设Panda将其转换为字符串以获得更好的堆栈跟踪)。~Startedreq

  10. ruby-on-rails - 独立测试 Rails 部分 View - 2

    我在标准rails2.1项目中使用Test/Unit。我希望能够独立于任何特定的Controller/操作来测试分部View。好像ZenTest'sTest::Rails::ViewTestCase会有所帮助,但我无法让它工作,与view_testhttp://www.continuousthinking.com/tags/view_test类似Google出现的大部分内容似乎都已经过时了,所以我猜它并不真正适用于Rails2.1非常感谢任何帮助。谢谢,罗兰 最佳答案 我们正在使用RSpec在我们的Rails2.1项目中,我们可以做

随机推荐