pytest如何为每个测试参数化配置的一部分?

pytest how to parameterize part of a config to each test?

config.yaml 中的测试用例配置列表。

**config.yaml**

-id: test1
name: joker

-id: test2
name: joker

-id: test3
name: not_joker

-id: test4
name: not_joker

// 测试代码

test_ids, input_data = load(config.yaml)

@pytest.fixture(params=input_data, ids=test_ids
def test_setup(request):
   data=request.param
   yield data

def test_joker_names(test_setup):
   in_data=test_setup
   assert  data[name] == 'joker'

以上代码将读取 config.yaml 并为配置中的每个测试 ID 生成测试设置夹具。但我不希望那样,我只希望前两个测试 name 不是小丑,由测试 test_joker_names 进行测试。我想添加另一个测试来检查 not_joker_names.

有可能吗?

从 Pytest 查看 parametrize feature

您可以运行 对相同的变量使用不同的值进行测试。它像固定装置一样工作。

@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])
def test_eval(test_input, expected):
    assert eval(test_input) == expected

我写了一个名为 Parametrize From File 的包,它可以很容易地从配置文件加载测试参数。我认为这很适合您要尝试做的事情。以下是您将如何使用它:

  1. 重新组织您的配置文件,使顶层是一个将测试名称映射到测试用例列表的字典:
    # test_joker.yml
    test_joker_names:
      - id: test1
        name: joker
    
      - id: test2
        name: joker
    
    test_not_joker_names:
      - id: test3
        name: not_joker
    
      - id: test4
        name: not_joker
    
  2. @parametrize_from_file装饰你的测试函数:
    # test_joker.py
    import parametrize_from_file
    
    @parametrize_from_file
    def test_joker_names(name):
        assert name == 'joker'
    
    @parametrize_from_file
    def test_not_joker_names(name):
        assert name != 'joker'
    
  3. 运行 像往常一样进行 pytest。

一些评论:

  • 在此示例中,每个测试的两个测试用例是多余的,但我假设在您的实际应用程序中,每个测试都有多个不同的测试用例。
  • 这种方法完全摆脱了夹具,我认为这是一件好事。不过,如果您确实需要夹具,从文件参数化 也可以对夹具进行参数化。
  • 配置文件中的id字段被特殊解释。它用作测试用例的名称,而不是作为参数传递给测试。这在文档(上面链接)中有更多描述。
  • 我在此示例中选择了 file/test 名称,以便默认找到参数(即无需指定任何路径)。但如果默认设置不适合您,也可以指定路径。