【问题标题】:How to skip a test in pytest *before* fixtures are computed如何在计算 pytest *before* 固定装置之前跳过测试
【发布时间】:2021-02-27 16:23:37
【问题描述】:

我有一个用 pytest 编写的相当大的测试套件,旨在对包括服务器端和客户端之间通信的应用程序执行系统测试。测试有一个巨大的固定装置,它被初始化以包含有关服务器的信息,然后用于创建客户端对象并运行测试。服务器端可能支持不同的特性集,它通过夹具初始化的服务器对象中可能存在或不存在的属性来反映。

现在,与this question 非常相似,如果服务器对象中不存在所需的属性,我需要跳过某些测试。 到目前为止,我们一直在这样做的方式是在测试中添加一个装饰器,它检查属性并在它们不存在时使用pytest.skip

例子:

import functools
import pytest

def skip_if_not_feature(feature):
  def _skip_if_not_feature(func):
    @functools.wraps(func)
    def wrapper(server, *args, **kwargs):
      if not server.supports(feature):
        pytest.skip("Server does not support {}".format(feature))
      return func(server, *args, **kwargs)
    return wrapper
  return _skip_if_not_feature

@skip_if_not_feature("feature_A")
def test_feature_A(server, args...):
  ...

当其中一些测试有更多的夹具时出现问题,其中一些具有相对耗时的设置,并且由于 pytest 的工作方式,跳过它们的装饰器代码运行夹具设置之后,浪费宝贵的时间。

例子:

@skip_if_not_feature("sync_db")
def test_sync_db(server, really_slow_db_fixture, args...):
  ...

我希望通过更快地跳过这些测试来优化测试套件以更快地运行。 我只能想到两种方法:

  1. 重写装饰器不使用服务器夹具,并使其在夹具之前运行
  2. 运行决定跳过测试的代码在服务器夹具的初始化和其余夹具的初始化之间

我无法确定粗体部分是否可行,以及如果可行,该怎么做。我已经针对类似问题浏览了 pytest 文档和 google / stackoverflow 结果,但一无所获。

【问题讨论】:

    标签: python pytest fixtures system-testing


    【解决方案1】:

    您可以在测试中添加带有功能名称的自定义标记,并在需要时在pytest_collection_modifyitems 中添加跳过标记。 在这种情况下,会跳过测试而不先加载固定装置。

    conftest.py

    def pytest_configure(config):
        config.addinivalue_line(
            "markers",
            "feature: mark test with the needed feature"
        )
    
    
    def pytest_collection_modifyitems(config, items):
        for item in items:
            feature_mark = item.get_closest_marker("feature")
            if feature_mark and feature_mark.args:
                feature = feature_mark.args[0]
                if not server.supports(feature):
                    item.add_marker("skip")
    

    test_db.py

    @pytest.mark.feature("sync_db")
    def test_sync_db(server, really_slow_db_fixture, args...):
      ...
    

    【讨论】:

      【解决方案2】:

      当前装饰器的问题是,在装饰器做完之后,模块包含一个测试函数,其中一个或多个参数是特性。这些被 pytest 机制识别为特征,并进行评估。

      一切尽在您的*args

      你可以做的是让你的装饰器在意识到它会跳过这个测试时吐出func(server)而不是func(server,*args, **kwargs)。 这样跳过的函数就不会有其他的fixture,因此它们不会被评估。

      事实上,您甚至可以返回一个更简单的空lambda: None 而不是func,因为它无论如何都不会被测试。

      【讨论】:

        猜你喜欢
        • 2018-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-08
        • 2018-02-10
        相关资源
        最近更新 更多