我需要创建一个使用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
内,但是由于我的固定装置必须放在类中并且只能执行一次,因此我不确定是否可以。
任何帮助将不胜感激。谢谢!
答案 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")
但是根据需要设置的内容,如果要控制每个会话或模块仅发生一次,则需要稍微修改一下方法。