【问题标题】:What is the pythonic/pytest way to use tests tagging/parametrization?使用测试标记/参数化的 pythonic/pytest 方法是什么?
【发布时间】:2020-01-08 23:25:22
【问题描述】:

我的想法是我有一组条件,例如:正数、负数、偶数、奇数。

我有一堆测试,可以在这些条件的组合下运行('positive+even' or 'negative+odd')

但我只想对每个条件的任何值运行一个测试。例如:

正+偶数:

2

负数+奇数

-3

在这个例子中,我想标记测试,所以 pytest 会根据条件自动选择值并且只运行一次测试。

我正在考虑为每个条件创建一个夹具并将所有夹具传递给测试或使用 pytest_generate_tests。

http://doc.pytest.org/en/latest/example/parametrize.html#deferring-the-setup-of-parametrized-resources 这个例子几乎是我想要的,但我不想为每个数据库运行测试,而是希望它运行一次并支持诸如 any('oracle', 'Db2', ' 之类的组合条件mysql') + any('win', 'linux')。

能否请您提供有关执行此操作的更好方法的建议?它应该在复杂的夹具中实现还是使用pytest-tags插件+添加解析/处理conftest.py中的组合还是有其他方式

更新:

例子

@pytest.fixture(scope='function')
def connection(request):
    oracle_dbs = ['db1', 'db2', 'db3_19c']
    mysql_dbs = ['db1', 'db2', 'db3']
    connect = Create_connector(request.tag[0])
    if request.tag[1] == 'oracle':
        if and not request.tag[2]:
            connect.oracle(random.choice(oracle_dbs))
        else:
            connect.oracle(random.choice(db3_19c))
    if request.tag[1] == 'mysql':
        connect.mysql(random.choice(mysql_dbs))
    return connect

@pytest.mark.tag('any_os', 'any_db')
def test_run_any_query(connection):
    pass

@pytest.mark.tag('linux', 'oracle')
def test_run_query_lin_oracle(connection):
    pass

@pytest.mark.tag('linux', 'oracle', '19c')
def test_run_query_lin_oracle(connection):
    pass

解释:

1次测试,它通过标签找到一个合适的环境并只运行一次测试,而不是所有组合

2 测试,它也找到了一个合适的环境(所以它可以是 ubuntu/debian/gentoo/etc 和任何 oracle 版本),但它仍然应该只运行一次。

3测试,它只选择一个满足条件的oracle db并且只运行一次

我可以在 pytest_generate_tests(metafunc) 函数中获取标记或标签吗?

【问题讨论】:

  • 请提供一两个示例函数以及在这种情况下测试的样子,以便我们更好地了解所需的行为
  • 听起来很像hypothesis
  • @aws_apprentice,我已经更新了示例,现在可以理解了吗?

标签: python pytest


【解决方案1】:

您的问题似乎有两个问题:

参数化测试

正如您已经在问题中链接的那样,您可以参数化测试。

例如

import pytest


@pytest.mark.parametrize("db_name,os_name", [
    ("oracle", "win"),
    ("Db2", "linux")
])
def test_db_os_combinations(db_name: str, os_name: str):
    print("\ndb_name={db_name}, os_name={os_name}".format(
        db_name=db_name,
        os_name=os_name
    ))

查找所有“组合”

您可以通过生成参数列表来简单地扩展上述内容。例如

import pytest


@pytest.mark.parametrize("db_name,os_name", [
    (db_name, os_name)
    for db_name in ['oracle', 'Db2', 'mysql']
    for os_name in ['win', 'linux']
])
def test_db_os_combinations(db_name: str, os_name: str):
    print("\ndb_name={db_name}, os_name={os_name}".format(
        db_name=db_name,
        os_name=os_name
    ))

【讨论】:

  • 请查看更新的示例,希望我详细描述。
【解决方案2】:

它已完成如下: test_numbers.py:

import pytest

@pytest.mark.env('EVEN', 'NEGATIVE')
def test_sum(number):
    assert (number < 0) and number % 2 == 0


@pytest.mark.env('ODD', 'POSITIVE')
def test_substraction(number):
    assert (number > 0) and number % 2 == 1

conftest.py:

from _pytest.python import Metafunc
import random
import pytest


def pytest_generate_tests(metafunc: Metafunc):
    if 'number' in metafunc.fixturenames:
        for marker in metafunc.definition.iter_markers():
            if marker.name == 'env':
                number = random.randint(-10, 10) * 2
                if 'ODD' in marker.args:
                    number += 1
                if 'POSITIVE' in marker.args:
                    if number < 0:
                        number *= -1
                if 'NEGATIVE' in marker.args:
                    if number > 0:
                        number *= -1
                metafunc.parametrize('number', [number], indirect=True, scope='function')


@pytest.fixture
def number(request):
    return request.param

【讨论】:

猜你喜欢
  • 2020-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-27
  • 1970-01-01
  • 1970-01-01
  • 2022-11-15
相关资源
最近更新 更多