pytest - >如何在类下的测试方法中使用fixture返回值

2023-11-22

我有一个返回如下值的装置:

import pytest

@pytest.yield_fixture(scope="module")
def oneTimeSetUp(browser):
    print("Running one time setUp")
    if browser == 'firefox':
        driver = webdriver.Firefox()
        print("Running tests on FF")
    else:
        driver = webdriver.Chrome()
        print("Running tests on chrome")
    yield driver
    print("Running one time tearDown")

该装置从另一个正在读取命令行选项的装置获取浏览器值。

然后我有一个测试类,其中有多个测试方法,并且它们都希望使用相同的返回值驱动程序来进行测试。

import pytest

@pytest.mark.usefixtures("oneTimeSetUp")
class TestClassDemo():

    def test_methodA(self):
        # I would like to use the driver value here
        # How could I do this?
        # Something like this
        self.driver.get("https://www.google.com")
        self.driver.find_element(By.ID, "some id")
        print("Running method A")

    def test_methodB(self):
        print("Running method B")

使用 self.driver 失败并显示错误消息

self = <test_class_demo.TestClassDemo object at 0x102fb6c18>

    def test_methodA(self):
>       self.driver.get("https://www.google.com")
E           AttributeError: 'TestClassDemo' object has no attribute 'driver'

我知道我可以将固定装置作为参数传递给我想要使用它的每个方法,但这不是最好的方法,因为我在每个方法中都需要它,并且应该可以将它传递给类,然后使用它在所有的测试方法中。

使驱动程序对象可供方法使用的最佳方法是什么?

EDIT 1:

按照建议在 conftest.py 中创建了固定装置

@pytest.yield_fixture(scope="class") # <-- note class scope
def oneTimeSetUp(request, browser): # <-- note the additional `request` param
    print("Running one time setUp")
    if browser == 'firefox':
        driver = webdriver.Firefox()
        driver.maximize_window()
        driver.implicitly_wait(3)
        print("Running tests on FF")
    else:
        driver = webdriver.Chrome()
        print("Running tests on chrome")

    ## add `driver` attribute to the class under test -->
    if request.cls is not None:
        request.cls.driver = driver
    ## <--

    yield driver
    print("Running one time tearDown")

我还有一个类,TestClassDemo 中需要该对象,并且我需要将相同的驱动程序实例传递给该类。将其视为 ABC 类

class ABC():

    def __init(self, driver):
        self.driver = driver

    def enterName(self):
        # Do something with driver instance

然后在TestClassDemo中

@pytest.mark.usefixtures("oneTimeSetUp", "setUp")
class TestClassDemo(unittest.TestCase):

    # I need to create an object of class ABC, so that I can use it here
    # abc = ABC(self.driver)

    @pytest.fixture(scope="class", autouse=True)
    def setup(self):
        self.abc = ABC(self.driver)
    # I tried this, but it's not working
    # This error message shows up
    # AttributeError: 'TestClassDemo' object has no attribute 'driver'

    def setup_module(self):
    self.abc = ABC(self.driver)
    # This also does not work
    # Error message ->  AttributeError: 'TestClassDemo' object has no attribute 'abc'


    def test_methodA(self):
        self.driver.get("https://google.com")
        self.abc.enterName("test")
        print("Running method A")

    def test_methodB(self):
        self.abc.enterName("test")
        print("Running method B")

这个 abc 对象也应该可以在其他 test_ 方法中使用。

所有这些类都位于单独的模块中,我的意思是在单独的 .py 文件中。

另请在答案中解释使用收益驱动程序实例的最佳方法是什么。

EDIT 2:

对于这个没有收益的示例,运行 oneTimeTearDown 的最佳方法是什么?我在产量之后运行拆卸步骤

@pytest.fixture(scope="class")
def oneTimeSetUp(request, browser):
    print("Running one time setUp")
    if browser == 'firefox':
        driver = webdriver.Firefox()
        driver.maximize_window()
        driver.implicitly_wait(3)
        print("Running tests on FF")
    else:
        driver = webdriver.Chrome()
        print("Running tests on chrome")

    if request.cls is not None:
        request.cls.driver = driver

我还尝试使用 UnitTest 类,但是当我使用 def setUpClass(cls) 时,我无法使用 test_ 方法中实例化的对象。所以我不知道如何实现这一目标。

我还想从命令行提供像浏览器这样的命令行参数,当我尝试进行单元测试时,我必须在每个类中编写命令行参数。我只想在一个地方提供它们,比如测试套件。所以conftest在这里帮助了我。

我在 stackoverflow 上有一个问题,但没有得到答复。您也可以看一下吗?Python unittest 将参数传递给父测试类

Thanks

Thanks


中概述了一种技术py.text 单元测试集成文档这可能对你有帮助......使用内置request夹具。否则,我不知道如何在不提供命名的固定装置作为方法参数的情况下访问固定装置的返回值。

@pytest.yield_fixture(scope="class") # <-- note class scope
def oneTimeSetUp(request, browser): # <-- note the additional `request` param
    print("Running one time setUp")
    if browser == 'firefox':
        driver = webdriver.Firefox()
        print("Running tests on FF")
    else:
        driver = webdriver.Chrome()
        print("Running tests on chrome")

    ## add `driver` attribute to the class under test -->
    if request.cls is not None:
        request.cls.driver = driver
    ## <--

    yield driver
    print("Running one time tearDown")

现在您可以访问driver作为类属性TestClassDemo,正如您在示例中所看到的那样(即self.driver应该管用)。

需要注意的是,您的灯具必须使用scope='class',否则request对象不会拥有cls属性。

我希望这有帮助!


UPDATE

我还有一个类,TestClassDemo 中需要该对象,并且我需要将相同的驱动程序实例传递给该类。将其视为 ABC 类

如果没有更多上下文,很难知道,但在我看来,你可能可以通过实例化一个ABC实例化对象的同时driver... 在里面oneTimeSetUp夹具。例如 ...

@pytest.yield_fixture(scope="class")
def oneTimeSetUp(request, browser):
    print("Running one time setUp")
    if browser == 'firefox':
        driver = webdriver.Firefox()
        driver.maximize_window()
        driver.implicitly_wait(3)
        print("Running tests on FF")
    else:
        driver = webdriver.Chrome()
        print("Running tests on chrome")

    if request.cls is not None:
        request.cls.driver = driver
        request.cls.abc = ABC(driver) # <-- here

    yield driver
    print("Running one time tearDown")

但是,如果您只需要一个或两个测试类的 ABC 实例,那么您可以在类定义中使用固定装置...

@pytest.mark.usefixtures("oneTimeSetUp", "setUp")
class TestClassDemo(unittest.TestCase):
    @pytest.fixture(autouse=True)
    def build_abc(self, oneTimeSetUp): # <-- note the oneTimeSetup reference here
        self.abc = ABC(self.driver)

    def test_methodA(self):
        self.driver.get("https://google.com")
        self.abc.enterName("test")
        print("Running method A")

    def test_methodB(self):
        self.abc.enterName("test")
        print("Running method B")

我对第二个例子不是特别满意。第三种选择是有另一个yield_fixture,或类似的,它完全独立于oneTimeSetUp并返回一个 ABC 实例,其中驱动程序已包装。

哪种方式最适合您?没有把握。您需要根据您正在处理的内容来决定。

值得后人注意的是,pytest 装置只是糖和一点魔法。如果您发现它们很困难,则根本不需要使用它们。 pytest 很乐意执行普通的unittest 测试用例。


另请在答案中解释使用收益驱动程序实例的最佳方法是什么。

这就是我的想法......

@pytest.fixture(scope="class")
def oneTimeSetUp(request, browser):
    print("Running one time setUp")
    if browser == 'firefox':
        driver = webdriver.Firefox()
        driver.maximize_window()
        driver.implicitly_wait(3)
        print("Running tests on FF")
    else:
        driver = webdriver.Chrome()
        print("Running tests on chrome")

    if request.cls is not None:
        request.cls.driver = driver

...请注意,这不会返回(或产生)驱动程序对象,这意味着将此固定装置作为命名参数提供给函数/方法不再有用,如果所有测试用例都是这样,这应该没问题。编写为类(根据您的示例建议)。

但是,如果您想将夹具用作命名参数,请不要这样做。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pytest - >如何在类下的测试方法中使用fixture返回值 的相关文章

随机推荐