【问题标题】:Pytest Using Parametized Fixture VS. pytest.mark.parametrizePytest 使用参数化夹具 VS。 pytest.mark.parametrize
【发布时间】:2020-02-24 03:06:30
【问题描述】:

我正在使用 Pytest 编写一些单元测试,并遇到了两种参数化测试输入的方法。一种是使用参数化的fixtures,另一种是使用pytest.mark.parametrize 方法。

我的两个例子是:

# method 1
def tokens():
    yield from ["+", "*", "?"]

@pytest.mark.parametrize("token", tokens())
def test_stuff(token):
    assert stuff

# method 2
@pytest.fixture(params=["+", "*", "?"])
def token(request):
    return request.param

def test_stuff(token):
    assert stuff

据我所知,两者都有不同的优点和缺点:

方法一

优势

  • 支持多个参数
  • 支持惰性求值

缺点

  • 更多样板代码用于多种测试方法
  • 需要对使用的每个方法进行显式参数映射,即使参数名称相同

方法2

优势

  • 更少的样板代码

缺点

  • 只允许将单个参数传递给单元测试

我还是 PyTest 的新手,所以也许有一种方法可以解决我上面列出的每种方法的缺点,但考虑到那些我一直很难决定使用哪个方法。我猜想我想要做的事情的预期方法是使用@pytest.mark.parametrize,但是当通过使用夹具仅传递一个具有较少样板代码的单个参数时似乎是一个很大的优势。谁能告诉我不这样做的理由还是这是一个完全有效的用例?

【问题讨论】:

  • 如果您只使用一组数据一次,那么 @pytest.mark.parametrize 应该是一种方法,但是,如果您需要为测试设置和拆卸一些东西或使用相同的数据集多个测试然后使用夹具。您可以在夹具中使用 autouse=True,这将为范围内的所有测试实现夹具,而无需在每个测试中显式调用夹具。

标签: python pytest


【解决方案1】:

正如pk786 在他的评论中提到的那样,您应该使用夹具“......如果您有一些东西要为测试设置和拆卸,或者使用(相同的)数据集进行多个测试,那么请使用夹具”。

例如,您可能想要加载多个数据集,以便在不同的测试函数中进行测试。使用夹具允许您只加载一次这些数据集并在测试函数之间共享它们。您可以使用@pytest.fixtureparams 参数来加载和缓存每个数据集。然后,使用这些夹具的测试函数将针对每个加载的数据集运行。在代码中,这可能类似于:

import json

import pytest


test_files = ["test_file1.json", "test_file2.json"]


@pytest.fixture(params=test_files)
def example_data(request):
    with open(request.param, "r") as f:
        data = json.load(f)
    return data


def test_function1(example_data):
    # run test with example data.
    # this test will be run once for each file in the list `test_files` above.
    ...


def test_function2(example_data):
    # run a different test with example data.
    # this test will be run once for each file in the list `test_files` above.
    # this test takes advantage of automatic caching mechanisms of fixtures...
    # ...so that data is not loaded again.
    ...   

或者,正如pk786 所说,“如果您只使用一组数据一次,那么@pytest.mark.parametrize 应该是方法”。

此语句适用于您提供的示例,因为您没有在需要跨测试共享的夹具中执行任何设置。在这种情况下,即使您在多个测试中使用“令牌”,我也会考虑使用@pytest.mark.parameterize 装饰每个函数,因为我相信这种方法更明确地说明了您的意图,并且对于其他阅读您的代码的人来说更容易理解。这看起来像这样:

...

def tokens():
    yield from ["+", "*", "?"]


@pytest.mark.parametrize("token", tokens())
def test_stuff(token):
    assert stuff


@pytest.mark.parametrize("token", tokens())
def test_other_stuff(token)
    assert other_stuff

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-02
    • 2015-11-23
    • 1970-01-01
    • 1970-01-01
    • 2018-02-24
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多