【问题标题】:Access pytest fixture params with class scope while ordering parametrized tests在订购参数化测试时访问具有类范围的 pytest 夹具参数
【发布时间】:2021-09-29 20:56:20
【问题描述】:

对于我使用 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,然后 火狐也一样。

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")

【问题讨论】:

  • 是的,我可以看到浏览器总共被调用了 4 次。它不应该调用两次吗?一次使用浏览器 = Chrome & 浏览器 = Firefox??
  • 我在 oneTimeSetup1 中添加了 print("the velue of param is " + request.param)。我附上了 CLI 屏幕截图。对于每个测试函数,都会调用一个新的浏览器会话。
  • 好的,我现在可以重现该问题 - 它与 pytest-ordering 有关(我第一次尝试时没有安装它)。它似乎打破了范围。由于我碰巧维护pytest-orderpytest-ordering 的继任者(不再维护),我将为此编写一个错误。现在尝试删除run 标记并检查它是否仍然存在。
  • 谢谢,在删除 @pytest.mark.run 后效果很好。有没有其他方法可以保持测试的顺序。?我希望他们在下一个 pytest-order 版本中解决这个问题。
  • 问题在于这里的参数化测试 - 排序测试会将参数化测试放在一起,而类作用域则相反。我会考虑这个...正如我所写,我维护pytest-order,所以在这种情况下“他们”就是我。我会看看我能做什么,虽然我还不清楚,因为类范围的参数化和排序在这里有些矛盾。

标签: python selenium pytest


【解决方案1】:

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

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

...
    @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的作者。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-24
    • 1970-01-01
    • 2022-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多