如何在我的测试用例中使用pytest驱动程序实例

时间:2018-08-04 04:26:02

标签: python selenium selenium-webdriver pytest

我正在尝试使用Python,Pytest构建基于硒的自动化框架。 我的意图是通过在conftest.py中对其进行初始化并在所有测试用例中使用它来在类级别创建驱动程序实例,从而使用户无需在每个测试用例中创建驱动程序实例。

conftest.py中的驱动程序实例:

@pytest.fixture(scope="class")
def get_driver(request):
    from selenium import webdriver
    driver = webdriver.Chrome()
    request.cls.driver = driver
    yield
    driver.quit()

BaseTestCase类如下:

@pytest.mark.usefixtures("get_driver")
class BaseTestCase(unittest.TestCase):

    def __init__(self, *args, **kwargs):
        super(BaseTestCase, self).__init__(*args, **kwargs)

    @classmethod
    def setUpClass(cls):
        if hasattr(super(BaseTestCase, cls), "setUpClass"):
            super(BaseTestCase, cls).setUpClass()

我的测试用例如下:

from ..pages.google import Google

class Test_Google_Page(BaseTestCase):

    @classmethod
    def setUpClass(self):
        self.page = Google(self.driver, "https://www.google.com/")

我的页面Google扩展到如下所示的BasePage:

class BasePage(object):
    def __init__(self, driver, url=None, root_element = 'body'):
        super(BasePage, self).__init__()

        self.driver = driver
        self._root_element = root_element
        self.driver.set_script_timeout(script_timeout)

执行测试用例时,出现以下错误:

    @classmethod
    def setUpClass(self):
>       driver = self.driver
E       AttributeError: type object 'Test_Google_Page' has no attribute 'driver'

如何通过简单地调用self.driver使驱动程序实例在我的测试用例中可用?

1 个答案:

答案 0 :(得分:2)

setUpClass类方法之后执行类范围的灯具,因此,当执行Test_Google_Page.setUpClass时,get_driver尚未运行。查看执行顺序:

import unittest
import pytest


@pytest.fixture(scope='class')
def fixture_class_scoped(request):
    print(f'{request.cls.__name__}::fixture_class_scoped()')


@pytest.mark.usefixtures('fixture_class_scoped')
class TestCls(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        print(f'{cls.__name__}::setUpClass()')

    def setUp(self):
        print(f'{self.__class__.__name__}::setUp()')

    @pytest.fixture()
    def fixture_instance_scoped(self):
        print(f'{self.__class__.__name__}::fixture_instance_scoped()')

    @pytest.mark.usefixtures('fixture_instance_scoped')
    def test_bar(self):
        print(f'{self.__class__.__name__}::test_bar()')
        assert True

例如通过pytest -sv,输出结果为:

TestCls::setUpClass()
TestCls::fixture_class_scoped()
TestCls::fixture_instance_scoped()
TestCls::setUp()
TestCls::test_bar()

因此解决方案是将代码从setUpClass移至例如setUp

class Test_Google_Page(BaseTestCase):

    def setUp(self):
        self.page = Google(self.driver, "https://www.google.com/")
  

恐怕我可能不会使用setUp,因为在我的大多数类文件中,我有多个测试用例,并且我只想在setUpClass中进行一次设置,而不是每次调用任何测试方法之前都启动。

然后我将代码从setUpClass移到另一个类范围的灯具:

import pytest

@pytest.mark.usefixtures('get_driver')
@pytest.fixture(scope='class')
def init_google_page(request):
    request.cls.page = Google(request.cls.driver, 
                              "https://www.google.com/")


@pytest.mark.usefixtures('init_google_page')
class Test_Google_Page(BaseTestCase):
    ...

以前的setUpClass现在是init_google_page固定装置,它将在get_driver之后调用(由于pytest.mark.usefixtures('get_driver'))。