简体   繁体   English

Pytest 在拆卸后断言夹具

[英]Pytest asserting fixture after teardown

I have a test that makes a thing, validates it, deletes the thing and confirms it was deleted.我有一个测试,可以制作一个东西,验证它,删除它并确认它已被删除。

def test_thing():
    thing = Thing()  # Simplified, it actually takes many lines to make a thing

    assert thing.exists

    thing.delete()  # Simplified, it also takes a few lines to delete it

    assert thing.deleted

Next I want to make many more tests that all use the thing, so it's a natural next step to move the thing creation/deletion into a fixture接下来我想做更多的测试来使用这个东西,所以很自然的下一步就是把东西的创建/删除移到一个fixture中

@pytest.fixture
def thing():
    thing = Thing()  # Simplified, it actually takes many lines to make a thing
    yield thing
    thing.delete()  # Simplified, it also takes a few lines to delete it

def test_thing(thing):
    assert thing.exists

def test_thing_again(thing):
    # Do more stuff with thing

...

But now I've lost my assert thing.deleted .但现在我失去了我的assert thing.deleted

I feel like I have a few options here, but none are satisfying.我觉得我在这里有几个选择,但没有一个是令人满意的。

  1. I could assert in the fixture but AFAIK it's bad practice to put assertions in the fixture because if it fails it will result in an ERROR instead of a FAIL .我可以在夹具中断言,但 AFAIK 将断言放入夹具中是不好的做法,因为如果它失败,它将导致ERROR而不是FAIL
  2. I could keep my original test and also create the fixture, but this would result in a lot of duplicated code for creating/deleting the thing.我可以保留我的原始测试并创建夹具,但这会导致创建/删除事物的大量重复代码。
  3. I can't call the fixture directly because I get a Fixture called directly exception so I could move the thing creation out into a generator that is used by both the fixture and the test.我不能直接调用夹具,因为我得到了一个Fixture called directly所以我可以将事物创建移到夹具和测试都使用的生成器中。 This feels clunky though and what happens if my thing fixture needs to use another fixture?但这感觉很笨重,如果我thing夹具需要使用另一个夹具会发生什么?

What is my best option here?我在这里最好的选择是什么? Is there something I haven't thought of?有什么我没有想到的吗?

If you want to test that a "thing" is deleted, make a fixture without teardown, delete it in the test, then assert if it is deleted.如果你想测试一个“东西”是否被删除,制作一个不拆卸的夹具,在测试中删除它,然后断言它是否被删除。

@pytest.fixture
def thing_create():
    # Perform all the creation steps
    thing = Thing()
    ...

    yield thing


def thing_delete(thing):
    # Perform all the deletion steps
    ...
    thing.delete()  


@pytest.fixture
def thing_all(thing_create):
    yield thing_create
    thing_delete(thing_create)


def test_thing(thing_all):
    assert thing_all.exists


def test_thing_again(thing_create):
    thing_delete(thing_create)
    assert thing_create.deleted

How about using the fixture where appropriate (to reduce duplication) but not where your logic only exists once.如何在适当的地方使用夹具(以减少重复),而不是在你的逻辑只存在一次的地方。

@pytest.fixture
def thing():
    thing = Thing()  # Simplified, it actually takes many lines to make a thing
    yield thing
    thing.delete()  # Simplified, it also takes a few lines to delete it

def test_thing(thing):
    assert thing.exists

def test_thing_does_a_thing(thing):
    expected = "expected"
    assert thing.do_thing() == expected

def test_thing_deletes():
    # just don't use the fixture here
    thing = Thing()
    thing.delete()
    assert thing.deleted

Another solution could be to have a single fixture that yields a context manager, so the test can be in full control of invoking it.另一种解决方案可能是拥有一个生成上下文管理器的单一夹具,因此测试可以完全控制调用它。

@pytest.fixture
def gen_thing():

    @contextmanager
    def cm():
        thing = Thing()  # Simplified, it actually takes many lines to make a thing
        try:
            yield thing
        finally:
            thing.delete()  # Simplified, it also takes a few lines to delete it

    yield cm


def test_thing(gen_thing):
    with gen_thing() as thing:
        assert thing.exists
    assert thing.deleted


def test_thing_again(gen_thing):
    with gen_thing() as thing:
        # Do more stuff with thing

Creating the context manager as a closure means it would have the same scope as the fixture too.将上下文管理器创建为闭包意味着它也将具有与夹具相同的 scope。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM