类内的pytest固定装置仅执行一次

时间:2018-07-28 03:03:23

标签: python python-3.x pytest

我需要创建一个使用conftest.py中的灯具的类,并且该类中的灯具在每个测试会话中只需要使用一次。

我有两个测试类,它们取决于具有固定装置的此类。

test_app.py中的示例代码:

@pytest.mark.usefixtures("driver_get")
class TestBase:
    @pytest.fixture(scope="module", autouse=True)
    def set_up(self):
        # set up code.
        # web page will load if this fixture is called
        # uses self.driver, where driver was set in driver_get

class TestOne(TestBase):
    def test_1(self):
        # test code
        # uses self.driver also in the test

class TestTwo(TestBase):
    def test_2(self):
        # test code
        # uses self.driver also in the test

conftest.py中的示例代码(跟随https://dzone.com/articles/improve-your-selenium-webdriver-tests-with-pytest):

@pytest.fixture(scope="session")
def driver_get(request):
    from selenium import webdriver
    web_driver = webdriver.Chrome()
    session = request.node
    for item in session.items:
        cls = item.getparent(pytest.Class)
        setattr(cls.obj,"driver",web_driver)
    yield
    web_driver.close()

如您所见,conftest.py将驱动程序设置为类属性,这就是为什么我将driver_get固定装置应用于class TestBase的原因,因为我需要在驱动程序内部使用驱动程序课。

问题是,TestOne完成后,网页将再次加载并执行TestTwo,这意味着夹具set_up被再次执行,这不是我想要的(因为我将set_up范围设置为模块,所以它只能真正发生一次。)

我知道这里有一个类似的问题(py.test method to be executed only once per run),但是询问者没有约束,也不需要TestBase对其应用夹具。

我曾考虑过将固定装置放在conftest.py内,但是由于我的固定装置必须放在类中并且只能执行一次,因此我不确定是否可以。

任何帮助将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:1)

在您的代码中,将在模块set_up解析TestBase固定装置之前调用模块范围的driver_get固定装置。因此,在set_up尝试self.driver会产生AttributeError: object has no attribute 'driver'

在示例代码中解决此问题的一种快速方法是像这样在模块set_up固定装置中引用driver_get固定装置:

class TestBase:
    @pytest.fixture(scope="module", autouse=True)
    def set_up(self, driver_get): # <-------------
        self.driver.get("https://www.yahoo.com")

引用固定装置的另一种方法是仅将固定装置名称包括为argument

我个人并不喜欢您从该博客复制的在请求节点上设置类属性的方法。您会收到有关引用self.driver的IDE警告。对我来说,将驱动程序从driver_get中淘汰出来,然后在测试类中将其设置为固定样式夹具中的self或直接使用它,将更为清楚。类似于下面的内容。

@pytest.fixture(scope="session")
def driver_get():
    from selenium import webdriver
    web_driver = webdriver.Chrome()
    yield web_driver
    web_driver.close()

class TestClass:
    @pytest.fixture(autouse=True)
    def setup(self, driver_get):
        self.driver = driver_get

    def test_something(self):
        self.driver.get("https://www.google.com")

但是根据需要设置的内容,如果要控制每个会话或模块仅发生一次,则需要稍微修改一下方法。