跟着官方文档理解Fixture用法(二)

Fixture用法4:

一个测试用例/Fixture,可以同时调用多个其他的fixture

Tests and fixtures aren’t limited to requesting a single fixture at a time. They can request as many as they like. Here’s another quick example to demonstrate:

# contents of test_append.py
import pytest

# Arrange
@pytest.fixture
def first_entry():
    return "a"

# Arrange
@pytest.fixture
def second_entry():
    return 2

# Arrange
@pytest.fixture
def order(first_entry, second_entry):
    return [first_entry, second_entry]

# Arrange
@pytest.fixture
def expected_list():
    return ["a", 2, 3.0]

def test_string(order, expected_list):
    # Act
    order.append(3.0)

    # Assert
    assert order == expected_list

Fixture用法5:

每个测试可以请求fixture不止一次(返回值被缓存) Fixtures can be requested more than once per test (return values are cached)

Fixtures can also be requested more than once during the same test, and pytest won’t execute them again for that test. This means we can request fixtures in multiple fixtures that are dependent on them (and even again in the test itself) without those fixtures being executed more than once.

# contents of test_append.py
import pytest

# Arrange
@pytest.fixture
def first_entry():
    return "a"

# Arrange
@pytest.fixture
def order():
    return []

# Act
@pytest.fixture
def append_first(order, first_entry):
    return order.append(first_entry)

def test_string_only(append_first, order, first_entry):
    # Assert
    assert order == [first_entry]

当test_string_only执行,调用append_first这个装饰器时,append_first又依次调用了first_entry和order;他们的执行结果会被缓存下来,当test_string_only分别调用first_entry和order时,就不会再去执行一遍代码,而直接使用缓存的数据

Fixture用法6:

自动使用装饰器(不需要手动去调用)

Autouse fixtures (fixtures you don’t have to request)

# contents of test_append.py
import pytest

@pytest.fixture
def first_entry():
    return "a"

@pytest.fixture
def order(first_entry):
    return []

@pytest.fixture(autouse=True)
def append_first(order, first_entry):
    return order.append(first_entry)

def test_string_only(order, first_entry):
    assert order == [first_entry]

def test_string_and_int(order, first_entry):
    order.append(2)
    assert order == [first_entry, 2]

当有1个或多个fixture,所有的测试用例都依赖他时,可以给这个fixture加上参数 autouse=True,把这个装饰器变为自动使用的装饰器,使所有测试自动请求他们,减少冗余的请求

Fixture用法7:

fixture可以在类、模块、包和会话间共享 Scope: sharing fixtures across classes, modules, packages or session

conftest.py文件中写fixture,该fixture作用域为当前模块

# content of conftest.py
import pytest
import smtplib

@pytest.fixture(scope="module")
def smtp_connection():
    return smtplib.SMTP("smtp.gmail.com", 587, timeout=5)

test_module.py文件中写测试用例

# content of test_module.py

def test_ehlo(smtp_connection):
    response, msg = smtp_connection.ehlo()
    assert response == 250
    assert b"smtp.gmail.com" in msg
    assert 0  # for demo purposes

def test_noop(smtp_connection):
    response, msg = smtp_connection.noop()
    assert response == 250
    assert 0  # for demo purposes

当直接执行pytest test_module.py时,会提示断言失败,缺少smtp_connection返回的数据
所以我们可以把conftest.py中,fixture的scope作用域改为session

fixture支持的作用域如下

function: the default scope, the fixture is destroyed at the end of the test.
函数:默认范围,fixture在测试结束时被销毁。
class: the fixture is destroyed during teardown of the last test in the class.
类:在类中的最后一个测试中销毁fixture
module: the fixture is destroyed during teardown of the last test in the module.
模块:在拆卸模块中的最后一个测试时,fixture被销毁
package: the fixture is destroyed during teardown of the last test in the package.
套件:在拆解包中的最后一个测试时,fixture被破坏
session: the fixture is destroyed at the end of the test session.
会话:在测试会话结束时销毁fixture

注意:

Pytest only caches one instance of a fixture at a time, which means that when using a parametrized fixture, pytest may invoke a fixture more than once in the given scope.
Pytest一次只缓存一个fixture的实例,这意味着在使用参数化fixture时,Pytest可以在给定的范围内多次调用一个fixture

Fixture用法8:

在某些情况下,希望在不更改代码的情况下更改fixture的范围,为此,传递一个可调用对象到scope。可调用对象必须返回一个具有有效作用域的字符串,并且只在fixture定义期间执行一次,使用两个关键字参数进行调用,fixture_name 作为字符串, config 使用配置对象

def determine_scope(fixture_name, config):
    if config.getoption("--keep-containers", None):
        return "session"
    return "function"

@pytest.fixture(scope=determine_scope)
def docker_container():
    yield spawn_container()
posted @ 2021-04-21 14:10  Hei蛋炒饭  阅读(86)  评论(0编辑  收藏  举报