如何将pytest参数化与需要修改的输入一起使用



我看到的大多数例子都显示了一个简单的例子,其中输入/输出可以用一行表示:

@pytest.mark.parametrize("test_input", [1, 2, 3, 4])

我应该如何处理需要一两行修改的参数?例如:

test_input1 = User()
test_input1.name = 'John'
test_input2 = User()
test_input2.phone = '1234567890'
test_input2.address = '123 Main St'
test_input3 = User()
test_input3.initials.middle = 'A'
test_input4 = User()
test_input4.make_super_user()

假设我不能将这些作为构造函数参数传递,所以User(name='John')不是一个选项。

有几种方法可以做到这一点:

  1. 提供设置对象所需的信息,然后在测试函数中进行设置。对于您的特定示例来说,这有点麻烦,在这些示例中,设置不遵循常规模式,但它仍然有效:

    @pytest.mark.parametrize(
    'params', [
    dict(
    name='John',
    ),
    dict(
    phone='1234567890',
    address='123 Main St',
    ),
    dict(
    initials=dict(middle='A'),
    ),
    dict(
    is_super_user=True,
    ),
    ]
    )
    def test_user(params):
    user = User()
    if 'name' in params:
    user.name = params['name']
    if 'phone' in params:
    user.phone = params['phone']
    if 'address' in params:
    user.phone = params['address']
    if 'initials' in params:
    user.initials.middle = params['initials']['middle']
    if params.get('is_super_user')
    user.make_super_user()
    assert ...
    
  2. 使用出厂函数对测试函数进行参数化。这个想法与jonrsharpe在评论中建议的有点不同,因为在这种情况下,您将为每个测试用例编写一个单独的工厂。也就是说,你可以通过写一个";工厂工厂;使用类似于jonrsharpe的代码:

    def make_user_with_name():
    user = User()
    user.name = 'John'
    return user
    def make_user_with_phone_address():
    user = User()
    user.phone = '1234567890'
    user.address = '123 Main St'
    return user
    def make_user_with_middle_initial():
    user = User()
    user.initial.middle = 'A'
    return user
    def make_super_user():
    user = User()
    user.make_super_user()
    return user
    @pytest.mark.parametrize(
    'factory', [
    make_user_with_name,
    make_user_with_phone_address,
    make_user_with_middle_initial,
    make_super_user,
    ]
    )
    def test_user(factory):
    user = factory()
    assert ...
    
  3. 使用exec()从字符串创建对象。当您从一个单独的文件加载参数时,这是一种很好的方法(我强烈建议您这样做;请参阅parameterize_from_file(,尽管为了简单起见,下面的示例只包含了python中的所有内容。注意,每个代码段都需要定义一个名为user:的全局变量

    @pytest.mark.parametrize(
    'snippet', [
    """
    user = User()
    user.name = 'John'
    """,
    """
    user = User()
    user.phone = '1234567890'
    user.address = '123 Main St'
    """,
    """
    user = User()
    user.initials.middle = 'A'
    """,
    """
    user = User()
    user.make_super_user()
    """,
    ]
    )
    def test_user(snippet):
    scope = {}
    exec(snippet, scope)
    user = scope['user']
    assert ...
    

最新更新