首页 > 解决方案 > 在订购参数化测试时访问具有类范围的 pytest 夹具参数

问题描述

在此处输入图像描述对于我使用 pytest 进行的硒测试,我在 conftest.py 文件中有以下逻辑

    import pytest
    from selenium import webdriver
    from webdriver_manager.chrome import ChromeDriverManager
    from webdriver_manager.firefox import GeckoDriverManager
    
    @pytest.fixture(params=["Chrome","Firefox"],scope='class')
    def oneTimeSetup1(request):
        if request.param == "Chrome":
            driver = webdriver.Chrome(ChromeDriverManager().install())
        if request.param == "Firefox":
            driver = webdriver.Firefox(executable_path=GeckoDriverManager().install())
    
        driver.implicitly_wait(5)
        driver.maximize_window()
        driver.get("https://courses.letskodeit.com/practice")
    
        if request.cls is not None:
            request.cls.driver = driver
        print("the velue of param is " + request.param)

    
        yield driver
        driver.quit()

我的测试结构是

dir tests
--conftest.py
--test_one.py
----TestClassOne
------test_one
------test_two

当我收集测试时,我可以在下面看到

<Package tests>
  <Module test_one.py>
    <Class TestClassOne>
        <Function test_one[Chrome]>
        <Function test_one[Firefox]>
        <Function test_two[Chrome]>
        <Function test_two[Firefox]>

由于 oneTimeSetup1 夹具的范围是类,我不确定为什么每个测试函数都在新的浏览器会话中运行。

我们能否有一个 Chrome 浏览器会话来执行我的 test_one 和 test_two,然后对 firefox 执行相同的操作。

import pytest
from pages.page1 import Page1


@pytest.mark.usefixtures("oneTimeSetup1")
class TestClassOne():

    @pytest.fixture(autouse=True)
    def classObject(self):
        self.page = Page1(self.driver)

    @pytest.mark.run(order=1)
    def test_one(self):
        self.page.methodA()
        print("This is Test One")

    @pytest.mark.run(order=2)
    def test_two(self):
        self.page.methodC()
        print("This is Test Two")

标签: pythonseleniumpytest

解决方案


如评论中所述,问题来自通过pytest-ordering插件进行的排序。这实际上是预期的行为(而不是我最初写的错误),因为测试是明确排序的,并且由于夹具的使用,此排序是在任何初始排序之后完成的。

如果使用带有选项--indulgent-ordering的pytest-orderpytest-ordering的一个分支,不再维护),则有可能更改此行为。这改变了排序的顺序,因此测试首先由插件排序,然后由夹具排序。请注意,在这种情况下,您必须将订单标记从更改为:runorder

...
    @pytest.mark.run(order=2)
    def test_one(self):
        self.page.methodA()
        print("This is Test One")

    @pytest.mark.order(1)
    def test_two(self):
        self.page.methodC()
        print("This is Test Two")

(我更改了顺序以表明该顺序有任何影响)。如果在没有选项的情况下运行它,您将得到(如原始问题所示):

$ python -m pytest --collect-only
<Package tests>
  <Module test_one.py>
    <Class TestClassOne>
        <Function test_two[Chrome]>
        <Function test_two[Firefox]>
        <Function test_one[Chrome]>
        <Function test_one[Firefox]>

使用该--indulgent-ordering选项,您将获得:

$ python -m pytest --collect-only --indulgent-ordering
<Package tests>
  <Module test_one.py>
    <Class TestClassOne>
        <Function test_two[Chrome]>
        <Function test_one[Chrome]>
        <Function test_two[Firefox]>
        <Function test_one[Firefox]>

这使得夹具可以作为类范围的夹具正常工作。

通常,pytest.ini如果您希望它对所有测试都有效,您可以将选项添加到您的:

[pytest]
addopts = --indulgent-ordering

免责声明
我是pytest-order.


推荐阅读