首页 > 解决方案 > 带有参数化会话夹具的 Pytest 集合

问题描述


我在理解 pytest 收集夹具和测试以及执行所有操作的顺序时遇到了一些麻烦,特别是传入了 `params=[]` 的 pytest 夹具。

我想分享这个例子,以及我的逻辑。

假设我有 3 个应用程序,App1App2app3,并且对于每个应用程序,我执行 SampleSuite。SampleSuite 有 1 个类作用域夹具,可以让一些随机用户登录。在测试套件中的每个测试之前,有一个函数作用域夹具,它将执行一些导航。
这是通过这个示例test_sample.py和一个基本pytest.ini文件(用于记录)在下面实现的

import logging
import pytest

logger = logging.getLogger(__name__)

@pytest.fixture(scope="session", params=["App1", "App2", "App3"])
def apps_fixture(request):
    """ Sets up some generic app """
    logger.info(f"Setting up for app {request.param}")
    yield
    logger.info(f"Tearing down for app {request.param}")


@pytest.mark.usefixtures("apps_fixture", "testsuite_user_fixture", "testcase_navigation_fixture")
class TestSampleSuite:
    """ Sample Suite """
    @classmethod
    @pytest.fixture(scope="class")
    def testsuite_user_fixture(cls):
        """ fixture executed once for the test suite """
        logger.info("Setting up testsuite_user_fixture to sign a random user in")
        yield
        logger.info("Tearing down testsuite_user_fixture to sign the user out")

    @classmethod
    @pytest.fixture(scope="function")
    def testcase_navigation_fixture(cls):
        """ fixture executed before each test case """
        logger.info("Setting up testcase_navigation_fixture for navigation")
        yield
        logger.info("Tearing down testcase_navigation_fixture")

    def test_sample_1(self):
        """
        A test case
        """
        logger.info("Test3")

现在,当我在上面运行这个测试时,输出的顺序如下......

test_apps.py::TestSampleSuite::test_sample_1[App1] 
--------------------------------- live log setup ----------------------------------
2020-09-01 15:48:59 INFO Setting up for app App1
2020-09-01 15:48:59 INFO Setting up testsuite_user_fixture to sign a random user in
2020-09-01 15:48:59 INFO Setting up testcase_navigation_fixture for navigation
---------------------------------- live log call ----------------------------------
2020-09-01 15:48:59 INFO Test3
PASSED                                                                      [ 33%]
-------------------------------- live log teardown --------------------------------
2020-09-01 15:48:59 INFO Tearing down testcase_navigation_fixture

test_apps.py::TestSampleSuite::test_sample_1[App2] 
--------------------------------- live log setup ----------------------------------
2020-09-01 15:48:59 INFO Tearing down for app App1
2020-09-01 15:48:59 INFO Setting up for app App2
2020-09-01 15:48:59 INFO Setting up testcase_navigation_fixture for navigation
---------------------------------- live log call ----------------------------------
2020-09-01 15:48:59 INFO Test3
PASSED                                                                      [ 66%]
-------------------------------- live log teardown --------------------------------
2020-09-01 15:48:59 INFO Tearing down testcase_navigation_fixture

test_apps.py::TestSampleSuite::test_sample_1[App3] 
--------------------------------- live log setup ----------------------------------
2020-09-01 15:48:59 INFO Tearing down for app App2
2020-09-01 15:48:59 INFO Setting up for app App3
2020-09-01 15:48:59 INFO Setting up testcase_navigation_fixture for navigation
---------------------------------- live log call ----------------------------------
2020-09-01 15:48:59 INFO Test3
PASSED                                                                      [100%]
-------------------------------- live log teardown --------------------------------
2020-09-01 15:48:59 INFO Tearing down testcase_navigation_fixture
2020-09-01 15:48:59 INFO Tearing down testsuite_user_fixture to sign the user out
2020-09-01 15:48:59 INFO Tearing down for app App3

从我在此输出中看到的内容来看,会话范围固定装置apps_fixture会为每个传递的参数(如预期的那样)设置和拆除,但类范围固定装置testsuite_user_fixture仅在整个运行过程中设置和拆除一次。(这对我来说是令人困惑的部分)

我所期待的是,testsuite_user_fixture将为每个传递的参数设置和拆除,因为类的范围比会话小。

至于我的调查,我在 pytest 文档或谷歌周围没有找到太多帮助。我确实发现使用 pytests 会--collect-only分享一些有趣的细节。运行后pytest test_apps.py --collect-only收集的结构看起来像这样......

<Module test_apps.py>
  <Class TestSampleSuite>
      <Function test_sample_1[App1]>
      <Function test_sample_1[App2]>
      <Function test_sample_1[App3]>

这让我对为什么每个参数只设置和拆除一次班级固定装置有一些了解,但我不明白为什么。我试图调试它并了解 pytest 如何收集所有这些,但我迷失在了一堆钩子中。

注意:testsuite_user_fixture如果我在测试运行期间有 2 个或更多类,则工作正常,因为每个类都会在从apps_fixture. 因此,仅在运行 1 个测试类时才会出现问题。

对于传入参数的夹具,我找不到关于 pytest 的优秀文档,所以我希望在这里能找到一些帮助。所以我的问题是......
是否可以根据为会话范围夹具传递的参数运行类范围夹具?

标签: pytest

解决方案


推荐阅读