当前位置: 首页 > 面试题库 >

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

司徒志
2023-03-14
问题内容

我有一个夹具,返回的值是这样的:

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'

我知道我可以将夹具作为参数传递给要使用它的每个方法,但这不是最好的方法,因为我在每个方法中都需要它,应该可以将其传递给类,然后再使用在所有测试方法中

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

编辑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文件中说。

另外,请在答案中说明什么是代替yield driver实例的最佳使用方法。

编辑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_方法中实例化的对象。所以我不知道该怎么实现。

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

我对stackoverflow有疑问,但没有得到回应。您还可以看看吗? Python
unittest将参数传递给父测试类

谢谢

谢谢


问题答案:

py.text
unittest集成文档
中概述了一种技术,该技术可能对您有所帮助…使用内置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")

现在,您可以driverTestClassDemo在示例中一样(即self.driver应该工作)访问中的as class属性。

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

希望对您有所帮助!

更新

我还有一个类,在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很高兴执行香草单元测试TestCases。

另外,请在答案中说明什么是代替yield driver实例的最佳使用方法。

这就是我的想法…

@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

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

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



 类似资料:
  • 我的测试结构是 当我收集测试时,我可以看到下面 由于oneTimeSetup1夹具的范围是类,我不确定为什么每个测试函数都在新的浏览器会话中运行。 我们可以有一个单一的Chrome浏览器会话,将执行我的test_one

  • Java 8,但这是一个通用的单元测试问题,它(很可能)是与语言无关的。 编写JUnit测试的语法很容易,但是决定要编写什么测试以及如何测试主/生产代码是我发现的最大挑战。在阅读单元测试最佳实践时,我一遍又一遍地听到同样的事情: 测试合同 我相信这个想法是,单元测试不应该是脆弱的,如果方法的实现发生变化,它不应该被破坏。该方法应定义输入的协定 - 假设我有以下方法: 所以在这里,我们有一个方法,我

  • 我试图在Java中创建一个方法,它打印fib序列,直到传递给该方法的数字。我的问题是,我需要使用int返回类型来返回序列,而我不能使用递归。

  • 问题内容: 在尝试JUnit时,我尝试如下测试一个简单的私有方法,该方法接收String并确保其中不包含单词’Dummy’。 我知道,可以将测试 与类 放在同一包 中,并将方法的访问修饰符更改为包,但是我想使用反射来学习这一点。 我试图通过反射访问私有方法,但测试失败!它显示以下异常: 基于这个问题的答案,我也正在抓。 JUnit的 问题答案: 我在上面的评论中同意@Stultuske,并将测试重

  • 我有一个类似这样的pytest测试: 现在,作为重构的一部分,我移动了这一行: 放入它自己的夹具中(在conftest.py文件中),因为它在其他地方使用。但是,除了直接导入fixture函数外,是否有其他方法在测试中引用它?我知道funcargs通常是调用fixture的方式,但是在本文中,当我想要调用fixture时,我不在测试函数中。

  • 问题内容: 考虑以下示例(OOP书籍中的典型示例): 我有一Animal堂课,每个人Animal可以有很多朋友。 和子类喜欢Dog,Duck,Mouse等里面加如特定行为bark(),quack()等等。 这是Animal课程: 这是一些带有大量类型转换的代码片段: 有什么办法可以将泛型用于返回类型来摆脱类型转换,所以我可以说 这是一些带有返回类型的初始代码,这些代码作为从未使用过的参数传递给该方

  • 问题内容: 通常,我会写一个在每个方法中都使用pytest固定装置的测试类。这是一个例子。我希望能够避免必须在每种方法的签名中写入灯具名称。不是干的。如何才能做到这一点? 我希望能够通过将灯具作为测试类的属性来访问灯具。在此示例中,我希望将Google固定装置视为TestGoogle的属性。这可能吗? 问题答案: 当然,只需使用自动使用的夹具即可。这是docs中的相关位置。在您的示例中,更改将引入

  • 我有一个返回[异常,字符串]的方法 } 现在我为类B和I存根方法验证编写测试 是否可以以这种方式存根以返回函数的右(......)?