链接测试并将对象从一个测试传递到另一个测试 [英] Chaining tests and passing an object from one test to another

查看:51
本文介绍了链接测试并将对象从一个测试传递到另一个测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在 pytest 中将一个测试的结果传递给另一个 - 或者更具体地说,在第二个测试中重用第一个测试创建的对象.这就是我目前的做法.

@pytest.fixture(scope="module")def result_holder:返回 []def test_creation(result_holder):对象 = create_object()assert object.status == 'created' # 测试创建是否按预期工作result_holder.append(object.id) # 下一个测试需要这个值# 理想情况下,这个测试应该只在前一个测试成功时运行def test_deletion(result_holder):previous_id = result_holder.pop()object = get_object(previous_id) # 这里我检索了第一次测试中创建的对象object.delete()assert object.status == 'deleted' # 测试是否删除

(在我们继续之前,我知道 py.test 将一项测试的结果传递给另一项 - 但该问题的唯一答案是题外话,问题本身已有 2 年历史)

使用这样的夹具感觉不是很干净......如果第一次测试失败,行为并不清楚(尽管可以通过测试夹具的内容来补救,或者使用类似增量夹具的东西pytest 文档和下面的评论).有没有更好/更规范的方法来做到这一点?

解决方案

为了在测试之间共享数据,您可以使用 pytest 命名空间或缓存.

命名空间

通过命名空间共享数据的示例.通过 conftest.py 中的钩子声明 shared 变量:

# conftest.py导入pytestdef pytest_namespace():返回{'共享':无}

现在在测试中访问并重新定义它:

导入pytestdef test_creation():pytest.shared = '垃圾邮件'断言真def test_deletion():断言 pytest.shared == '垃圾邮件'

缓存

缓存是一个很好的特性,因为它在测试运行之间持久化在磁盘上,所以通常在重用一些长时间运行的任务的结果以节省重复测试运行的时间时很方便,但你也可以用它来共享数据测试之间.缓存对象可通过 config 获得.您可以访问它,即通过 request 夹具:

def test_creation(request):request.config.cache.set('共享', '垃圾邮件')断言真def test_deletion(请求):断言 request.config.cache.get('shared', None) == 'spam'

<块引用>

理想情况下,这个测试应该只在上一个测试成功的情况下运行

有一个插件:pytest-dependency.示例:

导入pytest@pytest.mark.dependency()def test_creation():断言假@pytest.mark.dependency(depends=['test_creation'])def test_deletion():断言真

将产生:

$ pytest -v============================ 测试会话开始 ==============================...收集了 2 件物品test_spam.py::test_creation 失败 [50%]test_spam.py::test_deletion 跳过 [100%]==================================失败==================================________________________________ 测试_创建 ________________________________def test_creation():>断言假E 断言假test_spam.py:5: 断言错误==================== 1 次失败,1 次在 0.09 秒内跳过 ======================

I'm trying to pass the result of one test to another in pytest - or more specifically, reuse an object created by the first test in the second test. This is how I currently do it.

@pytest.fixture(scope="module")
def result_holder:
    return []

def test_creation(result_holder):
    object = create_object()
    assert object.status == 'created' # test that creation works as expected
    result_holder.append(object.id) # I need this value for the next test

# ideally this test should only run if the previous test was successful
def test_deletion(result_holder):
    previous_id = result_holder.pop()
    object = get_object(previous_id) # here I retrieve the object created in the first test
    object.delete()
    assert object.status == 'deleted' # test for deletion

(before we go further, I'm aware of py.test passing results of one test to another - but the single answer on that question is off-topic, and the question itself is 2 years old)

Using fixtures like this doesn't feel super clean... And the behavior is not clear if the first test fails (although that can be remedied by testing for the content of the fixture, or using something like the incremental fixture in the pytest doc and the comments below). Is there a better/more canonical way to do this?

解决方案

For sharing data between tests, you could use the pytest namespace or cache.

Namespace

Example with sharing data via namespace. Declare the shared variable via hook in conftest.py:

# conftest.py

import pytest


def pytest_namespace():
    return {'shared': None}

Now access and redefine it in tests:

import pytest


def test_creation():
    pytest.shared = 'spam'
    assert True


def test_deletion():
    assert pytest.shared == 'spam'

Cache

The cache is a neat feature because it is persisted on disk between test runs, so usually it comes handy when reusing results of some long-running tasks to save time on repeated test runs, but you can also use it for sharing data between tests. The cache object is available via config. You can access it i.e. via request fixture:

def test_creation(request):
    request.config.cache.set('shared', 'spam')
    assert True


def test_deletion(request):
    assert request.config.cache.get('shared', None) == 'spam'

ideally this test should only run if the previous test was successful

There is a plugin for that: pytest-dependency. Example:

import pytest


@pytest.mark.dependency()
def test_creation():
    assert False


@pytest.mark.dependency(depends=['test_creation'])
def test_deletion():
    assert True

will yield:

$ pytest -v
============================= test session starts =============================
...
collected 2 items

test_spam.py::test_creation FAILED                                      [ 50%]
test_spam.py::test_deletion SKIPPED                                     [100%]

================================== FAILURES ===================================
________________________________ test_creation ________________________________

    def test_creation():
>       assert False
E       assert False

test_spam.py:5: AssertionError
===================== 1 failed, 1 skipped in 0.09 seconds =====================

这篇关于链接测试并将对象从一个测试传递到另一个测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆